Skip to content

Commit 1ae39ef

Browse files
committed
Complete non-repeatable flag & option instances only once in fish.
Signed-off-by: Ross Goldberg <[email protected]>
1 parent d30ab56 commit 1ae39ef

File tree

3 files changed

+168
-89
lines changed

3 files changed

+168
-89
lines changed

Sources/ArgumentParser/Completions/FishCompletionsGenerator.swift

Lines changed: 52 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,36 @@ extension ToolInfoV0 {
2424
extension CommandInfoV0 {
2525
fileprivate var fishCompletionScript: String {
2626
"""
27-
function \(shouldOfferCompletionsForFunctionName) -a expected_commands expected_positional_index positional_index_comparison
28-
set -l unparsed_tokens (\(tokensFunctionName) -pc)
27+
function \(shouldOfferCompletionsForFlagsOrOptionsFunctionName) -a expected_commands
28+
set -l non_repeating_flags_or_options $argv[2..]
29+
30+
set -l non_repeating_flags_or_options_absent 0
2931
set -l positional_index 0
3032
set -l commands
33+
\(parseTokensFunctionName)
34+
test "$commands" = "$expected_commands"; and return $non_repeating_flags_or_options_absent
35+
end
3136
37+
function \(shouldOfferCompletionsForPositionalFunctionName) -a expected_commands expected_positional_index positional_index_comparison
3238
if test -z $positional_index_comparison
3339
set positional_index_comparison -eq
3440
end
3541
42+
set -l non_repeating_flags_or_options
43+
set -l non_repeating_flags_or_options_absent 0
44+
set -l positional_index 0
45+
set -l commands
46+
\(parseTokensFunctionName)
47+
test "$commands" = "$expected_commands" -a \\( "$positional_index" "$positional_index_comparison" "$expected_positional_index" \\)
48+
end
49+
50+
function \(parseTokensFunctionName) -S
51+
set -l unparsed_tokens (\(tokensFunctionName) -pc)
52+
set -l present_flags_and_options
53+
3654
switch $unparsed_tokens[1]
3755
\(commandCases)
3856
end
39-
40-
test "$commands" = "$expected_commands" -a \\( -z "$expected_positional_index" -o "$positional_index" "$positional_index_comparison" "$expected_positional_index" \\)
4157
end
4258
4359
function \(tokensFunctionName)
@@ -48,9 +64,8 @@ extension CommandInfoV0 {
4864
end
4965
end
5066
51-
function \(parseSubcommandFunctionName) -S
67+
function \(parseSubcommandFunctionName) -S -a positional_count
5268
argparse -s r -- $argv
53-
set -l positional_count $argv[1]
5469
set -l option_specs $argv[2..]
5570
5671
set -a commands $unparsed_tokens[1]
@@ -62,8 +77,16 @@ extension CommandInfoV0 {
6277
argparse -sn "$commands" $option_specs -- $unparsed_tokens 2> /dev/null
6378
set unparsed_tokens $argv
6479
set positional_index (math $positional_index + 1)
80+
81+
for non_repeating_flag_or_option in $non_repeating_flags_or_options
82+
if set -ql _flag_$non_repeating_flag_or_option
83+
set non_repeating_flags_or_options_absent 1
84+
break
85+
end
86+
end
87+
6588
if test (count $unparsed_tokens) -eq 0 -o \\( -z "$_flag_r" -a "$positional_index" -gt "$positional_count" \\)
66-
return 0
89+
break
6790
end
6891
set -e unparsed_tokens[1]
6992
end
@@ -117,11 +140,7 @@ extension CommandInfoV0 {
117140
}
118141

119142
private var completions: [String] {
120-
let prefix = """
121-
complete -c '\(initialCommand)'\
122-
-n '\(shouldOfferCompletionsForFunctionName)\
123-
"\(commandContext.joined(separator: separator))"
124-
"""
143+
let prefix = "complete -c '\(initialCommand)' -n '"
125144

126145
let subcommands = (subcommands ?? []).filter(\.shouldDisplay)
127146

@@ -145,12 +164,15 @@ extension CommandInfoV0 {
145164
\(prefix)\(
146165
arg.kind == .positional
147166
? """
148-
\({
167+
\(shouldOfferCompletionsForPositionalFunctionName) "\(commandContext.joined(separator: separator))" \({
149168
positionalIndex += 1
150-
return " \(positionalIndex)\(repeatingPositionalComparison)"
169+
return "\(positionalIndex)\(repeatingPositionalComparison)"
151170
}())
152171
"""
153-
: ""
172+
: """
173+
\(shouldOfferCompletionsForFlagsOrOptionsFunctionName) "\(commandContext.joined(separator: separator))"\
174+
\((arg.isRepeating ? [] : arg.names ?? []).map { " \($0.name)" }.sorted().joined())
175+
"""
154176
)' \(argumentSegments(arg).joined(separator: separator))
155177
"""
156178
}
@@ -160,7 +182,10 @@ extension CommandInfoV0 {
160182
return
161183
argumentCompletions
162184
+ subcommands.map {
163-
"\(prefix) \(positionalIndex)' -fa '\($0.commandName)' -d '\($0.abstract?.fishEscapeForSingleQuotedString() ?? "")'"
185+
"""
186+
\(prefix)\(shouldOfferCompletionsForPositionalFunctionName) "\(commandContext.joined(separator: separator))"\
187+
\(positionalIndex)' -fa '\($0.commandName)' -d '\($0.abstract?.fishEscapeForSingleQuotedString() ?? "")'
188+
"""
164189
}
165190
+ subcommands.flatMap(\.completions)
166191
}
@@ -262,8 +287,16 @@ extension CommandInfoV0 {
262287
"""
263288
}
264289

265-
private var shouldOfferCompletionsForFunctionName: String {
266-
"\(completionFunctionPrefix)_should_offer_completions_for"
290+
private var shouldOfferCompletionsForFlagsOrOptionsFunctionName: String {
291+
"\(completionFunctionPrefix)_should_offer_completions_for_flags_or_options"
292+
}
293+
294+
private var shouldOfferCompletionsForPositionalFunctionName: String {
295+
"\(completionFunctionPrefix)_should_offer_completions_for_positional"
296+
}
297+
298+
private var parseTokensFunctionName: String {
299+
"\(completionFunctionPrefix)_parse_tokens"
267300
}
268301

269302
private var tokensFunctionName: String {
@@ -304,7 +337,7 @@ extension ArgumentInfoV0 {
304337
private func optionSpecRequiresValue(_ optionSpec: String) -> String {
305338
switch kind {
306339
case .option:
307-
return "\(optionSpec)="
340+
return "\(optionSpec)=\(isRepeating ? "+" : "")"
308341
default:
309342
return optionSpec
310343
}
Lines changed: 63 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,30 @@
1-
function __math_should_offer_completions_for -a expected_commands expected_positional_index positional_index_comparison
2-
set -l unparsed_tokens (__math_tokens -pc)
1+
function __math_should_offer_completions_for_flags_or_options -a expected_commands
2+
set -l non_repeating_flags_or_options $argv[2..]
3+
4+
set -l non_repeating_flags_or_options_absent 0
35
set -l positional_index 0
46
set -l commands
7+
__math_parse_tokens
8+
test "$commands" = "$expected_commands"; and return $non_repeating_flags_or_options_absent
9+
end
510

11+
function __math_should_offer_completions_for_positional -a expected_commands expected_positional_index positional_index_comparison
612
if test -z $positional_index_comparison
713
set positional_index_comparison -eq
814
end
915

16+
set -l non_repeating_flags_or_options
17+
set -l non_repeating_flags_or_options_absent 0
18+
set -l positional_index 0
19+
set -l commands
20+
__math_parse_tokens
21+
test "$commands" = "$expected_commands" -a \( "$positional_index" "$positional_index_comparison" "$expected_positional_index" \)
22+
end
23+
24+
function __math_parse_tokens -S
25+
set -l unparsed_tokens (__math_tokens -pc)
26+
set -l present_flags_and_options
27+
1028
switch $unparsed_tokens[1]
1129
case 'math'
1230
__math_parse_subcommand 0 'version' 'h/help'
@@ -29,8 +47,6 @@ function __math_should_offer_completions_for -a expected_commands expected_posit
2947
__math_parse_subcommand -r 1 'version'
3048
end
3149
end
32-
33-
test "$commands" = "$expected_commands" -a \( -z "$expected_positional_index" -o "$positional_index" "$positional_index_comparison" "$expected_positional_index" \)
3450
end
3551

3652
function __math_tokens
@@ -41,9 +57,8 @@ function __math_tokens
4157
end
4258
end
4359

44-
function __math_parse_subcommand -S
60+
function __math_parse_subcommand -S -a positional_count
4561
argparse -s r -- $argv
46-
set -l positional_count $argv[1]
4762
set -l option_specs $argv[2..]
4863

4964
set -a commands $unparsed_tokens[1]
@@ -55,8 +70,16 @@ function __math_parse_subcommand -S
5570
argparse -sn "$commands" $option_specs -- $unparsed_tokens 2> /dev/null
5671
set unparsed_tokens $argv
5772
set positional_index (math $positional_index + 1)
73+
74+
for non_repeating_flag_or_option in $non_repeating_flags_or_options
75+
if set -ql _flag_$non_repeating_flag_or_option
76+
set non_repeating_flags_or_options_absent 1
77+
break
78+
end
79+
end
80+
5881
if test (count $unparsed_tokens) -eq 0 -o \( -z "$_flag_r" -a "$positional_index" -gt "$positional_count" \)
59-
return 0
82+
break
6083
end
6184
set -e unparsed_tokens[1]
6285
end
@@ -82,36 +105,36 @@ function __math_custom_completion
82105
end
83106
84107
complete -c 'math' -f
85-
complete -c 'math' -n '__math_should_offer_completions_for "math"' -l 'version' -d 'Show the version.'
86-
complete -c 'math' -n '__math_should_offer_completions_for "math"' -s 'h' -l 'help' -d 'Show help information.'
87-
complete -c 'math' -n '__math_should_offer_completions_for "math" 1' -fa 'add' -d 'Print the sum of the values.'
88-
complete -c 'math' -n '__math_should_offer_completions_for "math" 1' -fa 'multiply' -d 'Print the product of the values.'
89-
complete -c 'math' -n '__math_should_offer_completions_for "math" 1' -fa 'stats' -d 'Calculate descriptive statistics.'
90-
complete -c 'math' -n '__math_should_offer_completions_for "math" 1' -fa 'help' -d 'Show subcommand help information.'
91-
complete -c 'math' -n '__math_should_offer_completions_for "math add"' -l 'hex-output' -s 'x' -d 'Use hexadecimal notation for the result.'
92-
complete -c 'math' -n '__math_should_offer_completions_for "math add"' -l 'version' -d 'Show the version.'
93-
complete -c 'math' -n '__math_should_offer_completions_for "math add"' -s 'h' -l 'help' -d 'Show help information.'
94-
complete -c 'math' -n '__math_should_offer_completions_for "math multiply"' -l 'hex-output' -s 'x' -d 'Use hexadecimal notation for the result.'
95-
complete -c 'math' -n '__math_should_offer_completions_for "math multiply"' -l 'version' -d 'Show the version.'
96-
complete -c 'math' -n '__math_should_offer_completions_for "math multiply"' -s 'h' -l 'help' -d 'Show help information.'
97-
complete -c 'math' -n '__math_should_offer_completions_for "math stats"' -l 'version' -d 'Show the version.'
98-
complete -c 'math' -n '__math_should_offer_completions_for "math stats"' -s 'h' -l 'help' -d 'Show help information.'
99-
complete -c 'math' -n '__math_should_offer_completions_for "math stats" 1' -fa 'average' -d 'Print the average of the values.'
100-
complete -c 'math' -n '__math_should_offer_completions_for "math stats" 1' -fa 'stdev' -d 'Print the standard deviation of the values.'
101-
complete -c 'math' -n '__math_should_offer_completions_for "math stats" 1' -fa 'quantiles' -d 'Print the quantiles of the values (TBD).'
102-
complete -c 'math' -n '__math_should_offer_completions_for "math stats average"' -l 'kind' -d 'The kind of average to provide.' -rfka 'mean median mode'
103-
complete -c 'math' -n '__math_should_offer_completions_for "math stats average"' -l 'version' -d 'Show the version.'
104-
complete -c 'math' -n '__math_should_offer_completions_for "math stats average"' -s 'h' -l 'help' -d 'Show help information.'
105-
complete -c 'math' -n '__math_should_offer_completions_for "math stats stdev"' -l 'version' -d 'Show the version.'
106-
complete -c 'math' -n '__math_should_offer_completions_for "math stats stdev"' -s 'h' -l 'help' -d 'Show help information.'
107-
complete -c 'math' -n '__math_should_offer_completions_for "math stats quantiles" 1' -fka 'alphabet alligator branch braggart'
108-
complete -c 'math' -n '__math_should_offer_completions_for "math stats quantiles" 2' -fka '(__math_custom_completion ---completion stats quantiles -- positional@1 (count (__math_tokens -pc)) (__math_tokens -tC))'
109-
complete -c 'math' -n '__math_should_offer_completions_for "math stats quantiles" 3' -fka '(__math_custom_completion ---completion stats quantiles -- positional@2)'
110-
complete -c 'math' -n '__math_should_offer_completions_for "math stats quantiles"' -l 'file' -rfa '(set -l exts \'txt\' \'md\';for p in (string match -e -- \'*/\' (commandline -t);or printf \n)*.{$exts};printf %s\n $p;end;__fish_complete_directories (commandline -t) \'\')'
111-
complete -c 'math' -n '__math_should_offer_completions_for "math stats quantiles"' -l 'directory' -rfa '(__math_complete_directories)'
112-
complete -c 'math' -n '__math_should_offer_completions_for "math stats quantiles"' -l 'shell' -rfka '(head -100 \'/usr/share/dict/words\' | tail -50)'
113-
complete -c 'math' -n '__math_should_offer_completions_for "math stats quantiles"' -l 'custom' -rfka '(__math_custom_completion ---completion stats quantiles -- --custom (count (__math_tokens -pc)) (__math_tokens -tC))'
114-
complete -c 'math' -n '__math_should_offer_completions_for "math stats quantiles"' -l 'custom-deprecated' -rfka '(__math_custom_completion ---completion stats quantiles -- --custom-deprecated)'
115-
complete -c 'math' -n '__math_should_offer_completions_for "math stats quantiles"' -l 'version' -d 'Show the version.'
116-
complete -c 'math' -n '__math_should_offer_completions_for "math stats quantiles"' -s 'h' -l 'help' -d 'Show help information.'
117-
complete -c 'math' -n '__math_should_offer_completions_for "math help"' -l 'version' -d 'Show the version.'
108+
complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math" version' -l 'version' -d 'Show the version.'
109+
complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math" h help' -s 'h' -l 'help' -d 'Show help information.'
110+
complete -c 'math' -n '__math_should_offer_completions_for_positional "math" 1' -fa 'add' -d 'Print the sum of the values.'
111+
complete -c 'math' -n '__math_should_offer_completions_for_positional "math" 1' -fa 'multiply' -d 'Print the product of the values.'
112+
complete -c 'math' -n '__math_should_offer_completions_for_positional "math" 1' -fa 'stats' -d 'Calculate descriptive statistics.'
113+
complete -c 'math' -n '__math_should_offer_completions_for_positional "math" 1' -fa 'help' -d 'Show subcommand help information.'
114+
complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math add" hex-output x' -l 'hex-output' -s 'x' -d 'Use hexadecimal notation for the result.'
115+
complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math add" version' -l 'version' -d 'Show the version.'
116+
complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math add" h help' -s 'h' -l 'help' -d 'Show help information.'
117+
complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math multiply" hex-output x' -l 'hex-output' -s 'x' -d 'Use hexadecimal notation for the result.'
118+
complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math multiply" version' -l 'version' -d 'Show the version.'
119+
complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math multiply" h help' -s 'h' -l 'help' -d 'Show help information.'
120+
complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math stats" version' -l 'version' -d 'Show the version.'
121+
complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math stats" h help' -s 'h' -l 'help' -d 'Show help information.'
122+
complete -c 'math' -n '__math_should_offer_completions_for_positional "math stats" 1' -fa 'average' -d 'Print the average of the values.'
123+
complete -c 'math' -n '__math_should_offer_completions_for_positional "math stats" 1' -fa 'stdev' -d 'Print the standard deviation of the values.'
124+
complete -c 'math' -n '__math_should_offer_completions_for_positional "math stats" 1' -fa 'quantiles' -d 'Print the quantiles of the values (TBD).'
125+
complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math stats average" kind' -l 'kind' -d 'The kind of average to provide.' -rfka 'mean median mode'
126+
complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math stats average" version' -l 'version' -d 'Show the version.'
127+
complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math stats average" h help' -s 'h' -l 'help' -d 'Show help information.'
128+
complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math stats stdev" version' -l 'version' -d 'Show the version.'
129+
complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math stats stdev" h help' -s 'h' -l 'help' -d 'Show help information.'
130+
complete -c 'math' -n '__math_should_offer_completions_for_positional "math stats quantiles" 1' -fka 'alphabet alligator branch braggart'
131+
complete -c 'math' -n '__math_should_offer_completions_for_positional "math stats quantiles" 2' -fka '(__math_custom_completion ---completion stats quantiles -- positional@1 (count (__math_tokens -pc)) (__math_tokens -tC))'
132+
complete -c 'math' -n '__math_should_offer_completions_for_positional "math stats quantiles" 3' -fka '(__math_custom_completion ---completion stats quantiles -- positional@2)'
133+
complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math stats quantiles" file' -l 'file' -rfa '(set -l exts \'txt\' \'md\';for p in (string match -e -- \'*/\' (commandline -t);or printf \n)*.{$exts};printf %s\n $p;end;__fish_complete_directories (commandline -t) \'\')'
134+
complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math stats quantiles" directory' -l 'directory' -rfa '(__math_complete_directories)'
135+
complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math stats quantiles" shell' -l 'shell' -rfka '(head -100 \'/usr/share/dict/words\' | tail -50)'
136+
complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math stats quantiles" custom' -l 'custom' -rfka '(__math_custom_completion ---completion stats quantiles -- --custom (count (__math_tokens -pc)) (__math_tokens -tC))'
137+
complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math stats quantiles" custom-deprecated' -l 'custom-deprecated' -rfka '(__math_custom_completion ---completion stats quantiles -- --custom-deprecated)'
138+
complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math stats quantiles" version' -l 'version' -d 'Show the version.'
139+
complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math stats quantiles" h help' -s 'h' -l 'help' -d 'Show help information.'
140+
complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math help" version' -l 'version' -d 'Show the version.'

0 commit comments

Comments
 (0)