@guanghechen/commander 4.7.3 → 4.7.5

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/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Change Log
2
2
 
3
+ ## 4.7.5
4
+
5
+ ### Patch Changes
6
+
7
+ - Fix help output ordering and remove duplicated negative options in help output.
8
+
9
+ ## 4.7.4
10
+
11
+ ### Patch Changes
12
+
13
+ - Fix commander completion metadata and negative option rules.
14
+ - Include built-in control options (help/version) in completion metadata.
15
+ - Prevent generating negative completions for reserved controls (--no-help/--no-version).
16
+ - Align completion option metadata with explicit type/args semantics.
17
+
3
18
  ## 4.7.3
4
19
 
5
20
  ### Patch Changes
@@ -715,8 +715,28 @@ class Command {
715
715
  const desc = metadata.length > 0 ? `${arg.desc} ${metadata.join(' ')}` : arg.desc;
716
716
  argumentsLines.push({ sig, desc });
717
717
  }
718
+ const sortedOptions = [...allOptions].sort((a, b) => {
719
+ const optionRank = (option) => {
720
+ if (option.long === 'help') {
721
+ return 0;
722
+ }
723
+ if (option.long === 'version') {
724
+ return 1;
725
+ }
726
+ if (option.required === true) {
727
+ return 2;
728
+ }
729
+ return 3;
730
+ };
731
+ const rankA = optionRank(a);
732
+ const rankB = optionRank(b);
733
+ if (rankA !== rankB) {
734
+ return rankA - rankB;
735
+ }
736
+ return camelToKebabCase(a.long).localeCompare(camelToKebabCase(b.long));
737
+ });
718
738
  const options = [];
