Add generators: code, completion, and docs generators
This commit is contained in:
89
src/generators/completion-generator.ts
Normal file
89
src/generators/completion-generator.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import Handlebars from 'handlebars';
|
||||
import type { CLISpec, ShellType } from '../types/spec.js';
|
||||
|
||||
const TEMPLATE_DIR = path.resolve(process.cwd(), 'src', 'templates');
|
||||
|
||||
function getTemplatePath(shell: ShellType): string {
|
||||
return path.join(TEMPLATE_DIR, `completion-${shell}.handlebars`);
|
||||
}
|
||||
|
||||
function getTemplateContent(shell: ShellType): string {
|
||||
const templatePath = getTemplatePath(shell);
|
||||
if (!fs.existsSync(templatePath)) {
|
||||
throw new Error(`Completion template not found: ${templatePath}`);
|
||||
}
|
||||
return fs.readFileSync(templatePath, 'utf-8');
|
||||
}
|
||||
|
||||
function compileTemplate(content: string): Handlebars.TemplateDelegate {
|
||||
Handlebars.registerHelper('escape', function (str: string) {
|
||||
return str.replace(/'/g, "'\\''").replace(/\n/g, ' ');
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('defaultValue', function (value: unknown) {
|
||||
if (value === undefined || value === null) return '';
|
||||
return String(value);
|
||||
});
|
||||
|
||||
return Handlebars.compile(content, { noEscape: true });
|
||||
}
|
||||
|
||||
export interface CompletionResult {
|
||||
success: boolean;
|
||||
script?: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export function generateCompletion(spec: CLISpec, shell: ShellType): CompletionResult {
|
||||
try {
|
||||
const templateContent = getTemplateContent(shell);
|
||||
const template = compileTemplate(templateContent);
|
||||
const script = template({ spec });
|
||||
return { success: true, script };
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Unknown error during completion generation',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function getCompletionFileName(spec: CLISpec, shell: ShellType): string {
|
||||
const baseName = spec.bin || spec.name;
|
||||
const extensions: Record<ShellType, string> = {
|
||||
'bash': 'bash',
|
||||
'zsh': 'zsh',
|
||||
'fish': 'fish',
|
||||
};
|
||||
return `_${baseName}.${extensions[shell]}`;
|
||||
}
|
||||
|
||||
export function getInstallInstructions(spec: CLISpec, shell: ShellType): string {
|
||||
const fileName = getCompletionFileName(spec, shell);
|
||||
|
||||
switch (shell) {
|
||||
case 'bash':
|
||||
return `# Add to ~/.bashrc or /etc/bash_completion.d/
|
||||
source ${fileName}
|
||||
# Or for user-specific installation:
|
||||
echo "source $(pwd)/${fileName}" >> ~/.bashrc`;
|
||||
|
||||
case 'zsh':
|
||||
return `# Add to ~/.zshrc or create file in ~/.zsh/completion/
|
||||
mkdir -p ~/.zsh/completion
|
||||
cp ${fileName} ~/.zsh/completion/
|
||||
echo "fpath=(~/.zsh/completion \\$$fpath)" >> ~/.zshrc
|
||||
autoload -U compinit
|
||||
compinit`;
|
||||
|
||||
case 'fish':
|
||||
return `# Add to ~/.config/fish/completions/
|
||||
mkdir -p ~/.config/fish/completions/
|
||||
cp ${fileName} ~/.config/fish/completions/`;
|
||||
|
||||
default:
|
||||
return `Unknown shell: ${shell}`;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user