mirror of
https://github.com/Fission-AI/OpenSpec.git
synced 2026-10-04 14:38:54 +08:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2fa07b9216 | ||
|
|
cc8aa95ebc |
@@ -83,6 +83,22 @@ complete -F _openspec_completion openspec
|
||||
|
||||
// Handle subcommands
|
||||
if (cmd.subcommands && cmd.subcommands.length > 0) {
|
||||
// First, check if user is typing a flag for the parent command
|
||||
if (cmd.flags.length > 0) {
|
||||
lines.push(`${indent}if [[ "$cur" == -* ]]; then`);
|
||||
const flags = cmd.flags.map(f => {
|
||||
const parts: string[] = [];
|
||||
if (f.short) parts.push(`-${f.short}`);
|
||||
parts.push(`--${f.name}`);
|
||||
return parts.join(' ');
|
||||
}).join(' ');
|
||||
lines.push(`${indent} local flags="${flags}"`);
|
||||
lines.push(`${indent} COMPREPLY=($(compgen -W "$flags" -- "$cur"))`);
|
||||
lines.push(`${indent} return 0`);
|
||||
lines.push(`${indent}fi`);
|
||||
lines.push('');
|
||||
}
|
||||
|
||||
lines.push(`${indent}if [[ $cword -eq 2 ]]; then`);
|
||||
lines.push(`${indent} local subcommands="` + cmd.subcommands.map(s => this.escapeCommandName(s.name)).join(' ') + '"');
|
||||
lines.push(`${indent} COMPREPLY=($(compgen -W "$subcommands" -- "$cur"))`);
|
||||
|
||||
@@ -74,6 +74,29 @@ Register-ArgumentCompleter -CommandName openspec -ScriptBlock $openspecCompleter
|
||||
const lines: string[] = [];
|
||||
|
||||
if (cmd.subcommands && cmd.subcommands.length > 0) {
|
||||
// First, check if user is typing a flag for the parent command
|
||||
if (cmd.flags.length > 0) {
|
||||
lines.push(`${indent}if ($wordToComplete -like "-*") {`);
|
||||
lines.push(`${indent} $flags = @(`);
|
||||
for (const flag of cmd.flags) {
|
||||
const longFlag = `--${flag.name}`;
|
||||
const shortFlag = flag.short ? `-${flag.short}` : undefined;
|
||||
if (shortFlag) {
|
||||
lines.push(`${indent} @{Name="${longFlag}"; Description="${this.escapeDescription(flag.description)}"},`);
|
||||
lines.push(`${indent} @{Name="${shortFlag}"; Description="${this.escapeDescription(flag.description)}"},`);
|
||||
} else {
|
||||
lines.push(`${indent} @{Name="${longFlag}"; Description="${this.escapeDescription(flag.description)}"},`);
|
||||
}
|
||||
}
|
||||
lines.push(`${indent} )`);
|
||||
lines.push(`${indent} $flags | Where-Object { $_.Name -like "$wordToComplete*" } | ForEach-Object {`);
|
||||
lines.push(`${indent} [System.Management.Automation.CompletionResult]::new($_.Name, $_.Name, "ParameterName", $_.Description)`);
|
||||
lines.push(`${indent} }`);
|
||||
lines.push(`${indent} return`);
|
||||
lines.push(`${indent}}`);
|
||||
lines.push('');
|
||||
}
|
||||
|
||||
// Handle subcommands
|
||||
lines.push(`${indent}if ($commandCount -eq 2 -or ($commandCount -eq 3 -and $wordToComplete)) {`);
|
||||
lines.push(`${indent} $subcommands = @(`);
|
||||
|
||||
@@ -205,6 +205,50 @@ describe('BashGenerator', () => {
|
||||
expect(script).toContain('list');
|
||||
});
|
||||
|
||||
it('should offer parent flags when command has both flags and subcommands', () => {
|
||||
const commands: CommandDefinition[] = [
|
||||
{
|
||||
name: 'config',
|
||||
description: 'Manage configuration',
|
||||
flags: [
|
||||
{
|
||||
name: 'scope',
|
||||
short: 's',
|
||||
description: 'Configuration scope',
|
||||
},
|
||||
{
|
||||
name: 'json',
|
||||
description: 'Output as JSON',
|
||||
},
|
||||
],
|
||||
subcommands: [
|
||||
{
|
||||
name: 'set',
|
||||
description: 'Set a config value',
|
||||
flags: [],
|
||||
},
|
||||
{
|
||||
name: 'get',
|
||||
description: 'Get a config value',
|
||||
flags: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const script = generator.generate(commands);
|
||||
|
||||
// Should check for flag prefix before offering subcommands
|
||||
expect(script).toContain('if [[ "$cur" == -* ]]; then');
|
||||
// Should include parent command flags
|
||||
expect(script).toContain('-s');
|
||||
expect(script).toContain('--scope');
|
||||
expect(script).toContain('--json');
|
||||
// Should also include subcommands
|
||||
expect(script).toContain('set');
|
||||
expect(script).toContain('get');
|
||||
});
|
||||
|
||||
it('should handle positional arguments for change-id', () => {
|
||||
const commands: CommandDefinition[] = [
|
||||
{
|
||||
|
||||
@@ -224,6 +224,50 @@ describe('PowerShellGenerator', () => {
|
||||
expect(script).toContain('List changes');
|
||||
});
|
||||
|
||||
it('should offer parent flags when command has both flags and subcommands', () => {
|
||||
const commands: CommandDefinition[] = [
|
||||
{
|
||||
name: 'config',
|
||||
description: 'Manage configuration',
|
||||
flags: [
|
||||
{
|
||||
name: 'scope',
|
||||
short: 's',
|
||||
description: 'Configuration scope',
|
||||
},
|
||||
{
|
||||
name: 'json',
|
||||
description: 'Output as JSON',
|
||||
},
|
||||
],
|
||||
subcommands: [
|
||||
{
|
||||
name: 'set',
|
||||
description: 'Set a config value',
|
||||
flags: [],
|
||||
},
|
||||
{
|
||||
name: 'get',
|
||||
description: 'Get a config value',
|
||||
flags: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const script = generator.generate(commands);
|
||||
|
||||
// Should check for flag prefix before offering subcommands
|
||||
expect(script).toContain('if ($wordToComplete -like "-*")');
|
||||
// Should include parent command flags
|
||||
expect(script).toContain('-s');
|
||||
expect(script).toContain('--scope');
|
||||
expect(script).toContain('--json');
|
||||
// Should also include subcommands
|
||||
expect(script).toContain('"set"');
|
||||
expect(script).toContain('"get"');
|
||||
});
|
||||
|
||||
it('should handle positional arguments for change-id', () => {
|
||||
const commands: CommandDefinition[] = [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user