@optique/core 1.0.0-dev.431 → 1.0.0-dev.432

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/facade.cjs CHANGED
@@ -11,51 +11,67 @@ const require_parser = require('./parser.cjs');
11
11
 
12
12
  //#region src/facade.ts
13
13
  /**
14
- * Creates help parsers based on the specified mode.
14
+ * Creates help parsers based on the sub-config.
15
15
  */
16
- function createHelpParser(mode) {
17
- const helpCommand = require_primitives.command("help", require_modifiers.multiple(require_primitives.argument(require_valueparser.string({ metavar: "COMMAND" }), { description: require_message.message`Command name to show help for.` })), { description: require_message.message`Show help information.` });
18
- const helpOption = require_primitives.flag("--help", { description: require_message.message`Show help information.` });
19
- switch (mode) {
20
- case "command": return {
21
- helpCommand,
22
- helpOption: null
23
- };
24
- case "option": return {
25
- helpCommand: null,
26
- helpOption
27
- };
28
- case "both": return {
29
- helpCommand,
30
- helpOption
31
- };
16
+ function createHelpParser(commandConfig, optionConfig) {
17
+ let helpCommand = null;
18
+ let helpOption = null;
19
+ if (commandConfig) {
20
+ const names = commandConfig.names ?? ["help"];
21
+ const innerParser = require_modifiers.multiple(require_primitives.argument(require_valueparser.string({ metavar: "COMMAND" }), { description: require_message.message`Command name to show help for.` }));
22
+ const commandParsers = [];
23
+ for (let i = 0; i < names.length; i++) commandParsers.push(require_primitives.command(names[i], innerParser, {
24
+ description: require_message.message`Show help information.`,
25
+ hidden: i === 0 ? commandConfig.hidden : commandConfig.hidden === true ? true : true
26
+ }));
27
+ helpCommand = commandParsers.length === 1 ? commandParsers[0] : require_constructs.longestMatch(...commandParsers);
28
+ }
29
+ if (optionConfig) {
30
+ const names = optionConfig.names ?? ["--help"];
31
+ helpOption = require_primitives.flag(...names, {
32
+ description: require_message.message`Show help information.`,
33
+ hidden: optionConfig.hidden
34
+ });
32
35
  }
36
+ return {
37
+ helpCommand,
38
+ helpOption
39
+ };
33
40
  }
34
41
  /**
35
- * Creates version parsers based on the specified mode.
42
+ * Creates version parsers based on the sub-config.
36
43
  */
37
- function createVersionParser(mode) {
38
- const versionCommand = require_primitives.command("version", require_constructs.object({}), { description: require_message.message`Show version information.` });
39
- const versionOption = require_primitives.flag("--version", { description: require_message.message`Show version information.` });
40
- switch (mode) {
41
- case "command": return {
42
- versionCommand,
43
- versionOption: null
44
- };
45
- case "option": return {
46
- versionCommand: null,
47
- versionOption
48
- };
49
- case "both": return {
50
- versionCommand,
51
- versionOption
52
- };
44
+ function createVersionParser(commandConfig, optionConfig) {
45
+ let versionCommand = null;
46
+ let versionOption = null;
47
+ if (commandConfig) {
48
+ const names = commandConfig.names ?? ["version"];
49
+ const innerParser = require_constructs.object({});
50
+ const commandParsers = [];
51
+ for (let i = 0; i < names.length; i++) commandParsers.push(require_primitives.command(names[i], innerParser, {
52
+ description: require_message.message`Show version information.`,
53
+ hidden: i === 0 ? commandConfig.hidden : commandConfig.hidden === true ? true : true
54
+ }));
55
+ versionCommand = commandParsers.length === 1 ? commandParsers[0] : require_constructs.longestMatch(...commandParsers);
53
56
  }
57
+ if (optionConfig) {
58
+ const names = optionConfig.names ?? ["--version"];
59
+ versionOption = require_primitives.flag(...names, {
60
+ description: require_message.message`Show version information.`,
61
+ hidden: optionConfig.hidden
62
+ });
63
+ }
64
+ return {
65
+ versionCommand,
66
+ versionOption
67
+ };
54
68
  }
55
69
  /**
56
- * Creates completion parsers based on the specified mode.
70
+ * Creates completion parsers based on the sub-config.
57
71
  */
58
- function createCompletionParser(mode, programName, availableShells, name = "both", helpVisibility = name) {
72
+ function createCompletionParser(programName, availableShells, commandConfig, optionConfig) {
73
+ let completionCommand = null;
74
+ let completionOption = null;
59
75
  const shellList = [];
60
76
  for (const shell in availableShells) {
61
77
  if (shellList.length > 0) shellList.push(require_message.text(", "));
@@ -65,56 +81,44 @@ function createCompletionParser(mode, programName, availableShells, name = "both
65
81
  shell: require_modifiers.optional(require_primitives.argument(require_valueparser.string({ metavar: "SHELL" }), { description: require_message.message`Shell type (${shellList}). Generate completion script when used alone, or provide completions when followed by arguments.` })),
66
82
  args: require_modifiers.multiple(require_primitives.argument(require_valueparser.string({ metavar: "ARG" }), { description: require_message.message`Command line arguments for completion suggestions (used by shell integration; you usually don't need to provide this).` }))
67
83
  });
68
- const commandName = name === "plural" ? "completions" : "completion";
69
- const completionCommandConfig = {
70
- brief: require_message.message`Generate shell completion script or provide completions.`,
71
- description: require_message.message`Generate shell completion script or provide completions.`,
72
- footer: require_message.message`Examples:${require_message.lineBreak()} Bash: ${require_message.commandLine(`eval "$(${programName} ${commandName} bash)"`)}${require_message.lineBreak()} zsh: ${require_message.commandLine(`eval "$(${programName} ${commandName} zsh)"`)}${require_message.lineBreak()} fish: ${require_message.commandLine(`eval "$(${programName} ${commandName} fish)"`)}${require_message.lineBreak()} PowerShell: ${require_message.commandLine(`${programName} ${commandName} pwsh > ${programName}-completion.ps1; . ./${programName}-completion.ps1`)}${require_message.lineBreak()} Nushell: ${require_message.commandLine(`${programName} ${commandName} nu | save ${programName}-completion.nu; source ./${programName}-completion.nu`)}`
73
- };
74
- const completionCommands = [];
75
- const showSingular = helpVisibility === "singular" || helpVisibility === "both";
76
- const showPlural = helpVisibility === "plural" || helpVisibility === "both";
77
- if (name === "singular" || name === "both") completionCommands.push(require_primitives.command("completion", completionInner, {
78
- ...completionCommandConfig,
79
- hidden: !showSingular
80
- }));
81
- if (name === "plural" || name === "both") completionCommands.push(require_primitives.command("completions", completionInner, {
82
- ...completionCommandConfig,
83
- hidden: !showPlural
84
- }));
85
- const completionCommand = require_constructs.longestMatch(...completionCommands);
86
- const completionOptions = [];
87
- if (name === "singular" || name === "both") completionOptions.push(require_primitives.option("--completion", require_valueparser.string({ metavar: "SHELL" }), {
88
- description: require_message.message`Generate shell completion script.`,
89
- hidden: !showSingular
90
- }));
91
- if (name === "plural" || name === "both") completionOptions.push(require_primitives.option("--completions", require_valueparser.string({ metavar: "SHELL" }), {
92
- description: require_message.message`Generate shell completion script.`,
93
- hidden: !showPlural
94
- }));
95
- const completionOption = completionOptions.length === 1 ? completionOptions[0] : require_constructs.longestMatch(completionOptions[0], completionOptions[1]);
96
- const argsParser = require_modifiers.withDefault(require_modifiers.multiple(require_primitives.argument(require_valueparser.string({ metavar: "ARG" }), { description: require_message.message`Command line arguments for completion suggestions (used by shell integration; you usually don't need to provide this).` })), []);
97
- const optionParser = require_constructs.object({
98
- shell: completionOption,
99
- args: argsParser
100
- });
101
- switch (mode) {
102
- case "command": return {
103
- completionCommand,
104
- completionOption: null
105
- };
106
- case "option": return {
107
- completionCommand: null,
108
- completionOption: optionParser
109
- };
110
- case "both": return {
111
- completionCommand,
112
- completionOption: optionParser
84
+ if (commandConfig) {
85
+ const names = commandConfig.names ?? ["completion"];
86
+ const displayName = names[0];
87
+ const completionCommandConfig = {
88
+ brief: require_message.message`Generate shell completion script or provide completions.`,
89
+ description: require_message.message`Generate shell completion script or provide completions.`,
90
+ footer: require_message.message`Examples:${require_message.lineBreak()} Bash: ${require_message.commandLine(`eval "$(${programName} ${displayName} bash)"`)}${require_message.lineBreak()} zsh: ${require_message.commandLine(`eval "$(${programName} ${displayName} zsh)"`)}${require_message.lineBreak()} fish: ${require_message.commandLine(`eval "$(${programName} ${displayName} fish)"`)}${require_message.lineBreak()} PowerShell: ${require_message.commandLine(`${programName} ${displayName} pwsh > ${programName}-completion.ps1; . ./${programName}-completion.ps1`)}${require_message.lineBreak()} Nushell: ${require_message.commandLine(`${programName} ${displayName} nu | save ${programName}-completion.nu; source ./${programName}-completion.nu`)}`
113
91
  };
92
+ const commandParsers = [];
93
+ for (let i = 0; i < names.length; i++) commandParsers.push(require_primitives.command(names[i], completionInner, {
94
+ ...completionCommandConfig,
95
+ hidden: i === 0 ? commandConfig.hidden : commandConfig.hidden === true ? true : true
96
+ }));
97
+ completionCommand = commandParsers.length === 1 ? commandParsers[0] : require_constructs.longestMatch(...commandParsers);
114
98
  }
99
+ if (optionConfig) {
100
+ const names = optionConfig.names ?? ["--completion"];
101
+ const completionOptions = [];
102
+ for (const name of names) completionOptions.push(require_primitives.option(name, require_valueparser.string({ metavar: "SHELL" }), {
103
+ description: require_message.message`Generate shell completion script.`,
104
+ hidden: optionConfig.hidden
105
+ }));
106
+ const completionOptionParser = completionOptions.length === 1 ? completionOptions[0] : require_constructs.longestMatch(...completionOptions);
107
+ const argsParser = require_modifiers.withDefault(require_modifiers.multiple(require_primitives.argument(require_valueparser.string({ metavar: "ARG" }), { description: require_message.message`Command line arguments for completion suggestions (used by shell integration; you usually don't need to provide this).` })), []);
108
+ completionOption = require_constructs.object({
109
+ shell: completionOptionParser,
110
+ args: argsParser
111
+ });
112
+ }
113
+ return {
114
+ completionCommand,
115
+ completionOption
116
+ };
115
117
  }
116
- function combineWithHelpVersion(originalParser, helpParsers, versionParsers, completionParsers, groups) {
118
+ function combineWithHelpVersion(originalParser, helpParsers, versionParsers, completionParsers, groups, helpOptionNames, versionOptionNames) {
117
119
  const parsers = [];
120
+ const effectiveHelpOptionNames = helpOptionNames ?? ["--help"];
121
+ const effectiveVersionOptionNames = versionOptionNames ?? ["--version"];
118
122
  if (helpParsers.helpOption) {
119
123
  const lenientHelpParser = {
120
124
  $mode: "sync",
@@ -135,11 +139,11 @@ function combineWithHelpVersion(originalParser, helpParsers, versionParsers, com
135
139
  let versionIndex = -1;
136
140
  for (let i = 0; i < buffer.length; i++) {
137
141
  if (buffer[i] === "--") break;
138
- if (buffer[i] === "--help") {
142
+ if (effectiveHelpOptionNames.includes(buffer[i])) {
139
143
  helpFound = true;
140
144
  helpIndex = i;
141
145
  }
142
- if (buffer[i] === "--version") versionIndex = i;
146
+ if (effectiveVersionOptionNames.includes(buffer[i])) versionIndex = i;
143
147
  }
144
148
  if (helpFound && versionIndex > helpIndex) return {
145
149
  success: false,
@@ -169,7 +173,7 @@ function combineWithHelpVersion(originalParser, helpParsers, versionParsers, com
169
173
  }
170
174
  return {
171
175
  success: false,
172
- error: require_message.message`Flag ${require_message.optionName("--help")} not found.`,
176
+ error: require_message.message`Flag ${require_message.optionName(effectiveHelpOptionNames[0])} not found.`,
173
177
  consumed: 0
174
178
  };
175
179
  },
@@ -180,16 +184,17 @@ function combineWithHelpVersion(originalParser, helpParsers, versionParsers, com
180
184
  };
181
185
  },
182
186
  *suggest(_context, prefix) {
183
- if ("--help".startsWith(prefix)) yield {
187
+ for (const name of effectiveHelpOptionNames) if (name.startsWith(prefix)) yield {
184
188
  kind: "literal",
185
- text: "--help"
189
+ text: name
186
190
  };
187
191
  },
188
192
  getDocFragments(state) {
189
193
  return helpParsers.helpOption?.getDocFragments(state) ?? { fragments: [] };
190
194
  }
191
195
  };
192
- parsers.push(lenientHelpParser);
196
+ const wrappedHelp = groups?.helpOptionGroup ? require_constructs.group(groups.helpOptionGroup, lenientHelpParser) : lenientHelpParser;
197
+ parsers.push(wrappedHelp);
193
198
  }
194
199
  if (versionParsers.versionOption) {
195
200
  const lenientVersionParser = {
@@ -211,11 +216,11 @@ function combineWithHelpVersion(originalParser, helpParsers, versionParsers, com
211
216
  let helpIndex = -1;
212
217
  for (let i = 0; i < buffer.length; i++) {
213
218
  if (buffer[i] === "--") break;
214
- if (buffer[i] === "--version") {
219
+ if (effectiveVersionOptionNames.includes(buffer[i])) {
215
220
  versionFound = true;
216
221
  versionIndex = i;
217
222
  }
218
- if (buffer[i] === "--help") helpIndex = i;
223
+ if (effectiveHelpOptionNames.includes(buffer[i])) helpIndex = i;
219
224
  }
220
225
  if (versionFound && helpIndex > versionIndex) return {
221
226
  success: false,
@@ -237,7 +242,7 @@ function combineWithHelpVersion(originalParser, helpParsers, versionParsers, com
237
242
  };
238
243
  return {
239
244
  success: false,
240
- error: require_message.message`Flag ${require_message.optionName("--version")} not found.`,
245
+ error: require_message.message`Flag ${require_message.optionName(effectiveVersionOptionNames[0])} not found.`,
241
246
  consumed: 0
242
247
  };
243
248
  },
@@ -248,16 +253,17 @@ function combineWithHelpVersion(originalParser, helpParsers, versionParsers, com
248
253
  };
249
254
  },
250
255
  *suggest(_context, prefix) {
251
- if ("--version".startsWith(prefix)) yield {
256
+ for (const name of effectiveVersionOptionNames) if (name.startsWith(prefix)) yield {
252
257
  kind: "literal",
253
- text: "--version"
258
+ text: name
254
259
  };
255
260
  },
256
261
  getDocFragments(state) {
257
262
  return versionParsers.versionOption?.getDocFragments(state) ?? { fragments: [] };
258
263
  }
259
264
  };
260
- parsers.push(lenientVersionParser);
265
+ const wrappedVersion = groups?.versionOptionGroup ? require_constructs.group(groups.versionOptionGroup, lenientVersionParser) : lenientVersionParser;
266
+ parsers.push(wrappedVersion);
261
267
  }
262
268
  if (versionParsers.versionCommand) {
263
269
  const versionParser = require_constructs.object({
@@ -267,7 +273,7 @@ function combineWithHelpVersion(originalParser, helpParsers, versionParsers, com
267
273
  result: versionParsers.versionCommand,
268
274
  helpFlag: helpParsers.helpOption ? require_modifiers.optional(helpParsers.helpOption) : require_primitives.constant(false)
269
275
  });
270
- parsers.push(groups?.versionGroup ? require_constructs.group(groups.versionGroup, versionParser) : versionParser);
276
+ parsers.push(groups?.versionCommandGroup ? require_constructs.group(groups.versionCommandGroup, versionParser) : versionParser);
271
277
  }
272
278
  if (completionParsers.completionCommand) {
273
279
  const completionParser = require_constructs.object({
@@ -277,7 +283,7 @@ function combineWithHelpVersion(originalParser, helpParsers, versionParsers, com
277
283
  completionData: completionParsers.completionCommand,
278
284
  helpFlag: helpParsers.helpOption ? require_modifiers.optional(helpParsers.helpOption) : require_primitives.constant(false)
279
285
  });
280
- parsers.push(groups?.completionGroup ? require_constructs.group(groups.completionGroup, completionParser) : completionParser);
286
+ parsers.push(groups?.completionCommandGroup ? require_constructs.group(groups.completionCommandGroup, completionParser) : completionParser);
281
287
  }
282
288
  if (helpParsers.helpCommand) {
283
289
  const helpParser = require_constructs.object({
@@ -286,7 +292,7 @@ function combineWithHelpVersion(originalParser, helpParsers, versionParsers, com
286
292
  completion: require_primitives.constant(false),
287
293
  commands: helpParsers.helpCommand
288
294
  });
289
- parsers.push(groups?.helpGroup ? require_constructs.group(groups.helpGroup, helpParser) : helpParser);
295
+ parsers.push(groups?.helpCommandGroup ? require_constructs.group(groups.helpCommandGroup, helpParser) : helpParser);
290
296
  }
291
297
  parsers.push(require_constructs.object({
292
298
  help: require_primitives.constant(false),
@@ -316,9 +322,10 @@ function combineWithHelpVersion(originalParser, helpParsers, versionParsers, com
316
322
  return combined;
317
323
  }
318
324
  /**
319
- * Classifies the parsing result into a discriminated union for cleaner handling.
325
+ * Classifies the parsing result into a discriminated union for cleaner
326
+ * handling.
320
327
  */
321
- function classifyResult(result, args) {
328
+ function classifyResult(result, args, helpOptionNames, helpCommandNames, versionOptionNames, versionCommandNames, completionCommandNames) {
322
329
  if (!result.success) return {
323
330
  type: "error",
324
331
  error: result.error
@@ -326,19 +333,19 @@ function classifyResult(result, args) {
326
333
  const value$1 = result.value;
327
334
  if (typeof value$1 === "object" && value$1 != null && "help" in value$1 && "version" in value$1) {
328
335
  const parsedValue = value$1;
329
- const hasVersionOption = args.includes("--version");
330
- const hasVersionCommand = args.length > 0 && args[0] === "version";
331
- const hasHelpOption = args.includes("--help");
332
- const hasHelpCommand = args.length > 0 && args[0] === "help";
333
- const hasCompletionCommand = args.length > 0 && args[0] === "completion";
336
+ const hasVersionOption = versionOptionNames.some((n) => args.includes(n));
337
+ const hasVersionCommand = args.length > 0 && versionCommandNames.includes(args[0]);
338
+ const hasHelpOption = helpOptionNames.some((n) => args.includes(n));
339
+ const hasHelpCommand = args.length > 0 && helpCommandNames.includes(args[0]);
340
+ const hasCompletionCommand = args.length > 0 && completionCommandNames.includes(args[0]);
334
341
  if (hasVersionOption && hasHelpOption && !hasVersionCommand && !hasHelpCommand) {}
335
342
  if (hasVersionCommand && hasHelpOption && parsedValue.helpFlag) return {
336
343
  type: "help",
337
- commands: ["version"]
344
+ commands: [args[0]]
338
345
  };
339
346
  if (hasCompletionCommand && hasHelpOption && parsedValue.helpFlag) return {
340
347
  type: "help",
341
- commands: ["completion"]
348
+ commands: [args[0]]
342
349
  };
343
350
  if (parsedValue.help && (hasHelpOption || hasHelpCommand)) {
344
351
  let commandContext = [];
@@ -369,7 +376,7 @@ function classifyResult(result, args) {
369
376
  * Handles shell completion requests.
370
377
  * @since 0.6.0
371
378
  */
372
- function handleCompletion(completionArgs, programName, parser, completionParser, stdout, stderr, onCompletion, onError, availableShells, colors, maxWidth, completionMode, completionName, sectionOrder) {
379
+ function handleCompletion(completionArgs, programName, parser, completionParser, stdout, stderr, onCompletion, onError, availableShells, colors, maxWidth, completionCommandDisplayName, completionOptionDisplayName, isOptionMode, sectionOrder) {
373
380
  const shellName = completionArgs[0] || "";
374
381
  const args = completionArgs.slice(1);
375
382
  const callOnError = (code) => {
@@ -389,7 +396,8 @@ function handleCompletion(completionArgs, programName, parser, completionParser,
389
396
  if (!shellName) {
390
397
  stderr("Error: Missing shell name for completion.\n");
391
398
  if (completionParser) {
392
- const doc = require_parser.getDocPage(completionParser, ["completion"]);
399
+ const displayName = completionCommandDisplayName ?? "completion";
400
+ const doc = require_parser.getDocPage(completionParser, [displayName]);
393
401
  if (doc) stderr(require_doc.formatDocPage(programName, doc, {
394
402
  colors,
395
403
  maxWidth,
@@ -414,8 +422,7 @@ function handleCompletion(completionArgs, programName, parser, completionParser,
414
422
  return callOnError(1);
415
423
  }
416
424
  if (args.length === 0) {
417
- const usePlural = completionName === "plural";
418
- const completionArg = completionMode === "option" ? usePlural ? "--completions" : "--completion" : usePlural ? "completions" : "completion";
425
+ const completionArg = isOptionMode ? completionOptionDisplayName ?? "--completion" : completionCommandDisplayName ?? "completion";
419
426
  const script = shell.generateScript(programName, [completionArg, shellName]);
420
427
  stdout(script);
421
428
  if (parser.$mode === "async") return Promise.resolve(callOnCompletion(0));
@@ -461,18 +468,23 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
461
468
  const { colors, maxWidth, showDefault, showChoices, sectionOrder, aboveError = "usage", onError = () => {
462
469
  throw new RunParserError("Failed to parse command line arguments.");
463
470
  }, stderr = console.error, stdout = console.log, brief, description, examples, author, bugs, footer } = options;
464
- const helpMode = options.help?.mode ?? "option";
471
+ const norm = (c) => c === true ? {} : c;
472
+ const helpCommandConfig = norm(options.help?.command);
473
+ const helpOptionConfig = norm(options.help?.option);
465
474
  const onHelp = options.help?.onShow ?? (() => ({}));
466
- const helpGroup = options.help?.group;
467
- const versionMode = options.version?.mode ?? "option";
475
+ const versionCommandConfig = norm(options.version?.command);
476
+ const versionOptionConfig = norm(options.version?.option);
468
477
  const versionValue = options.version?.value ?? "";
469
478
  const onVersion = options.version?.onShow ?? (() => ({}));
470
- const versionGroup = options.version?.group;
471
- const completionMode = options.completion?.mode ?? "both";
472
- const completionName = options.completion?.name ?? "both";
473
- const completionHelpVisibility = options.completion?.helpVisibility ?? completionName;
479
+ const completionCommandConfig = norm(options.completion?.command);
480
+ const completionOptionConfig = norm(options.completion?.option);
474
481
  const onCompletion = options.completion?.onShow ?? (() => ({}));
475
- const completionGroup = options.completion?.group;
482
+ const helpOptionNames = helpOptionConfig?.names ?? ["--help"];
483
+ const helpCommandNames = helpCommandConfig?.names ?? ["help"];
484
+ const versionOptionNames = versionOptionConfig?.names ?? ["--version"];
485
+ const versionCommandNames = versionCommandConfig?.names ?? ["version"];
486
+ const completionCommandNames = completionCommandConfig?.names ?? ["completion"];
487
+ const completionOptionNames = completionOptionConfig?.names ?? ["--completion"];
476
488
  const defaultShells = {
477
489
  bash: require_completion.bash,
478
490
  fish: require_completion.fish,
@@ -484,50 +496,47 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
484
496
  ...defaultShells,
485
497
  ...options.completion.shells
486
498
  } : defaultShells;
487
- const help = options.help ? helpMode : "none";
488
- const version = options.version ? versionMode : "none";
489
- const completion = options.completion ? completionMode : "none";
490
- const helpParsers = help === "none" ? {
499
+ const helpParsers = options.help ? createHelpParser(helpCommandConfig, helpOptionConfig) : {
491
500
  helpCommand: null,
492
501
  helpOption: null
493
- } : createHelpParser(help);
494
- const versionParsers = version === "none" ? {
502
+ };
503
+ const versionParsers = options.version ? createVersionParser(versionCommandConfig, versionOptionConfig) : {
495
504
  versionCommand: null,
496
505
  versionOption: null
497
- } : createVersionParser(version);
498
- const completionParsers = completion === "none" ? {
506
+ };
507
+ const completionParsers = options.completion ? createCompletionParser(programName, availableShells, completionCommandConfig, completionOptionConfig) : {
499
508
  completionCommand: null,
500
509
  completionOption: null
501
- } : createCompletionParser(completion, programName, availableShells, completionName, completionHelpVisibility);
510
+ };
502
511
  if (options.completion) {
503
- const hasHelpOption = args.includes("--help");
504
- if ((completionMode === "command" || completionMode === "both") && args.length >= 1 && ((completionName === "singular" || completionName === "both" ? args[0] === "completion" : false) || (completionName === "plural" || completionName === "both" ? args[0] === "completions" : false)) && !hasHelpOption) return handleCompletion(args.slice(1), programName, parser, completionParsers.completionCommand, stdout, stderr, onCompletion, onError, availableShells, colors, maxWidth, completionMode, completionName, sectionOrder);
505
- if (completionMode === "option" || completionMode === "both") for (let i = 0; i < args.length; i++) {
512
+ const hasHelpOption = helpOptionConfig ? helpOptionNames.some((n) => args.includes(n)) : false;
513
+ if (completionCommandConfig && args.length >= 1 && completionCommandNames.includes(args[0]) && !hasHelpOption) return handleCompletion(args.slice(1), programName, parser, completionParsers.completionCommand, stdout, stderr, onCompletion, onError, availableShells, colors, maxWidth, completionCommandNames[0], completionOptionNames[0], false, sectionOrder);
514
+ if (completionOptionConfig) for (let i = 0; i < args.length; i++) {
506
515
  const arg = args[i];
507
- const singularMatch = completionName === "singular" || completionName === "both" ? arg.startsWith("--completion=") : false;
508
- const pluralMatch = completionName === "plural" || completionName === "both" ? arg.startsWith("--completions=") : false;
509
- if (singularMatch || pluralMatch) {
510
- const shell = arg.slice(arg.indexOf("=") + 1);
516
+ const equalsMatch = completionOptionNames.find((n) => arg.startsWith(n + "="));
517
+ if (equalsMatch) {
518
+ const shell = arg.slice(equalsMatch.length + 1);
511
519
  const completionArgs = args.slice(i + 1);
512
- return handleCompletion([shell, ...completionArgs], programName, parser, completionParsers.completionCommand, stdout, stderr, onCompletion, onError, availableShells, colors, maxWidth, completionMode, completionName, sectionOrder);
513
- } else {
514
- const singularMatchExact = completionName === "singular" || completionName === "both" ? arg === "--completion" : false;
515
- const pluralMatchExact = completionName === "plural" || completionName === "both" ? arg === "--completions" : false;
516
- if (singularMatchExact || pluralMatchExact) {
517
- const shell = i + 1 < args.length ? args[i + 1] : "";
518
- const completionArgs = i + 1 < args.length ? args.slice(i + 2) : [];
519
- return handleCompletion([shell, ...completionArgs], programName, parser, completionParsers.completionCommand, stdout, stderr, onCompletion, onError, availableShells, colors, maxWidth, completionMode, completionName, sectionOrder);
520
- }
520
+ return handleCompletion([shell, ...completionArgs], programName, parser, completionParsers.completionCommand, stdout, stderr, onCompletion, onError, availableShells, colors, maxWidth, completionCommandNames[0], completionOptionNames[0], true, sectionOrder);
521
+ }
522
+ const exactMatch = completionOptionNames.includes(arg);
523
+ if (exactMatch) {
524
+ const shell = i + 1 < args.length ? args[i + 1] : "";
525
+ const completionArgs = i + 1 < args.length ? args.slice(i + 2) : [];
526
+ return handleCompletion([shell, ...completionArgs], programName, parser, completionParsers.completionCommand, stdout, stderr, onCompletion, onError, availableShells, colors, maxWidth, completionCommandNames[0], completionOptionNames[0], true, sectionOrder);
521
527
  }
522
528
  }
523
529
  }
524
- const augmentedParser = help === "none" && version === "none" && completion === "none" ? parser : combineWithHelpVersion(parser, helpParsers, versionParsers, completionParsers, {
525
- helpGroup,
526
- versionGroup,
527
- completionGroup
528
- });
530
+ const augmentedParser = !options.help && !options.version && !options.completion ? parser : combineWithHelpVersion(parser, helpParsers, versionParsers, completionParsers, {
531
+ helpCommandGroup: helpCommandConfig?.group,
532
+ helpOptionGroup: helpOptionConfig?.group,
533
+ versionCommandGroup: versionCommandConfig?.group,
534
+ versionOptionGroup: versionOptionConfig?.group,
535
+ completionCommandGroup: completionCommandConfig?.group,
536
+ completionOptionGroup: completionOptionConfig?.group
537
+ }, helpOptionConfig ? [...helpOptionNames] : void 0, versionOptionConfig ? [...versionOptionNames] : void 0);
529
538
  const handleResult = (result) => {
530
- const classified = classifyResult(result, args);
539
+ const classified = classifyResult(result, args, helpOptionConfig ? [...helpOptionNames] : [], helpCommandConfig ? [...helpCommandNames] : [], versionOptionConfig ? [...versionOptionNames] : [], versionCommandConfig ? [...versionCommandNames] : [], completionCommandConfig ? [...completionCommandNames] : []);
531
540
  switch (classified.type) {
532
541
  case "success": return classified.value;
533
542
  case "version":
@@ -540,16 +549,16 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
540
549
  case "completion": throw new RunParserError("Completion should be handled by early return");
541
550
  case "help": {
542
551
  let helpGeneratorParser;
543
- const helpAsCommand = help === "command" || help === "both";
544
- const versionAsCommand = version === "command" || version === "both";
545
- const completionAsCommand = completion === "command" || completion === "both";
546
- const helpAsOption = help === "option" || help === "both";
547
- const versionAsOption = version === "option" || version === "both";
548
- const completionAsOption = completion === "option" || completion === "both";
552
+ const helpAsCommand = helpCommandConfig != null;
553
+ const versionAsCommand = versionCommandConfig != null;
554
+ const completionAsCommand = completionCommandConfig != null;
555
+ const helpAsOption = helpOptionConfig != null;
556
+ const versionAsOption = versionOptionConfig != null;
557
+ const completionAsOption = completionOptionConfig != null;
549
558
  const requestedCommand = classified.commands[0];
550
- if ((requestedCommand === "completion" || requestedCommand === "completions") && completionAsCommand && completionParsers.completionCommand) helpGeneratorParser = completionParsers.completionCommand;
551
- else if (requestedCommand === "help" && helpAsCommand && helpParsers.helpCommand) helpGeneratorParser = helpParsers.helpCommand;
552
- else if (requestedCommand === "version" && versionAsCommand && versionParsers.versionCommand) helpGeneratorParser = versionParsers.versionCommand;
559
+ if (requestedCommand != null && completionCommandNames.includes(requestedCommand) && completionAsCommand && completionParsers.completionCommand) helpGeneratorParser = completionParsers.completionCommand;
560
+ else if (requestedCommand != null && helpCommandNames.includes(requestedCommand) && helpAsCommand && helpParsers.helpCommand) helpGeneratorParser = helpParsers.helpCommand;
561
+ else if (requestedCommand != null && versionCommandNames.includes(requestedCommand) && versionAsCommand && versionParsers.versionCommand) helpGeneratorParser = versionParsers.versionCommand;
553
562
  else {
554
563
  const commandParsers = [parser];
555
564
  const groupedMeta = {};
@@ -558,15 +567,24 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
558
567
  if (groupLabel) (groupedMeta[groupLabel] ??= []).push(p);
559
568
  else ungroupedMeta.push(p);
560
569
  };
561
- if (helpAsCommand && helpParsers.helpCommand) addMeta(helpParsers.helpCommand, helpGroup);
562
- if (versionAsCommand && versionParsers.versionCommand) addMeta(versionParsers.versionCommand, versionGroup);
563
- if (completionAsCommand && completionParsers.completionCommand) addMeta(completionParsers.completionCommand, completionGroup);
570
+ if (helpAsCommand && helpParsers.helpCommand) addMeta(helpParsers.helpCommand, helpCommandConfig?.group);
571
+ if (versionAsCommand && versionParsers.versionCommand) addMeta(versionParsers.versionCommand, versionCommandConfig?.group);
572
+ if (completionAsCommand && completionParsers.completionCommand) addMeta(completionParsers.completionCommand, completionCommandConfig?.group);
564
573
  commandParsers.push(...ungroupedMeta);
565
574
  for (const [label, parsers] of Object.entries(groupedMeta)) if (parsers.length === 1) commandParsers.push(require_constructs.group(label, parsers[0]));
566
575
  else commandParsers.push(require_constructs.group(label, require_constructs.longestMatch(...parsers)));
567
- if (helpAsOption && helpParsers.helpOption) commandParsers.push(helpParsers.helpOption);
568
- if (versionAsOption && versionParsers.versionOption) commandParsers.push(versionParsers.versionOption);
569
- if (completionAsOption && completionParsers.completionOption) commandParsers.push(completionParsers.completionOption);
576
+ const groupedMetaOptions = {};
577
+ const ungroupedMetaOptions = [];
578
+ const addMetaOption = (p, groupLabel) => {
579
+ if (groupLabel) (groupedMetaOptions[groupLabel] ??= []).push(p);
580
+ else ungroupedMetaOptions.push(p);
581
+ };
582
+ if (helpAsOption && helpParsers.helpOption) addMetaOption(helpParsers.helpOption, helpOptionConfig?.group);
583
+ if (versionAsOption && versionParsers.versionOption) addMetaOption(versionParsers.versionOption, versionOptionConfig?.group);
584
+ if (completionAsOption && completionParsers.completionOption) addMetaOption(completionParsers.completionOption, completionOptionConfig?.group);
585
+ commandParsers.push(...ungroupedMetaOptions);
586
+ for (const [label, optParsers] of Object.entries(groupedMetaOptions)) if (optParsers.length === 1) commandParsers.push(require_constructs.group(label, optParsers[0]));
587
+ else commandParsers.push(require_constructs.group(label, require_constructs.longestMatch(...optParsers)));
570
588
  if (commandParsers.length === 1) helpGeneratorParser = commandParsers[0];
571
589
  else if (commandParsers.length === 2) helpGeneratorParser = require_constructs.longestMatch(commandParsers[0], commandParsers[1]);
572
590
  else helpGeneratorParser = require_constructs.longestMatch(...commandParsers);
@@ -626,7 +644,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
626
644
  }
627
645
  const displayHelp = (doc) => {
628
646
  if (doc != null) {
629
- const isMetaCommandHelp = (completionName === "singular" || completionName === "both" ? requestedCommand === "completion" : false) || (completionName === "plural" || completionName === "both" ? requestedCommand === "completions" : false) || requestedCommand === "help" || requestedCommand === "version";
647
+ const isMetaCommandHelp = requestedCommand != null && completionCommandNames.includes(requestedCommand) || requestedCommand != null && helpCommandNames.includes(requestedCommand) || requestedCommand != null && versionCommandNames.includes(requestedCommand);
630
648
  const isSubcommandHelp = classified.commands.length > 0;
631
649
  const isTopLevel = !isSubcommandHelp;
632
650
  const shouldOverride = !isMetaCommandHelp && !isSubcommandHelp;
@@ -774,26 +792,31 @@ function indentLines(text$1, indent) {
774
792
  * @returns `true` if early exit should be performed, `false` otherwise.
775
793
  */
776
794
  function needsEarlyExit(args, options) {
795
+ const norm = (c) => c === true ? {} : c;
777
796
  if (options.help) {
778
- const helpMode = options.help.mode ?? "option";
779
- if ((helpMode === "option" || helpMode === "both") && args.includes("--help")) return true;
780
- if ((helpMode === "command" || helpMode === "both") && args[0] === "help") return true;
797
+ const helpOptionConfig = norm(options.help.option);
798
+ const helpCommandConfig = norm(options.help.command);
799
+ const helpOptionNames = helpOptionConfig?.names ?? ["--help"];
800
+ const helpCommandNames = helpCommandConfig?.names ?? ["help"];
801
+ if (helpOptionConfig && helpOptionNames.some((n) => args.includes(n))) return true;
802
+ if (helpCommandConfig && helpCommandNames.includes(args[0])) return true;
781
803
  }
782
804
  if (options.version) {
783
- const versionMode = options.version.mode ?? "option";
784
- if ((versionMode === "option" || versionMode === "both") && args.includes("--version")) return true;
785
- if ((versionMode === "command" || versionMode === "both") && args[0] === "version") return true;
805
+ const versionOptionConfig = norm(options.version.option);
806
+ const versionCommandConfig = norm(options.version.command);
807
+ const versionOptionNames = versionOptionConfig?.names ?? ["--version"];
808
+ const versionCommandNames = versionCommandConfig?.names ?? ["version"];
809
+ if (versionOptionConfig && versionOptionNames.some((n) => args.includes(n))) return true;
810
+ if (versionCommandConfig && versionCommandNames.includes(args[0])) return true;
786
811
  }
787
812
  if (options.completion) {
788
- const completionMode = options.completion.mode ?? "both";
789
- const completionName = options.completion.name ?? "both";
790
- if (completionMode === "command" || completionMode === "both") {
791
- if ((completionName === "singular" || completionName === "both") && args[0] === "completion") return true;
792
- if ((completionName === "plural" || completionName === "both") && args[0] === "completions") return true;
793
- }
794
- if (completionMode === "option" || completionMode === "both") for (const arg of args) {
795
- if ((completionName === "singular" || completionName === "both") && (arg === "--completion" || arg.startsWith("--completion="))) return true;
796
- if ((completionName === "plural" || completionName === "both") && (arg === "--completions" || arg.startsWith("--completions="))) return true;
813
+ const completionCommandConfig = norm(options.completion.command);
814
+ const completionOptionConfig = norm(options.completion.option);
815
+ const completionCommandNames = completionCommandConfig?.names ?? ["completion"];
816
+ const completionOptionNames = completionOptionConfig?.names ?? ["--completion"];
817
+ if (completionCommandConfig && completionCommandNames.includes(args[0])) return true;
818
+ if (completionOptionConfig) {
819
+ for (const arg of args) for (const name of completionOptionNames) if (arg === name || arg.startsWith(name + "=")) return true;
797
820
  }
798
821
  }
799
822
  return false;