This commit is contained in:
149
src/parsers/screenParser.ts
Normal file
149
src/parsers/screenParser.ts
Normal file
@@ -0,0 +1,149 @@
|
||||
import { shellUtils } from '../utils/shellUtils';
|
||||
import { Layout, Session, Window, Pane, ParserResult, TerminalType } from '../models/types';
|
||||
|
||||
interface ScreenWindowInfo {
|
||||
number: number;
|
||||
title: string;
|
||||
layout?: string;
|
||||
}
|
||||
|
||||
interface ScreenSessionInfo {
|
||||
session_name: string;
|
||||
windows: ScreenWindowInfo[];
|
||||
}
|
||||
|
||||
export class ScreenParser {
|
||||
async isAvailable(): Promise<boolean> {
|
||||
return shellUtils.isCommandAvailable('screen');
|
||||
}
|
||||
|
||||
async listSessions(): Promise<string[]> {
|
||||
const result = await shellUtils.exec('screen -ls | grep -o "[0-9]*\\.[^[:space:]]*"');
|
||||
if (!result.success) {
|
||||
return [];
|
||||
}
|
||||
return result.stdout.split('\n').filter(Boolean);
|
||||
}
|
||||
|
||||
async captureSession(sessionName?: string): Promise<ParserResult<Layout>> {
|
||||
try {
|
||||
const sessions = await this.listSessions();
|
||||
if (sessions.length === 0) {
|
||||
return { success: false, error: 'No screen sessions found' };
|
||||
}
|
||||
|
||||
const targetSession = sessionName || sessions[0];
|
||||
const sessionInfo = await this.getSessionInfo(targetSession);
|
||||
|
||||
if (!sessionInfo) {
|
||||
return { success: false, error: `Failed to capture session: ${targetSession}` };
|
||||
}
|
||||
|
||||
const layout = this.convertToLayout(sessionInfo);
|
||||
return { success: true, data: layout };
|
||||
} catch (error) {
|
||||
return { success: false, error: (error as Error).message };
|
||||
}
|
||||
}
|
||||
|
||||
private async getSessionInfo(sessionName: string): Promise<ScreenSessionInfo | null> {
|
||||
const result = await shellUtils.exec(`screen -S "${sessionName}" -Q windows`);
|
||||
if (!result.success) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const windows: ScreenWindowInfo[] = [];
|
||||
const lines = result.stdout.split('\n');
|
||||
|
||||
for (const line of lines) {
|
||||
const match = line.match(/(\d+)\s+(\*)?(.+)/);
|
||||
if (match) {
|
||||
windows.push({
|
||||
number: parseInt(match[1], 10),
|
||||
title: match[3].trim(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
session_name: sessionName,
|
||||
windows,
|
||||
};
|
||||
}
|
||||
|
||||
private convertToLayout(sessionInfo: ScreenSessionInfo): Layout {
|
||||
const windows: Window[] = sessionInfo.windows.map((w) => {
|
||||
const panes: Pane[] = [
|
||||
{
|
||||
id: 'p0',
|
||||
index: 0,
|
||||
layout: { x: 0, y: 0, width: 80, height: 24 },
|
||||
},
|
||||
];
|
||||
|
||||
return {
|
||||
id: `w${w.number}`,
|
||||
index: w.number,
|
||||
name: w.title || `window-${w.number}`,
|
||||
panes,
|
||||
};
|
||||
});
|
||||
|
||||
const session: Session = {
|
||||
id: `s-${sessionInfo.session_name}`,
|
||||
name: sessionInfo.session_name,
|
||||
windows,
|
||||
activeWindowIndex: 0,
|
||||
};
|
||||
|
||||
return {
|
||||
version: '1.0.0',
|
||||
terminalType: 'screen' as TerminalType,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
session,
|
||||
metadata: {
|
||||
description: `Captured screen session: ${sessionInfo.session_name}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async generateRestoreCommands(layout: Layout, sessionName?: string): Promise<string[]> {
|
||||
const commands: string[] = [];
|
||||
const targetSession = sessionName || layout.session.name;
|
||||
|
||||
commands.push(`screen -dmS "${targetSession}"`);
|
||||
|
||||
for (let i = 0; i < layout.session.windows.length; i++) {
|
||||
const window = layout.session.windows[i];
|
||||
|
||||
if (i === 0) {
|
||||
commands.push(`screen -S "${targetSession}" -X title "${window.name}"`);
|
||||
} else {
|
||||
commands.push(`screen -S "${targetSession}" -X screen ${window.index}`);
|
||||
commands.push(`screen -S "${targetSession}" -X title "${window.name}"`);
|
||||
}
|
||||
}
|
||||
|
||||
return commands;
|
||||
}
|
||||
|
||||
async restoreLayout(layout: Layout, sessionName?: string): Promise<ParserResult<void>> {
|
||||
try {
|
||||
const commands = await this.generateRestoreCommands(layout, sessionName);
|
||||
|
||||
for (const command of commands) {
|
||||
const result = await shellUtils.exec(command);
|
||||
if (!result.success) {
|
||||
return { success: false, error: `Failed to execute: ${command}\n${result.stderr}` };
|
||||
}
|
||||
}
|
||||
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
return { success: false, error: (error as Error).message };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const screenParser = new ScreenParser();
|
||||
Reference in New Issue
Block a user