fix: parse bare color as boolean flag (#12162)

* fix: parse bare color as boolean flag

Bare --color was treated as an enum-only option, so nopt could
consume the following flag as its value. This prevented command-specific
shorthands such as run --parallel from expanding when --color preceded
them.

Accept boolean values for the color option, and add parser/config
regression coverage for the shorthand case.

Co-authored-by: OpenAI Codex <codex@openai.com>

* test: remove tautological color type metadata test

Per review feedback, the assertion only restated the type metadata; the
behavior is already covered by the parser regression test and the
color-normalization test.

* fix: keep with current dispatch working after a boolean global flag

Bare `--color` now parses as a boolean flag, which enables forms like
`pnpm --color with current <cmd>`. The `with current` rewrite skipped any
occurrence whose preceding token was a long flag without `=`, assuming it
consumed `with` as its value. For boolean flags that is wrong, so the
lookup returned -1 and pnpm threw MISSING_WITH_CURRENT_CMD.

Skip only when the preceding long option actually takes a value, based on
the option type metadata; boolean flags and `--no-` negations no longer
hide the command.

---------

Co-authored-by: OpenAI Codex <codex@openai.com>
Co-authored-by: Zoltan Kochan <z@kochan.io>
This commit is contained in:
minbang
2026-06-08 22:04:19 +09:00
committed by GitHub
parent b4cc602b6d
commit 027196babe
5 changed files with 73 additions and 6 deletions

View File

@@ -263,6 +263,40 @@ test('use command-specific shorthands', async () => {
expect(options).toHaveProperty(['dev'])
})
test('bare --color does not consume a following command-specific shorthand', async () => {
const { cmd, options, params } = await parseCliArgs({
...DEFAULT_OPTS,
getTypesByCommandName: (commandName: string) => {
if (commandName === 'run') {
return {
recursive: Boolean,
sort: Boolean,
stream: Boolean,
'workspace-concurrency': Number,
}
}
return {}
},
shorthandsByCommandName: {
run: {
parallel: ['--workspace-concurrency=Infinity', '--no-sort', '--stream', '--recursive'],
},
},
universalOptionsTypes: {
color: [Boolean, 'always', 'auto', 'never'],
recursive: Boolean,
},
}, ['--recursive', '--color', '--parallel', 'run', 'dev'])
expect(cmd).toBe('run')
expect(params).toStrictEqual(['dev'])
expect(options.color).toBe(true)
expect(options.recursive).toBe(true)
expect(options['workspace-concurrency']).toBe(Infinity)
expect(options.sort).toBe(false)
expect(options.stream).toBe(true)
})
test('command-specific shorthands override universal shorthands', async () => {
const { options } = await parseCliArgs({
...DEFAULT_OPTS,