This commit is contained in:
226
src/index.ts
Normal file
226
src/index.ts
Normal file
@@ -0,0 +1,226 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { Command } from 'commander';
|
||||
import { fileUtils } from './utils/fileUtils';
|
||||
import {
|
||||
saveLayout,
|
||||
restoreLayout,
|
||||
listLayouts,
|
||||
importLayout,
|
||||
exportLayout,
|
||||
syncLayouts,
|
||||
manageTemplates,
|
||||
deleteLayout,
|
||||
} from './commands';
|
||||
|
||||
const program = new Command();
|
||||
|
||||
program.name('terminal-layout-sync').description('CLI tool for saving, restoring, and syncing terminal workspace layouts').version('1.0.0');
|
||||
|
||||
program.hook('preAction', async () => {
|
||||
await fileUtils.initialize().catch(() => {});
|
||||
});
|
||||
|
||||
program
|
||||
.command('save')
|
||||
.description('Save current terminal layout to a config file')
|
||||
.alias('s')
|
||||
.option('-n, --name <name>', 'Layout name')
|
||||
.option('-t, --terminal <type>', 'Terminal type (tmux, screen, iterm2)')
|
||||
.option('-s, --session <name>', 'Session name to capture')
|
||||
.option('-f, --format <format>', 'Output format (json, yaml)', 'json')
|
||||
.option('-d, --description <desc>', 'Layout description')
|
||||
.option('--tags <tags>', 'Tags (comma-separated)')
|
||||
.action(async (options) => {
|
||||
try {
|
||||
await saveLayout({
|
||||
name: options.name,
|
||||
terminal: options.terminal as 'tmux' | 'screen' | 'iterm2' | 'unknown',
|
||||
session: options.session,
|
||||
format: options.format,
|
||||
description: options.description,
|
||||
tags: options.tags?.split(',').map((t: string) => t.trim()),
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error saving layout:', (error as Error).message);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
program
|
||||
.command('restore')
|
||||
.description('Restore a saved layout to a terminal session')
|
||||
.alias('r')
|
||||
.argument('[name]', 'Layout name')
|
||||
.option('-s, --session <name>', 'Session name to restore to')
|
||||
.option('-a, --attach', 'Show attach command after restore')
|
||||
.option('--dry-run', 'Show commands without executing')
|
||||
.action(async (name, options) => {
|
||||
try {
|
||||
await restoreLayout({
|
||||
name,
|
||||
session: options.session,
|
||||
attach: options.attach,
|
||||
dryRun: options.dryRun,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error restoring layout:', (error as Error).message);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
program
|
||||
.command('list')
|
||||
.description('List all saved layouts')
|
||||
.alias('ls')
|
||||
.option('-f, --format <format>', 'Output format (table, json)', 'table')
|
||||
.option('-v, --verbose', 'Show verbose output')
|
||||
.action(async (options) => {
|
||||
try {
|
||||
await listLayouts({
|
||||
format: options.format,
|
||||
verbose: options.verbose,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error listing layouts:', (error as Error).message);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
program
|
||||
.command('import')
|
||||
.description('Import a layout from an external file')
|
||||
.alias('i')
|
||||
.argument('<file>', 'File to import')
|
||||
.option('-n, --name <name>', 'Layout name after import')
|
||||
.action(async (file, options) => {
|
||||
try {
|
||||
await importLayout({
|
||||
file,
|
||||
name: options.name,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error importing layout:', (error as Error).message);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
program
|
||||
.command('export')
|
||||
.description('Export a layout to an external file')
|
||||
.alias('e')
|
||||
.argument('[name]', 'Layout name to export')
|
||||
.option('-o, --output <path>', 'Output file path')
|
||||
.option('-f, --format <format>', 'Output format (json, yaml)')
|
||||
.action(async (name, options) => {
|
||||
try {
|
||||
await exportLayout({
|
||||
name,
|
||||
output: options.output,
|
||||
format: options.format,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error exporting layout:', (error as Error).message);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
program
|
||||
.command('delete')
|
||||
.description('Delete a saved layout')
|
||||
.alias('rm')
|
||||
.argument('[name]', 'Layout name to delete')
|
||||
.option('-f, --force', 'Skip confirmation')
|
||||
.action(async (name, options) => {
|
||||
try {
|
||||
await deleteLayout({
|
||||
name,
|
||||
force: options.force,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error deleting layout:', (error as Error).message);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
program
|
||||
.command('sync')
|
||||
.description('Sync layouts with git repository')
|
||||
.option('--init', 'Initialize git repository')
|
||||
.option('--remote <url>', 'Remote repository URL')
|
||||
.option('--branch <name>', 'Branch name', 'main')
|
||||
.option('--push', 'Push changes to remote')
|
||||
.option('--pull', 'Pull changes from remote')
|
||||
.option('-m, --message <msg>', 'Commit message')
|
||||
.action(async (options) => {
|
||||
try {
|
||||
await syncLayouts({
|
||||
init: options.init,
|
||||
remote: options.remote,
|
||||
branch: options.branch,
|
||||
push: options.push,
|
||||
pull: options.pull,
|
||||
message: options.message,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error syncing layouts:', (error as Error).message);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
program
|
||||
.command('template')
|
||||
.description('Manage layout templates')
|
||||
.alias('tpl')
|
||||
.option('--list', 'List all templates')
|
||||
.option('--create', 'Create a new template')
|
||||
.option('--delete <name>', 'Delete a template')
|
||||
.option('--apply <name>', 'Apply a template')
|
||||
.option('--var <values>', 'Template variables (key=value)')
|
||||
.action(async (options) => {
|
||||
try {
|
||||
const variables: Record<string, string> = {};
|
||||
if (options.var) {
|
||||
for (const v of options.var) {
|
||||
const [key, value] = v.split('=');
|
||||
if (key && value) {
|
||||
variables[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await manageTemplates({
|
||||
name: options.delete || options.apply,
|
||||
list: options.list,
|
||||
create: options.create,
|
||||
delete: !!options.delete,
|
||||
apply: options.apply,
|
||||
variables,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error managing templates:', (error as Error).message);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
program
|
||||
.command('info')
|
||||
.description('Show information about the CLI')
|
||||
.action(async () => {
|
||||
console.log('Terminal Layout Sync CLI');
|
||||
console.log('Version: 1.0.0');
|
||||
console.log('');
|
||||
console.log('Commands:');
|
||||
console.log(' save - Save current terminal layout');
|
||||
console.log(' restore - Restore a saved layout');
|
||||
console.log(' list - List all saved layouts');
|
||||
console.log(' import - Import layout from file');
|
||||
console.log(' export - Export layout to file');
|
||||
console.log(' delete - Delete a layout');
|
||||
console.log(' sync - Sync with git repository');
|
||||
console.log(' template - Manage templates');
|
||||
console.log('');
|
||||
console.log('For more information, use: terminal-layout-sync <command> --help');
|
||||
});
|
||||
|
||||
program.parse();
|
||||
Reference in New Issue
Block a user