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:36 +00:00
parent e70844b9c6
commit 3175e2ab1d

150
src/commands/save.ts Normal file
View File

@@ -0,0 +1,150 @@
import inquirer from 'inquirer';
import { fileUtils } from '../utils/fileUtils';
import { tmuxParser, screenParser, iterm2Parser } from '../parsers';
import { Layout, TerminalType } from '../models/types';
interface SaveOptions {
name?: string;
terminal?: TerminalType;
session?: string;
format?: 'json' | 'yaml';
description?: string;
tags?: string[];
}
export async function saveLayout(options: SaveOptions): Promise<void> {
await fileUtils.initialize();
let terminalType = options.terminal;
if (!terminalType) {
const availableTerminals = await detectAvailableTerminals();
if (availableTerminals.length === 0) {
console.log('No supported terminal multiplexers found. Creating a manual layout.');
terminalType = 'unknown';
} else {
const { selectedTerminal } = await inquirer.prompt([
{
type: 'list',
name: 'selectedTerminal',
message: 'Which terminal type would you like to save?',
choices: availableTerminals.map((t) => ({ name: t, value: t })),
},
]);
terminalType = selectedTerminal;
}
}
let layout: Layout;
switch (terminalType) {
case 'tmux': {
const sessionName = options.session || (await getDefaultSessionName('tmux'));
const result = await tmuxParser.captureSession(sessionName);
if (!result.success) {
throw new Error(`Failed to capture tmux session: ${result.error}`);
}
layout = result.data!;
break;
}
case 'screen': {
const sessionName = options.session || (await getDefaultSessionName('screen'));
const result = await screenParser.captureSession(sessionName);
if (!result.success) {
throw new Error(`Failed to capture screen session: ${result.error}`);
}
layout = result.data!;
break;
}
case 'iterm2': {
const result = await iterm2Parser.captureCurrentLayout();
if (!result.success) {
throw new Error(`Failed to capture iTerm2 layout: ${result.error}`);
}
layout = result.data!;
break;
}
default:
layout = createEmptyLayout('unknown');
}
let layoutName = options.name;
if (!layoutName) {
const { name } = await inquirer.prompt([
{
type: 'input',
name: 'name',
message: 'Enter a name for this layout:',
validate: (input: string) => input.trim() !== '' || 'Name cannot be empty',
},
]);
layoutName = name;
}
layout.metadata = layout.metadata || {};
if (options.description) {
layout.metadata.description = options.description;
} else {
const { description } = await inquirer.prompt([
{
type: 'input',
name: 'description',
message: 'Enter a description (optional):',
default: '',
},
]);
if (description) {
layout.metadata.description = description;
}
}
const finalName = layoutName || 'untitled-layout';
const format = options.format || 'json';
const filePath = await fileUtils.saveLayout(finalName, layout, format);
console.log(`Layout saved to: ${filePath}`);
}
async function detectAvailableTerminals(): Promise<TerminalType[]> {
const terminals: TerminalType[] = [];
const [tmuxAvailable, screenAvailable, iterm2Available] = await Promise.all([
tmuxParser.isAvailable(),
screenParser.isAvailable(),
iterm2Parser.isAvailable(),
]);
if (tmuxAvailable) terminals.push('tmux');
if (screenAvailable) terminals.push('screen');
if (iterm2Available) terminals.push('iterm2');
return terminals;
}
async function getDefaultSessionName(terminal: string): Promise<string | undefined> {
if (terminal === 'tmux') {
const sessions = await tmuxParser.listSessions();
if (sessions.length === 0) {
console.log('No tmux sessions found. Please specify a session name.');
return undefined;
}
return sessions[0];
}
return undefined;
}
function createEmptyLayout(terminalType: TerminalType): Layout {
return {
version: '1.0.0',
terminalType,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
session: {
id: 's-manual',
name: 'manual',
windows: [],
activeWindowIndex: 0,
},
metadata: {
description: 'Manually created layout',
},
};
}