719
- for (const opt of allOptions) {
739
+ for (const opt of sortedOptions) {
720
740
  const kebabLong = camelToKebabCase(opt.long);
721
741
  let sig = opt.short ? `-${opt.short}, ` : ' ';
722
742
  sig += `--${kebabLong}`;
@@ -734,21 +754,13 @@ class Command {
734
754
  desc += ` [choices: ${opt.choices.map(choice => JSON.stringify(choice)).join(', ')}]`;
735
755
  }
736
756
  options.push({ sig, desc });
737
- if (opt.type === 'boolean' &&
738
- opt.args === 'none' &&
739
- opt.long !== 'help' &&
740
- opt.long !== 'version') {
741
- options.push({
742
- sig: ` --no-${kebabLong}`,
743
- desc: `Negate --${kebabLong}`,
744
- });
745
- }
746
757
  }
747
758
  const commands = [];
748
759
  if (this.#subcommandsList.length > 0) {
749
760
  commands.push({ name: 'help', desc: 'Show help for a command' });
750
761
  }
751
- for (const entry of this.#subcommandsList) {
762
+ const sortedSubcommands = [...this.#subcommandsList].sort((a, b) => a.name.localeCompare(b.name));
763
+ for (const entry of sortedSubcommands) {
752
764
  let name = entry.name;
753
765
  if (entry.aliases.length > 0) {
754
766
  name += `, ${entry.aliases.join(', ')}`;
@@ -864,7 +876,15 @@ class Command {
864
876
  return ` ${outputLabel} ${desc}`;
865
877
  }
866
878
  getCompletionMeta() {
867
- const allOptions = this.#resolveOptionPolicy().mergedOptions;
879
+ const optionMap = new Map();
880
+ for (const option of this.#resolveOptionPolicy().mergedOptions) {
881
+ optionMap.set(option.long, option);
882
+ }
883
+ optionMap.set('help', BUILTIN_HELP_OPTION);
884
+ if (this.#supportsBuiltinVersion()) {
885
+ optionMap.set('version', BUILTIN_VERSION_OPTION);
886
+ }
887
+ const allOptions = Array.from(optionMap.values());
868
888
  const options = [];
869
889
  const argumentsMeta = [];
870
890
  for (const opt of allOptions) {
@@ -872,7 +892,8 @@ class Command {
872
892
  long: opt.long,
873
893
  short: opt.short,
874
894
  desc: opt.desc,
875
- takesValue: opt.args !== 'none',
895
+ type: opt.type,
896
+ args: opt.args,
876
897
  choices: opt.choices?.map(choice => String(choice)),
877
898
  });
878
899
  }
package/lib/cjs/node.cjs CHANGED
@@ -728,8 +728,28 @@ class Command {
728
728
  const desc = metadata.length > 0 ? `${arg.desc} ${metadata.join(' ')}` : arg.desc;
729
729
  argumentsLines.push({ sig, desc });
730
730
  }
731
+ const sortedOptions = [...allOptions].sort((a, b) => {
732
+ const optionRank = (option) => {
733
+ if (option.long === 'help') {
734
+ return 0;
735
+ }
736
+ if (option.long === 'version') {
737
+ return 1;
738
+ }
739
+ if (option.required === true) {
740
+ return 2;
741
+ }
742
+ return 3;
743
+ };
744
+ const rankA = optionRank(a);
745
+ const rankB = optionRank(b);
746
+ if (rankA !== rankB) {
747
+ return rankA - rankB;
748
+ }
749
+ return camelToKebabCase$1(a.long).localeCompare(camelToKebabCase$1(b.long));
750
+ });
731
751
  const options = [];
732
- for (const opt of allOptions) {
752
+ for (const opt of sortedOptions) {
733
753
  const kebabLong = camelToKebabCase$1(opt.long);
734
754
  let sig = opt.short ? `-${opt.short}, ` : ' ';
735
755
  sig += `--${kebabLong}`;
@@ -747,21 +767,13 @@ class Command {
747
767
  desc += ` [choices: ${opt.choices.map(choice => JSON.stringify(choice)).join(', ')}]`;
748
768
  }
749
769
  options.push({ sig, desc });
750
- if (opt.type === 'boolean' &&
751
- opt.args === 'none' &&
752
- opt.long !== 'help' &&
753
- opt.long !== 'version') {
754
- options.push({
755
- sig: ` --no-${kebabLong}`,
756
- desc: `Negate --${kebabLong}`,
757
- });
758
- }
759
770
  }
760
771
  const commands = [];
761
772
  if (this.#subcommandsList.length > 0) {
762
773
  commands.push({ name: 'help', desc: 'Show help for a command' });
763
774
  }
764
- for (const entry of this.#subcommandsList) {
775
+ const sortedSubcommands = [...this.#subcommandsList].sort((a, b) => a.name.localeCompare(b.name));
776
+ for (const entry of sortedSubcommands) {
765
777
  let name = entry.name;
766
778
  if (entry.aliases.length > 0) {
767
779
  name += `, ${entry.aliases.join(', ')}`;
@@ -877,7 +889,15 @@ class Command {
877
889
  return ` ${outputLabel} ${desc}`;
878
890
  }
879
891
  getCompletionMeta() {
880
- const allOptions = this.#resolveOptionPolicy().mergedOptions;
892
+ const optionMap = new Map();
893
+ for (const option of this.#resolveOptionPolicy().mergedOptions) {
894
+ optionMap.set(option.long, option);
895
+ }
896
+ optionMap.set('help', BUILTIN_HELP_OPTION);
897
+ if (this.#supportsBuiltinVersion()) {
898
+ optionMap.set('version', BUILTIN_VERSION_OPTION);
899
+ }
900
+ const allOptions = Array.from(optionMap.values());
881
901
  const options = [];
882
902
  const argumentsMeta = [];
883
903
  for (const opt of allOptions) {
@@ -885,7 +905,8 @@ class Command {
885
905
  long: opt.long,
886
906
  short: opt.short,
887
907
  desc: opt.desc,
888
- takesValue: opt.args !== 'none',
908
+ type: opt.type,
909
+ args: opt.args,
889
910
  choices: opt.choices?.map(choice => String(choice)),
890
911
  });
891
912
  }
@@ -2133,6 +2154,12 @@ class Coerce {
2133
2154
  function camelToKebabCase(str) {
2134
2155
  return str.replace(/[A-Z]/g, m => '-' + m.toLowerCase());
2135
2156
  }
2157
+ function canGenerateNegativeCompletion(opt) {
2158
+ return (opt.type === 'boolean' && opt.args === 'none' && opt.long !== 'help' && opt.long !== 'version');
2159
+ }
2160
+ function optionTakesValue(opt) {
2161
+ return opt.args !== 'none';
2162
+ }
2136
2163
  const COMPLETION_SHELL_STATE = Symbol('completion-shell-state');
2137
2164
  function getCommandPath(ctx) {
2138
2165
  const names = ctx.chain
@@ -2295,7 +2322,7 @@ class BashCompletion {
2295
2322
  if (opt.short)
2296
2323
  optParts.push(this.#escapeWord(`-${opt.short}`));
2297
2324
  optParts.push(this.#escapeWord(`--${kebabLong}`));
2298
- if (!opt.takesValue) {
2325
+ if (canGenerateNegativeCompletion(opt)) {
2299
2326
  optParts.push(this.#escapeWord(`--no-${kebabLong}`));
2300
2327
  }
2301
2328
  }
@@ -2327,7 +2354,7 @@ class BashCompletion {
2327
2354
  return words.map(choice => this.#escapeWord(choice)).join(' ');
2328
2355
  }
2329
2356
  #appendChoiceLogicForCommand(lines, indent, cmd, depth) {
2330
- const valueOptions = cmd.options.filter(opt => opt.takesValue);
2357
+ const valueOptions = cmd.options.filter(optionTakesValue);
2331
2358
  const valueOptionsWithChoices = valueOptions.filter(opt => opt.choices && opt.choices.length > 0);
2332
2359
  const valueLongPatterns = valueOptions.map(opt => `--${camelToKebabCase(opt.long)}`);
2333
2360
  const valueShortPatterns = valueOptions
@@ -2454,7 +2481,7 @@ class FishCompletion {
2454
2481
  line += ` -xa '${opt.choices.map(choice => this.#escapeChoice(choice)).join(' ')}'`;
2455
2482
  }
2456
2483
  lines.push(line);
2457
- if (!opt.takesValue) {
2484
+ if (canGenerateNegativeCompletion(opt)) {
2458
2485
  let noLine = `complete -c ${this.#programName}`;
2459
2486
  if (condition)
2460
2487
  noLine += ` -n '${condition}'`;
@@ -2464,11 +2491,11 @@ class FishCompletion {
2464
2491
  }
2465
2492
  }
2466
2493
  const valueOptionLongs = cmd.options
2467
- .filter(opt => opt.takesValue)
2494
+ .filter(optionTakesValue)
2468
2495
  .map(opt => camelToKebabCase(opt.long))
2469
2496
  .join(',');
2470
2497
  const valueOptionShorts = cmd.options
2471
- .filter(opt => opt.takesValue && opt.short)
2498
+ .filter(opt => optionTakesValue(opt) && opt.short)
2472
2499
  .map(opt => opt.short)
2473
2500
  .join(',');
2474
2501
  const argCount = cmd.arguments.length;
@@ -2667,7 +2694,7 @@ class PwshCompletion {
2667
2694
  ' if ($token.StartsWith("--")) {',
2668
2695
  ' if ($token.Contains("=")) { continue }',
2669
2696
  ' foreach ($opt in $cmd.options) {',
2670
- ' if ($token -eq "--$($opt.long)" -and $opt.takesValue) {',
2697
+ ' if ($token -eq "--$($opt.long)" -and $opt.args -ne "none") {',
2671
2698
  ' $expectValue = $true',
2672
2699
  ' break',
2673
2700
  ' }',
@@ -2677,7 +2704,7 @@ class PwshCompletion {
2677
2704
  ' if ($token.StartsWith("-") -and $token -ne "-") {',
2678
2705
  ' if ($token.Length -eq 2) {',
2679
2706
  ' foreach ($opt in $cmd.options) {',
2680
- ' if ($opt.short -and $token -eq "-$($opt.short)" -and $opt.takesValue) {',
2707
+ ' if ($opt.short -and $token -eq "-$($opt.short)" -and $opt.args -ne "none") {',
2681
2708
  ' $expectValue = $true',
2682
2709
  ' break',
2683
2710
  ' }',
@@ -2729,7 +2756,7 @@ class PwshCompletion {
2729
2756
  ' $opt.description',
2730
2757
  ' )',
2731
2758
  ' }',
2732
- ' if ($opt.isBoolean -and "--no-$($opt.long)" -like "$current*") {',
2759
+ ' if ($opt.canNegate -and "--no-$($opt.long)" -like "$current*") {',
2733
2760
  ' $completions += [System.Management.Automation.CompletionResult]::new(',
2734
2761
  ' "--no-$($opt.long)",',
2735
2762
  ' "no-$($opt.long)",',
@@ -2779,8 +2806,9 @@ class PwshCompletion {
2779
2806
  lines.push(`${indent} short = '${opt.short}'`);
2780
2807
  lines.push(`${indent} long = '${kebabLong}'`);
2781
2808
  lines.push(`${indent} description = '${this.#escape(opt.desc)}'`);
2782
- lines.push(`${indent} isBoolean = $${!opt.takesValue}`);
2783
- lines.push(`${indent} takesValue = $${opt.takesValue}`);
2809
+ lines.push(`${indent} type = '${opt.type}'`);
2810
+ lines.push(`${indent} args = '${opt.args}'`);
2811
+ lines.push(`${indent} canNegate = $${canGenerateNegativeCompletion(opt)}`);
2784
2812
  if (opt.choices) {
2785
2813
  lines.push(`${indent} choices = @('${opt.choices
2786
2814
  .map(choice => this.#escape(choice))
@@ -713,8 +713,28 @@ class Command {
713
713
  const desc = metadata.length > 0 ? `${arg.desc} ${metadata.join(' ')}` : arg.desc;
714
714
  argumentsLines.push({ sig, desc });
715
715
  }
716
+ const sortedOptions = [...allOptions].sort((a, b) => {
717
+ const optionRank = (option) => {
718
+ if (option.long === 'help') {
719
+ return 0;
720
+ }
721
+ if (option.long === 'version') {
722
+ return 1;
723
+ }
724
+ if (option.required === true) {
725
+ return 2;
726
+ }
727
+ return 3;
728
+ };
729
+ const rankA = optionRank(a);
730
+ const rankB = optionRank(b);
731
+ if (rankA !== rankB) {
732
+ return rankA - rankB;
733
+ }
734
+ return camelToKebabCase(a.long).localeCompare(camelToKebabCase(b.long));
735
+ });
716
736
  const options = [];
717
- for (const opt of allOptions) {
737
+ for (const opt of sortedOptions) {
718
738
  const kebabLong = camelToKebabCase(opt.long);
719
739
  let sig = opt.short ? `-${opt.short}, ` : ' ';
720
740
  sig += `--${kebabLong}`;
@@ -732,21 +752,13 @@ class Command {
732
752
  desc += ` [choices: ${opt.choices.map(choice => JSON.stringify(choice)).join(', ')}]`;
733
753
  }
734
754
  options.push({ sig, desc });
735
- if (opt.type === 'boolean' &&
736
- opt.args === 'none' &&
737
- opt.long !== 'help' &&
738
- opt.long !== 'version') {
739
- options.push({
740
- sig: ` --no-${kebabLong}`,
741
- desc: `Negate --${kebabLong}`,
742
- });
743
- }
744
755
  }
745
756
  const commands = [];
746
757
  if (this.#subcommandsList.length > 0) {
747
758
  commands.push({ name: 'help', desc: 'Show help for a command' });
748
759
  }
749
- for (const entry of this.#subcommandsList) {
760
+ const sortedSubcommands = [...this.#subcommandsList].sort((a, b) => a.name.localeCompare(b.name));
761
+ for (const entry of sortedSubcommands) {
750
762
  let name = entry.name;
751
763
  if (entry.aliases.length > 0) {
752
764
  name += `, ${entry.aliases.join(', ')}`;
@@ -862,7 +874,15 @@ class Command {
862
874
  return ` ${outputLabel} ${desc}`;
863
875
  }
864
876
  getCompletionMeta() {
865
- const allOptions = this.#resolveOptionPolicy().mergedOptions;
877
+ const optionMap = new Map();
878
+ for (const option of this.#resolveOptionPolicy().mergedOptions) {
879
+ optionMap.set(option.long, option);
880
+ }
881
+ optionMap.set('help', BUILTIN_HELP_OPTION);
882
+ if (this.#supportsBuiltinVersion()) {
883
+ optionMap.set('version', BUILTIN_VERSION_OPTION);
884
+ }
885
+ const allOptions = Array.from(optionMap.values());
866
886
  const options = [];
867
887
  const argumentsMeta = [];
868
888
  for (const opt of allOptions) {
@@ -870,7 +890,8 @@ class Command {
870
890
  long: opt.long,
871
891
  short: opt.short,
872
892
  desc: opt.desc,
873
- takesValue: opt.args !== 'none',
893
+ type: opt.type,
894
+ args: opt.args,
874
895
  choices: opt.choices?.map(choice => String(choice)),
875
896
  });
876
897
  }
package/lib/esm/node.mjs CHANGED
@@ -726,8 +726,28 @@ class Command {
726
726
  const desc = metadata.length > 0 ? `${arg.desc} ${metadata.join(' ')}` : arg.desc;
727
727
  argumentsLines.push({ sig, desc });
728
728
  }
729
+ const sortedOptions = [...allOptions].sort((a, b) => {
730
+ const optionRank = (option) => {
731
+ if (option.long === 'help') {
732
+ return 0;
733
+ }
734
+ if (option.long === 'version') {
735
+ return 1;
736
+ }
737
+ if (option.required === true) {
738
+ return 2;
739
+ }
740
+ return 3;
741
+ };
742
+ const rankA = optionRank(a);
743
+ const rankB = optionRank(b);
744
+ if (rankA !== rankB) {
745
+ return rankA - rankB;
746
+ }
747
+ return camelToKebabCase$1(a.long).localeCompare(camelToKebabCase$1(b.long));
748
+ });
729
749
  const options = [];
730
- for (const opt of allOptions) {
750
+ for (const opt of sortedOptions) {
731
751
  const kebabLong = camelToKebabCase$1(opt.long);
732
752
  let sig = opt.short ? `-${opt.short}, ` : ' ';
733
753
  sig += `--${kebabLong}`;
@@ -745,21 +765,13 @@ class Command {
745
765
  desc += ` [choices: ${opt.choices.map(choice => JSON.stringify(choice)).join(', ')}]`;
746
766
  }
747
767
  options.push({ sig, desc });
748
- if (opt.type === 'boolean' &&
749
- opt.args === 'none' &&
750
- opt.long !== 'help' &&
751
- opt.long !== 'version') {
752
- options.push({
753
- sig: ` --no-${kebabLong}`,
754
- desc: `Negate --${kebabLong}`,
755
- });
756
- }
757
768
  }
758
769
  const commands = [];
759
770
  if (this.#subcommandsList.length > 0) {
760
771
  commands.push({ name: 'help', desc: 'Show help for a command' });
761
772
  }
762
- for (const entry of this.#subcommandsList) {
773
+ const sortedSubcommands = [...this.#subcommandsList].sort((a, b) => a.name.localeCompare(b.name));
774
+ for (const entry of sortedSubcommands) {
763
775
  let name = entry.name;
764
776
  if (entry.aliases.length > 0) {
765
777
  name += `, ${entry.aliases.join(', ')}`;
@@ -875,7 +887,15 @@ class Command {
875
887
  return ` ${outputLabel} ${desc}`;
876
888
  }
877
889
  getCompletionMeta() {
878
- const allOptions = this.#resolveOptionPolicy().mergedOptions;
890
+ const optionMap = new Map();
891
+ for (const option of this.#resolveOptionPolicy().mergedOptions) {
892
+ optionMap.set(option.long, option);
893
+ }
894
+ optionMap.set('help', BUILTIN_HELP_OPTION);
895
+ if (this.#supportsBuiltinVersion()) {
896
+ optionMap.set('version', BUILTIN_VERSION_OPTION);
897
+ }
898
+ const allOptions = Array.from(optionMap.values());
879
899
  const options = [];
880
900
  const argumentsMeta = [];
881
901
  for (const opt of allOptions) {
@@ -883,7 +903,8 @@ class Command {
883
903
  long: opt.long,
884
904
  short: opt.short,
885
905
  desc: opt.desc,
886
- takesValue: opt.args !== 'none',
906
+ type: opt.type,
907
+ args: opt.args,
887
908
  choices: opt.choices?.map(choice => String(choice)),
888
909
  });
889
910
  }
@@ -2131,6 +2152,12 @@ class Coerce {
2131
2152
  function camelToKebabCase(str) {
2132
2153
  return str.replace(/[A-Z]/g, m => '-' + m.toLowerCase());
2133
2154
  }
2155
+ function canGenerateNegativeCompletion(opt) {
2156
+ return (opt.type === 'boolean' && opt.args === 'none' && opt.long !== 'help' && opt.long !== 'version');
2157
+ }
2158
+ function optionTakesValue(opt) {
2159
+ return opt.args !== 'none';
2160
+ }
2134
2161
  const COMPLETION_SHELL_STATE = Symbol('completion-shell-state');
2135
2162
  function getCommandPath(ctx) {
2136
2163
  const names = ctx.chain
@@ -2293,7 +2320,7 @@ class BashCompletion {
2293
2320
  if (opt.short)
2294
2321
  optParts.push(this.#escapeWord(`-${opt.short}`));
2295
2322
  optParts.push(this.#escapeWord(`--${kebabLong}`));
2296
- if (!opt.takesValue) {
2323
+ if (canGenerateNegativeCompletion(opt)) {
2297
2324
  optParts.push(this.#escapeWord(`--no-${kebabLong}`));
2298
2325
  }
2299
2326
  }
@@ -2325,7 +2352,7 @@ class BashCompletion {
2325
2352
  return words.map(choice => this.#escapeWord(choice)).join(' ');
2326
2353
  }
2327
2354
  #appendChoiceLogicForCommand(lines, indent, cmd, depth) {
2328
- const valueOptions = cmd.options.filter(opt => opt.takesValue);
2355
+ const valueOptions = cmd.options.filter(optionTakesValue);
2329
2356
  const valueOptionsWithChoices = valueOptions.filter(opt => opt.choices && opt.choices.length > 0);
2330
2357
  const valueLongPatterns = valueOptions.map(opt => `--${camelToKebabCase(opt.long)}`);
2331
2358
  const valueShortPatterns = valueOptions
@@ -2452,7 +2479,7 @@ class FishCompletion {
2452
2479
  line += ` -xa '${opt.choices.map(choice => this.#escapeChoice(choice)).join(' ')}'`;
2453
2480
  }
2454
2481
  lines.push(line);
2455
- if (!opt.takesValue) {
2482
+ if (canGenerateNegativeCompletion(opt)) {
2456
2483
  let noLine = `complete -c ${this.#programName}`;
2457
2484
  if (condition)
2458
2485
  noLine += ` -n '${condition}'`;
@@ -2462,11 +2489,11 @@ class FishCompletion {
2462
2489
  }
2463
2490
  }
2464
2491
  const valueOptionLongs = cmd.options
2465
- .filter(opt => opt.takesValue)
2492
+ .filter(optionTakesValue)
2466
2493
  .map(opt => camelToKebabCase(opt.long))
2467
2494
  .join(',');
2468
2495
  const valueOptionShorts = cmd.options
2469
- .filter(opt => opt.takesValue && opt.short)
2496
+ .filter(opt => optionTakesValue(opt) && opt.short)
2470
2497
  .map(opt => opt.short)
2471
2498
  .join(',');
2472
2499
  const argCount = cmd.arguments.length;
@@ -2665,7 +2692,7 @@ class PwshCompletion {
2665
2692
  ' if ($token.StartsWith("--")) {',
2666
2693
  ' if ($token.Contains("=")) { continue }',
2667
2694
  ' foreach ($opt in $cmd.options) {',
2668
- ' if ($token -eq "--$($opt.long)" -and $opt.takesValue) {',
2695
+ ' if ($token -eq "--$($opt.long)" -and $opt.args -ne "none") {',
2669
2696
  ' $expectValue = $true',
2670
2697
  ' break',
2671
2698
  ' }',
@@ -2675,7 +2702,7 @@ class PwshCompletion {
2675
2702
  ' if ($token.StartsWith("-") -and $token -ne "-") {',
2676
2703
  ' if ($token.Length -eq 2) {',
2677
2704
  ' foreach ($opt in $cmd.options) {',
2678
- ' if ($opt.short -and $token -eq "-$($opt.short)" -and $opt.takesValue) {',
2705
+ ' if ($opt.short -and $token -eq "-$($opt.short)" -and $opt.args -ne "none") {',
2679
2706
  ' $expectValue = $true',
2680
2707
  ' break',
2681
2708
  ' }',
@@ -2727,7 +2754,7 @@ class PwshCompletion {
2727
2754
  ' $opt.description',
2728
2755
  ' )',
2729
2756
  ' }',
2730
- ' if ($opt.isBoolean -and "--no-$($opt.long)" -like "$current*") {',
2757
+ ' if ($opt.canNegate -and "--no-$($opt.long)" -like "$current*") {',
2731
2758
  ' $completions += [System.Management.Automation.CompletionResult]::new(',
2732
2759
  ' "--no-$($opt.long)",',
2733
2760
  ' "no-$($opt.long)",',
@@ -2777,8 +2804,9 @@ class PwshCompletion {
2777
2804
  lines.push(`${indent} short = '${opt.short}'`);
2778
2805
  lines.push(`${indent} long = '${kebabLong}'`);
2779
2806
  lines.push(`${indent} description = '${this.#escape(opt.desc)}'`);
2780
- lines.push(`${indent} isBoolean = $${!opt.takesValue}`);
2781
- lines.push(`${indent} takesValue = $${opt.takesValue}`);
2807
+ lines.push(`${indent} type = '${opt.type}'`);
2808
+ lines.push(`${indent} args = '${opt.args}'`);
2809
+ lines.push(`${indent} canNegate = $${canGenerateNegativeCompletion(opt)}`);
2782
2810
  if (opt.choices) {
2783
2811
  lines.push(`${indent} choices = @('${opt.choices
2784
2812
  .map(choice => this.#escape(choice))
@@ -365,8 +365,10 @@ interface ICompletionOptionMeta {
365
365
  short?: string;
366
366
  /** Description */
367
367
  desc: string;
368
- /** Whether option takes value (args !== 'none') */
369
- takesValue: boolean;
368
+ /** Option type */
369
+ type: ICommandOptionType;
370
+ /** Option args mode */
371
+ args: ICommandOptionArgs;
370
372
  /** Allowed values */
371
373
  choices?: string[];
372
374
  }
@@ -365,8 +365,10 @@ interface ICompletionOptionMeta {
365
365
  short?: string;
366
366
  /** Description */
367
367
  desc: string;
368
- /** Whether option takes value (args !== 'none') */
369
- takesValue: boolean;
368
+ /** Option type */
369
+ type: ICommandOptionType;
370
+ /** Option args mode */
371
+ args: ICommandOptionArgs;
370
372
  /** Allowed values */
371
373
  choices?: string[];
372
374
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guanghechen/commander",
3
- "version": "4.7.3",
3
+ "version": "4.7.5",
4
4
  "description": "A minimal, type-safe command-line interface builder with fluent API",
5
5
  "author": {
6
6
  "name": "guanghechen",