fix: Accept flags after positional command in headless arg parser
`gsd headless new-milestone --auto --verbose` now works — flags are parsed regardless of position relative to the command word. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
898e797772
commit
2d41de9b32
2 changed files with 44 additions and 8 deletions
|
|
@ -129,13 +129,12 @@ export function parseHeadlessArgs(argv: string[]): HeadlessOptions {
|
|||
}
|
||||
|
||||
const args = argv.slice(2)
|
||||
let positionalStarted = false
|
||||
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
const arg = args[i]
|
||||
if (arg === 'headless') continue
|
||||
|
||||
if (!positionalStarted && arg.startsWith('--')) {
|
||||
if (arg.startsWith('--')) {
|
||||
if (arg === '--timeout' && i + 1 < args.length) {
|
||||
options.timeout = parseInt(args[++i], 10)
|
||||
if (Number.isNaN(options.timeout) || options.timeout < 0) {
|
||||
|
|
@ -197,8 +196,7 @@ export function parseHeadlessArgs(argv: string[]): HeadlessOptions {
|
|||
} else if (arg === '--bare') {
|
||||
options.bare = true
|
||||
}
|
||||
} else if (!positionalStarted) {
|
||||
positionalStarted = true
|
||||
} else if (options.command === 'auto') {
|
||||
options.command = arg
|
||||
} else {
|
||||
options.commandArgs.push(arg)
|
||||
|
|
|
|||
|
|
@ -54,13 +54,12 @@ function parseHeadlessArgs(argv: string[]): HeadlessOptions {
|
|||
}
|
||||
|
||||
const args = argv.slice(2)
|
||||
let positionalStarted = false
|
||||
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
const arg = args[i]
|
||||
if (arg === 'headless') continue
|
||||
|
||||
if (!positionalStarted && arg.startsWith('--')) {
|
||||
if (arg.startsWith('--')) {
|
||||
if (arg === '--timeout' && i + 1 < args.length) {
|
||||
options.timeout = parseInt(args[++i], 10)
|
||||
} else if (arg === '--json') {
|
||||
|
|
@ -108,8 +107,7 @@ function parseHeadlessArgs(argv: string[]): HeadlessOptions {
|
|||
} else if (arg === '--bare') {
|
||||
options.bare = true
|
||||
}
|
||||
} else if (!positionalStarted) {
|
||||
positionalStarted = true
|
||||
} else if (options.command === 'auto') {
|
||||
options.command = arg
|
||||
} else {
|
||||
options.commandArgs.push(arg)
|
||||
|
|
@ -372,6 +370,46 @@ test('--bare combined with --output-format json', () => {
|
|||
assert.equal(opts.command, 'auto')
|
||||
})
|
||||
|
||||
// ─── Command-first ordering (flags after command) ─────────────────────────
|
||||
|
||||
test('command before flags: new-milestone --context-text --auto --verbose', () => {
|
||||
const opts = parseHeadlessArgs([
|
||||
'node', 'gsd', 'headless',
|
||||
'new-milestone',
|
||||
'--context-text', 'build something cool',
|
||||
'--auto',
|
||||
'--verbose',
|
||||
])
|
||||
assert.equal(opts.command, 'new-milestone')
|
||||
assert.equal(opts.contextText, 'build something cool')
|
||||
assert.equal(opts.auto, true)
|
||||
assert.equal(opts.verbose, true)
|
||||
})
|
||||
|
||||
test('command before flags: next --json --timeout', () => {
|
||||
const opts = parseHeadlessArgs([
|
||||
'node', 'gsd', 'headless',
|
||||
'next',
|
||||
'--json',
|
||||
'--timeout', '60000',
|
||||
])
|
||||
assert.equal(opts.command, 'next')
|
||||
assert.equal(opts.json, true)
|
||||
assert.equal(opts.timeout, 60000)
|
||||
})
|
||||
|
||||
test('command between flags: --auto new-milestone --verbose', () => {
|
||||
const opts = parseHeadlessArgs([
|
||||
'node', 'gsd', 'headless',
|
||||
'--auto',
|
||||
'new-milestone',
|
||||
'--verbose',
|
||||
])
|
||||
assert.equal(opts.command, 'new-milestone')
|
||||
assert.equal(opts.auto, true)
|
||||
assert.equal(opts.verbose, true)
|
||||
})
|
||||
|
||||
test('--bare does not affect other flags', () => {
|
||||
const opts = parseHeadlessArgs([
|
||||
'node', 'gsd', 'headless',
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue