lsh-framework
Version:
A powerful, extensible shell with advanced job management, database persistence, and modern CLI features
241 lines (240 loc) • 11 kB
JavaScript
/**
* ZSH Import Commands
* CLI commands for importing ZSH configurations
*/
import { ShellExecutor } from '../lib/shell-executor.js';
import { ZshImportManager } from '../lib/zsh-import-manager.js';
import * as fs from 'fs';
import * as path from 'path';
import * as os from 'os';
export function registerZshImportCommands(program) {
const zshCommand = program
.command('zsh-import')
.description('Import ZSH configurations (aliases, functions, exports)');
zshCommand
.command('all')
.description('Import all ZSH configurations from .zshrc')
.option('--skip-conflicts', 'Skip items that conflict with existing ones', false)
.option('--rename-conflicts', 'Rename conflicting items with _zsh suffix', false)
.option('--overwrite-conflicts', 'Overwrite existing items', false)
.option('--exclude <patterns...>', 'Exclude items matching patterns (supports wildcards)')
.option('--include <patterns...>', 'Only include items matching patterns')
.option('--no-aliases', 'Skip importing aliases')
.option('--no-exports', 'Skip importing environment variables')
.option('--no-functions', 'Skip importing functions')
.option('--no-options', 'Skip importing ZSH options (setopt/unsetopt)')
.option('--diagnostic-log <path>', 'Path to diagnostic log file')
.action(async (options) => {
const executor = new ShellExecutor();
// Determine conflict resolution strategy
let conflictResolution = 'skip';
if (options.renameConflicts)
conflictResolution = 'rename';
if (options.overwriteConflicts)
conflictResolution = 'overwrite';
const importOptions = {
conflictResolution,
includeAliases: options.aliases !== false,
includeExports: options.exports !== false,
includeFunctions: options.functions !== false,
includeOptions: options.options !== false,
includePlugins: true,
excludePatterns: options.exclude || [],
includePatterns: options.include || [],
diagnosticLog: options.diagnosticLog,
};
const manager = new ZshImportManager(executor, importOptions);
const result = await manager.importZshConfig();
console.log(result.message);
if (result.diagnostics.filter(d => d.status === 'failed').length > 0) {
console.log(`\n⚠️ Some imports failed. Check diagnostic log: ${importOptions.diagnosticLog || '~/.lsh/zsh-import.log'}`);
}
process.exit(result.success ? 0 : 1);
});
zshCommand
.command('aliases')
.description('Import only aliases from .zshrc')
.option('--exclude <patterns...>', 'Exclude aliases matching patterns')
.option('--include <patterns...>', 'Only include aliases matching patterns')
.option('--rename-conflicts', 'Rename conflicting aliases')
.action(async (options) => {
const executor = new ShellExecutor();
const importOptions = {
includeAliases: true,
includeExports: false,
includeFunctions: false,
includeOptions: false,
includePlugins: false,
conflictResolution: options.renameConflicts ? 'rename' : 'skip',
excludePatterns: options.exclude || [],
includePatterns: options.include || [],
};
const manager = new ZshImportManager(executor, importOptions);
const result = await manager.importZshConfig();
console.log(result.message);
process.exit(result.success ? 0 : 1);
});
zshCommand
.command('exports')
.description('Import only environment variables from .zshrc')
.option('--exclude <patterns...>', 'Exclude exports matching patterns')
.option('--include <patterns...>', 'Only include exports matching patterns')
.action(async (options) => {
const executor = new ShellExecutor();
const importOptions = {
includeAliases: false,
includeExports: true,
includeFunctions: false,
includeOptions: false,
includePlugins: false,
excludePatterns: options.exclude || [],
includePatterns: options.include || [],
};
const manager = new ZshImportManager(executor, importOptions);
const result = await manager.importZshConfig();
console.log(result.message);
process.exit(result.success ? 0 : 1);
});
zshCommand
.command('functions')
.description('Import only functions from .zshrc')
.option('--exclude <patterns...>', 'Exclude functions matching patterns')
.option('--include <patterns...>', 'Only include functions matching patterns')
.option('--rename-conflicts', 'Rename conflicting functions')
.action(async (options) => {
const executor = new ShellExecutor();
const importOptions = {
includeAliases: false,
includeExports: false,
includeFunctions: true,
includeOptions: false,
includePlugins: false,
conflictResolution: options.renameConflicts ? 'rename' : 'skip',
excludePatterns: options.exclude || [],
includePatterns: options.include || [],
};
const manager = new ZshImportManager(executor, importOptions);
const result = await manager.importZshConfig();
console.log(result.message);
process.exit(result.success ? 0 : 1);
});
zshCommand
.command('setup-auto-import')
.description('Configure auto-import of ZSH config on LSH startup')
.option('--disable', 'Disable auto-import')
.option('--aliases-only', 'Only auto-import aliases')
.option('--exports-only', 'Only auto-import exports')
.option('--rename-conflicts', 'Auto-rename conflicts')
.action(async (options) => {
const lshrcPath = path.join(os.homedir(), '.lshrc');
if (options.disable) {
// Remove auto-import from .lshrc
if (fs.existsSync(lshrcPath)) {
let content = fs.readFileSync(lshrcPath, 'utf8');
content = content.replace(/# ZSH Auto-Import[\s\S]*?# End ZSH Auto-Import\n*/g, '');
fs.writeFileSync(lshrcPath, content, 'utf8');
console.log('✅ Auto-import disabled');
}
process.exit(0);
return;
}
// Generate auto-import configuration
const importCommand = 'zsh-source';
const options_list = [];
if (options.aliasesOnly) {
options_list.push('--no-exports', '--no-functions', '--no-options');
}
else if (options.exportsOnly) {
options_list.push('--no-aliases', '--no-functions', '--no-options');
}
if (options.renameConflicts) {
options_list.push('--rename-conflicts');
}
const autoImportConfig = `
# ZSH Auto-Import
# Automatically import ZSH configurations on startup
${importCommand}${options_list.length > 0 ? ' ' + options_list.join(' ') : ''}
# End ZSH Auto-Import
`;
// Read or create .lshrc
let lshrcContent = '';
if (fs.existsSync(lshrcPath)) {
lshrcContent = fs.readFileSync(lshrcPath, 'utf8');
// Remove existing auto-import config
lshrcContent = lshrcContent.replace(/# ZSH Auto-Import[\s\S]*?# End ZSH Auto-Import\n*/g, '');
}
// Append new auto-import config
lshrcContent += autoImportConfig;
fs.writeFileSync(lshrcPath, lshrcContent, 'utf8');
console.log('✅ Auto-import configured in ~/.lshrc');
console.log(` ZSH config will be imported automatically on LSH startup`);
console.log(`\nConfiguration added:`);
console.log(autoImportConfig.trim());
process.exit(0);
});
zshCommand
.command('status')
.description('Show ZSH import status and diagnostics')
.action(async () => {
const executor = new ShellExecutor();
const manager = new ZshImportManager(executor);
const stats = manager.getLastImportStats();
if (!stats) {
console.log('No ZSH import has been performed yet.');
console.log('\nRun one of these commands to import:');
console.log(' lsh zsh-import all # Import everything');
console.log(' lsh zsh-import aliases # Import only aliases');
console.log(' lsh zsh-import exports # Import only exports');
console.log(' lsh zsh-import functions # Import only functions');
process.exit(0);
return;
}
console.log('📊 Last ZSH Import Status:\n');
console.log(` Total Items: ${stats.total}`);
console.log(` ✅ Succeeded: ${stats.succeeded}`);
console.log(` ❌ Failed: ${stats.failed}`);
console.log(` ⏭️ Skipped: ${stats.skipped}`);
console.log(` ⚠️ Conflicts: ${stats.conflicts}\n`);
if (stats.byType) {
console.log('By Type:');
for (const [type, typeStats] of Object.entries(stats.byType)) {
const ts = typeStats;
console.log(` ${type.padEnd(12)}: ${ts.succeeded}/${ts.total} succeeded, ${ts.failed} failed, ${ts.skipped} skipped`);
}
}
const diagnosticLog = path.join(os.homedir(), '.lsh', 'zsh-import.log');
if (fs.existsSync(diagnosticLog)) {
console.log(`\nDiagnostic log: ${diagnosticLog}`);
console.log('Run: cat ' + diagnosticLog + ' | tail -50');
}
process.exit(0);
});
zshCommand
.command('diagnose')
.description('Show failed imports from diagnostic log')
.option('-n <number>', 'Number of recent entries to show', '20')
.action((options) => {
const diagnosticLog = path.join(os.homedir(), '.lsh', 'zsh-import.log');
if (!fs.existsSync(diagnosticLog)) {
console.log('No diagnostic log found.');
console.log('Import ZSH config first: lsh zsh-import all');
process.exit(1);
return;
}
const content = fs.readFileSync(diagnosticLog, 'utf8');
const lines = content.trim().split('\n');
const numLines = parseInt(options.n, 10) || 20;
const recentLines = lines.slice(-numLines);
console.log(`📋 Recent ZSH Import Diagnostics (last ${numLines} entries):\n`);
const failedLines = recentLines.filter(line => line.includes('failed') || line.includes('disabled'));
if (failedLines.length === 0) {
console.log('✅ No failed imports found!');
}
else {
failedLines.forEach(line => {
console.log(' ' + line);
});
}
process.exit(0);
});
}