Initial upload with CI/CD workflow
Some checks failed
CI / test (push) Has been cancelled

This commit is contained in:
2026-02-05 19:31:55 +00:00
parent 241486619b
commit 8a1c87a3d1

149
src/parsers/screenParser.ts Normal file
View 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();