diff --git a/Sources/ArgumentParser/Completions/BashCompletionsGenerator.swift b/Sources/ArgumentParser/Completions/BashCompletionsGenerator.swift index c4e7c914..16dfa1f5 100644 --- a/Sources/ArgumentParser/Completions/BashCompletionsGenerator.swift +++ b/Sources/ArgumentParser/Completions/BashCompletionsGenerator.swift @@ -48,15 +48,17 @@ extension CommandInfoV0 { # # required variables: # - # - flags: the flags that the current (sub)command can accept - # - options: the options that the current (sub)command can accept + # - repeating_flags: the repeating flags that the current (sub)command can accept + # - non_repeating_flags: the non-repeating flags that the current (sub)command can accept + # - repeating_options: the repeating options that the current (sub)command can accept + # - non_repeating_options: the non-repeating options that the current (sub)command can accept # - positional_number: value ignored # - unparsed_words: unparsed words from the current command line # # modified variables: # - # - flags: remove flags for this (sub)command that are already on the command line - # - options: remove options for this (sub)command that are already on the command line + # - non_repeating_flags: remove flags for this (sub)command that are already on the command line + # - non_repeating_options: remove options for this (sub)command that are already on the command line # - positional_number: set to the current positional number # - unparsed_words: remove all flags, options, and option values for this (sub)command \(offerFlagsOptionsFunctionName)() { @@ -93,26 +95,26 @@ extension CommandInfoV0 { # ${word} is a flag or an option # If ${word} is an option, mark that the next word to be parsed is an option value local option - for option in "${options[@]}"; do + for option in "${repeating_options[@]}" "${non_repeating_options[@]}"; do [[ "${word}" = "${option}" ]] && is_parsing_option_value=true && break done - # Remove ${word} from ${flags} or ${options} so it isn't offered again + # Remove ${word} from ${non_repeating_flags} or ${non_repeating_options} so it isn't offered again local not_found=true local -i index - for index in "${!flags[@]}"; do - if [[ "${flags[${index}]}" = "${word}" ]]; then - unset "flags[${index}]" - flags=("${flags[@]}") + for index in "${!non_repeating_flags[@]}"; do + if [[ "${non_repeating_flags[${index}]}" = "${word}" ]]; then + unset "non_repeating_flags[${index}]" + non_repeating_flags=("${non_repeating_flags[@]}") not_found=false break fi done if "${not_found}"; then - for index in "${!options[@]}"; do - if [[ "${options[${index}]}" = "${word}" ]]; then - unset "options[${index}]" - options=("${options[@]}") + for index in "${!non_repeating_flags[@]}"; do + if [[ "${non_repeating_flags[${index}]}" = "${word}" ]]; then + unset "non_repeating_flags[${index}]" + non_repeating_flags=("${non_repeating_flags[@]}") break fi done @@ -124,7 +126,7 @@ extension CommandInfoV0 { fi # ${word} is neither a flag, nor an option, nor an option value - if [[ "${positional_number}" -lt "${positional_count}" ]]; then + if [[ "${positional_number}" -lt "${positional_count}" || "${positional_count}" -lt 0 ]]; then # ${word} is a positional ((positional_number++)) unset "unparsed_words[${word_index}]" @@ -147,7 +149,7 @@ extension CommandInfoV0 { && ! "${is_parsing_option_value}"\\ && [[ ("${cur}" = -* && "${positional_number}" -ge 0) || "${positional_number}" -eq -1 ]] then - COMPREPLY+=($(compgen -W "${flags[*]} ${options[*]}" -- "${cur}")) + COMPREPLY+=($(compgen -W "${repeating_flags[*]} ${non_repeating_flags[*]} ${repeating_options[*]} ${non_repeating_options[*]}" -- "${cur}")) fi } @@ -211,13 +213,20 @@ extension CommandInfoV0 { let positionalArguments = positionalArguments - let flagCompletions = flagCompletions - let optionCompletions = optionCompletions - if !flagCompletions.isEmpty || !optionCompletions.isEmpty { + let arguments = arguments ?? [] + + let flags = arguments.filter { $0.kind == .flag } + let options = arguments.filter { $0.kind == .option } + if !flags.flatMap(\.completionWords).isEmpty + || !options.flatMap(\.completionWords).isEmpty + { result += """ - \(declareTopLevelArray)flags=(\(flagCompletions.joined(separator: " "))) - \(declareTopLevelArray)options=(\(optionCompletions.joined(separator: " "))) - \(offerFlagsOptionsFunctionName) \(positionalArguments.count) + \(declareTopLevelArray)repeating_flags=(\(flags.filter(\.isRepeating).flatMap(\.completionWords).joined(separator: " "))) + \(declareTopLevelArray)non_repeating_flags=(\(flags.filter { !$0.isRepeating }.flatMap(\.completionWords).joined(separator: " "))) + \(declareTopLevelArray)repeating_options=(\(options.filter(\.isRepeating).flatMap(\.completionWords).joined(separator: " "))) + \(declareTopLevelArray)non_repeating_options=(\(options.filter { !$0.isRepeating }.flatMap(\.completionWords).joined(separator: " "))) + \(offerFlagsOptionsFunctionName) \ + \(positionalArguments.contains { $0.isRepeating } ? -1 : positionalArguments.count) """ } @@ -225,12 +234,12 @@ extension CommandInfoV0 { // Generate the case pattern-matching statements for option values. // If there aren't any, skip the case block altogether. let optionHandlers = - (arguments ?? []).compactMap { arg in + options.compactMap { arg in guard arg.kind != .flag else { return nil } let words = arg.completionWords guard !words.isEmpty else { return nil } return """ - \(arg.completionWords.map { "'\($0.shellEscapeForSingleQuotedString())'" }.joined(separator: "|"))) + \(words.map { "'\($0.shellEscapeForSingleQuotedString())'" }.joined(separator: "|"))) \(valueCompletion(arg).indentingEachLine(by: 8))\ return ;; @@ -248,14 +257,23 @@ extension CommandInfoV0 { """ } + var encounteredRepeatingPositional = false let positionalCases = zip(1..., positionalArguments) .compactMap { position, arg in + guard !encounteredRepeatingPositional else { + return nil as String? + } + + if arg.isRepeating { + encounteredRepeatingPositional = true + } + let completion = valueCompletion(arg) return completion.isEmpty ? nil : """ - \(position)) + \(encounteredRepeatingPositional ? "*" : position.description)) \(completion.indentingEachLine(by: 8))\ return ;; @@ -310,30 +328,6 @@ extension CommandInfoV0 { """ } - /// Returns flag completions. - private var flagCompletions: [String] { - (arguments ?? []).flatMap { - switch $0.kind { - case .flag: - return $0.completionWords - default: - return [] - } - } - } - - /// Returns option completions. - private var optionCompletions: [String] { - (arguments ?? []).flatMap { - switch $0.kind { - case .option: - return $0.completionWords - default: - return [] - } - } - } - /// Returns the completions that can follow the given argument's `--name`. private func valueCompletion(_ arg: ArgumentInfoV0) -> String { switch arg.completionKind { @@ -375,7 +369,6 @@ extension CommandInfoV0 { """ case .custom, .customAsync: - // Generate a call back into the command to retrieve a completions list return """ \(addCompletionsFunctionName) -W\ "$(\(customCompleteFunctionName) \(arg.commonCustomCompletionCall(command: self))\ @@ -385,7 +378,6 @@ extension CommandInfoV0 { """ case .customDeprecated: - // Generate a call back into the command to retrieve a completions list return """ \(addCompletionsFunctionName) -W\ "$(\(customCompleteFunctionName) \(arg.commonCustomCompletionCall(command: self)))" diff --git a/Sources/ArgumentParser/Completions/FishCompletionsGenerator.swift b/Sources/ArgumentParser/Completions/FishCompletionsGenerator.swift index a984e3bd..11d90e56 100644 --- a/Sources/ArgumentParser/Completions/FishCompletionsGenerator.swift +++ b/Sources/ArgumentParser/Completions/FishCompletionsGenerator.swift @@ -24,16 +24,36 @@ extension ToolInfoV0 { extension CommandInfoV0 { fileprivate var fishCompletionScript: String { """ - function \(shouldOfferCompletionsForFunctionName) -a expected_commands -a expected_positional_index - set -l unparsed_tokens (\(tokensFunctionName) -pc) + function \(shouldOfferCompletionsForFlagsOrOptionsFunctionName) -a expected_commands + set -l non_repeating_flags_or_options $argv[2..] + + set -l non_repeating_flags_or_options_absent 0 set -l positional_index 0 set -l commands + \(parseTokensFunctionName) + test "$commands" = "$expected_commands"; and return $non_repeating_flags_or_options_absent + end + + function \(shouldOfferCompletionsForPositionalFunctionName) -a expected_commands expected_positional_index positional_index_comparison + if test -z $positional_index_comparison + set positional_index_comparison -eq + end + + set -l non_repeating_flags_or_options + set -l non_repeating_flags_or_options_absent 0 + set -l positional_index 0 + set -l commands + \(parseTokensFunctionName) + test "$commands" = "$expected_commands" -a \\( "$positional_index" "$positional_index_comparison" "$expected_positional_index" \\) + end + + function \(parseTokensFunctionName) -S + set -l unparsed_tokens (\(tokensFunctionName) -pc) + set -l present_flags_and_options switch $unparsed_tokens[1] \(commandCases) end - - test "$commands" = "$expected_commands" -a \\( -z "$expected_positional_index" -o "$expected_positional_index" -eq "$positional_index" \\) end function \(tokensFunctionName) @@ -44,9 +64,8 @@ extension CommandInfoV0 { end end - function \(parseSubcommandFunctionName) -S + function \(parseSubcommandFunctionName) -S -a positional_count argparse -s r -- $argv - set -l positional_count $argv[1] set -l option_specs $argv[2..] set -a commands $unparsed_tokens[1] @@ -58,8 +77,16 @@ extension CommandInfoV0 { argparse -sn "$commands" $option_specs -- $unparsed_tokens 2> /dev/null set unparsed_tokens $argv set positional_index (math $positional_index + 1) + + for non_repeating_flag_or_option in $non_repeating_flags_or_options + if set -ql _flag_$non_repeating_flag_or_option + set non_repeating_flags_or_options_absent 1 + break + end + end + if test (count $unparsed_tokens) -eq 0 -o \\( -z "$_flag_r" -a "$positional_index" -gt "$positional_count" \\) - return 0 + break end set -e unparsed_tokens[1] end @@ -113,31 +140,41 @@ extension CommandInfoV0 { } private var completions: [String] { - let prefix = """ - complete -c '\(initialCommand)'\ - -n '\(shouldOfferCompletionsForFunctionName)\ - "\(commandContext.joined(separator: separator))" - """ + let prefix = "complete -c '\(initialCommand)' -n '" let subcommands = (subcommands ?? []).filter(\.shouldDisplay) var positionalIndex = 0 + var repeatingPositionalComparison = "" let argumentCompletions = completableArguments - .map { arg in - """ - \(prefix)\( - arg.kind == .positional - ? """ - \({ - positionalIndex += 1 - return " \(positionalIndex)" - }()) + .compactMap { arg in + if arg.kind == .positional { + guard repeatingPositionalComparison.isEmpty else { + return nil as String? + } + + if arg.isRepeating { + repeatingPositionalComparison = " -ge" + } + } + + return """ + \(prefix)\( + arg.kind == .positional + ? """ + \(shouldOfferCompletionsForPositionalFunctionName) "\(commandContext.joined(separator: separator))" \({ + positionalIndex += 1 + return "\(positionalIndex)\(repeatingPositionalComparison)" + }()) + """ + : """ + \(shouldOfferCompletionsForFlagsOrOptionsFunctionName) "\(commandContext.joined(separator: separator))"\ + \((arg.isRepeating ? [] : arg.names ?? []).map { " \($0.name)" }.sorted().joined()) + """ + )' \(argumentSegments(arg).joined(separator: separator)) """ - : "" - )' \(argumentSegments(arg).joined(separator: separator)) - """ } positionalIndex += 1 @@ -145,7 +182,10 @@ extension CommandInfoV0 { return argumentCompletions + subcommands.map { - "\(prefix) \(positionalIndex)' -fa '\($0.commandName)' -d '\($0.abstract?.fishEscapeForSingleQuotedString() ?? "")'" + """ + \(prefix)\(shouldOfferCompletionsForPositionalFunctionName) "\(commandContext.joined(separator: separator))"\ + \(positionalIndex)' -fa '\($0.commandName)' -d '\($0.abstract?.fishEscapeForSingleQuotedString() ?? "")' + """ } + subcommands.flatMap(\.completions) } @@ -247,8 +287,16 @@ extension CommandInfoV0 { """ } - private var shouldOfferCompletionsForFunctionName: String { - "\(completionFunctionPrefix)_should_offer_completions_for" + private var shouldOfferCompletionsForFlagsOrOptionsFunctionName: String { + "\(completionFunctionPrefix)_should_offer_completions_for_flags_or_options" + } + + private var shouldOfferCompletionsForPositionalFunctionName: String { + "\(completionFunctionPrefix)_should_offer_completions_for_positional" + } + + private var parseTokensFunctionName: String { + "\(completionFunctionPrefix)_parse_tokens" } private var tokensFunctionName: String { @@ -289,7 +337,7 @@ extension ArgumentInfoV0 { private func optionSpecRequiresValue(_ optionSpec: String) -> String { switch kind { case .option: - return "\(optionSpec)=" + return "\(optionSpec)=\(isRepeating ? "+" : "")" default: return optionSpec } diff --git a/Sources/ArgumentParser/Completions/ZshCompletionsGenerator.swift b/Sources/ArgumentParser/Completions/ZshCompletionsGenerator.swift index 2953d939..210bb6e0 100644 --- a/Sources/ArgumentParser/Completions/ZshCompletionsGenerator.swift +++ b/Sources/ArgumentParser/Completions/ZshCompletionsGenerator.swift @@ -60,8 +60,52 @@ extension CommandInfoV0 { private var completionFunctions: String { let functionName = completionFunctionName - let argumentSpecsAndSetupScripts = (arguments ?? []).compactMap { - argumentSpecAndSetupScript($0) + var repeatingPositionalIndicator = "" + let argumentSpecsAndSetupScripts = (arguments ?? []).compactMap { arg in + guard arg.shouldDisplay else { + return nil as (argumentSpec: String, setupScript: String?)? + } + + let line: String + let names = arg.names ?? [] + switch names.count { + case 0: + guard repeatingPositionalIndicator.isEmpty else { + return nil + } + + if arg.isRepeating { + repeatingPositionalIndicator = "*" + } + line = repeatingPositionalIndicator + case 1: + // swift-format-ignore: NeverForceUnwrap + // Preconditions: names has exactly one element. + line = """ + \(arg.isRepeatingOption ? "*" : "")\(names.first!.commonCompletionSynopsisString().zshEscapeForSingleQuotedOptionSpec())\(arg.completionAbstract) + """ + default: + let synopses = names.map { + $0.commonCompletionSynopsisString() + .zshEscapeForSingleQuotedOptionSpec() + } + line = """ + \(arg.isRepeatingOption ? "*" : "(\(synopses.joined(separator: " ")))")'\ + {\(synopses.joined(separator: ","))}\ + '\(arg.completionAbstract) + """ + } + + switch arg.kind { + case .option, .positional: + let (argumentAction, setupScript) = argumentActionAndSetupScript(arg) + return ( + "'\(line):\(arg.valueName?.zshEscapeForSingleQuotedOptionSpec() ?? ""):\(argumentAction)'", + setupScript + ) + case .flag: + return ("'\(line)'", nil) + } } var argumentSpecs = argumentSpecsAndSetupScripts.map(\.argumentSpec) let setupScripts = argumentSpecsAndSetupScripts.compactMap(\.setupScript) @@ -139,45 +183,6 @@ extension CommandInfoV0 { """ } - private func argumentSpecAndSetupScript( - _ arg: ArgumentInfoV0 - ) -> (argumentSpec: String, setupScript: String?)? { - guard arg.shouldDisplay else { return nil } - - let line: String - let names = arg.names ?? [] - switch names.count { - case 0: - line = arg.isRepeating ? "*" : "" - case 1: - // swift-format-ignore: NeverForceUnwrap - // Preconditions: names has exactly one element. - line = """ - \(arg.isRepeatingOption ? "*" : "")\(names.first!.commonCompletionSynopsisString().zshEscapeForSingleQuotedOptionSpec())\(arg.completionAbstract) - """ - default: - let synopses = names.map { - $0.commonCompletionSynopsisString().zshEscapeForSingleQuotedOptionSpec() - } - line = """ - \(arg.isRepeatingOption ? "*" : "(\(synopses.joined(separator: " ")))")'\ - {\(synopses.joined(separator: ","))}\ - '\(arg.completionAbstract) - """ - } - - switch arg.kind { - case .option, .positional: - let (argumentAction, setupScript) = argumentActionAndSetupScript(arg) - return ( - "'\(line):\(arg.valueName?.zshEscapeForSingleQuotedOptionSpec() ?? ""):\(argumentAction)'", - setupScript - ) - case .flag: - return ("'\(line)'", nil) - } - } - /// Returns the zsh "action" for an argument completion string. private func argumentActionAndSetupScript( _ arg: ArgumentInfoV0 diff --git a/Sources/ArgumentParser/Parsable Properties/Flag.swift b/Sources/ArgumentParser/Parsable Properties/Flag.swift index b9f94033..6c110689 100644 --- a/Sources/ArgumentParser/Parsable Properties/Flag.swift +++ b/Sources/ArgumentParser/Parsable Properties/Flag.swift @@ -152,6 +152,7 @@ public struct FlagInversion: Hashable { self.init(base: .prefixedNo) } + // swift-format-ignore: BeginDocumentationCommentWithOneLineSummary /// Uses matching flags with `enable-` and `disable-` prefixes. /// /// For example, the `extraOutput` property in this declaration is set to @@ -316,7 +317,7 @@ extension Flag where Value == Bool { /// ```swift /// @Flag(inversion: .prefixedNo) /// var useHTTPS: Bool = true - /// ```` + /// ``` /// /// - Parameters: /// - wrappedValue: A default value to use for this property, provided @@ -349,7 +350,7 @@ extension Flag where Value == Bool { /// ```swift /// @Flag(inversion: .prefixedNo) /// var useHTTPS: Bool - /// ```` + /// ``` /// /// - Parameters: /// - name: A specification for what names are allowed for this flag. diff --git a/Tests/ArgumentParserExampleTests/Snapshots/testMathBashCompletionScript().bash b/Tests/ArgumentParserExampleTests/Snapshots/testMathBashCompletionScript().bash index dca1d833..a4cf0089 100644 --- a/Tests/ArgumentParserExampleTests/Snapshots/testMathBashCompletionScript().bash +++ b/Tests/ArgumentParserExampleTests/Snapshots/testMathBashCompletionScript().bash @@ -22,15 +22,17 @@ __math_cursor_index_in_current_word() { # # required variables: # -# - flags: the flags that the current (sub)command can accept -# - options: the options that the current (sub)command can accept +# - repeating_flags: the repeating flags that the current (sub)command can accept +# - non_repeating_flags: the non-repeating flags that the current (sub)command can accept +# - repeating_options: the repeating options that the current (sub)command can accept +# - non_repeating_options: the non-repeating options that the current (sub)command can accept # - positional_number: value ignored # - unparsed_words: unparsed words from the current command line # # modified variables: # -# - flags: remove flags for this (sub)command that are already on the command line -# - options: remove options for this (sub)command that are already on the command line +# - non_repeating_flags: remove flags for this (sub)command that are already on the command line +# - non_repeating_options: remove options for this (sub)command that are already on the command line # - positional_number: set to the current positional number # - unparsed_words: remove all flags, options, and option values for this (sub)command __math_offer_flags_options() { @@ -67,26 +69,26 @@ __math_offer_flags_options() { # ${word} is a flag or an option # If ${word} is an option, mark that the next word to be parsed is an option value local option - for option in "${options[@]}"; do + for option in "${repeating_options[@]}" "${non_repeating_options[@]}"; do [[ "${word}" = "${option}" ]] && is_parsing_option_value=true && break done - # Remove ${word} from ${flags} or ${options} so it isn't offered again + # Remove ${word} from ${non_repeating_flags} or ${non_repeating_options} so it isn't offered again local not_found=true local -i index - for index in "${!flags[@]}"; do - if [[ "${flags[${index}]}" = "${word}" ]]; then - unset "flags[${index}]" - flags=("${flags[@]}") + for index in "${!non_repeating_flags[@]}"; do + if [[ "${non_repeating_flags[${index}]}" = "${word}" ]]; then + unset "non_repeating_flags[${index}]" + non_repeating_flags=("${non_repeating_flags[@]}") not_found=false break fi done if "${not_found}"; then - for index in "${!options[@]}"; do - if [[ "${options[${index}]}" = "${word}" ]]; then - unset "options[${index}]" - options=("${options[@]}") + for index in "${!non_repeating_flags[@]}"; do + if [[ "${non_repeating_flags[${index}]}" = "${word}" ]]; then + unset "non_repeating_flags[${index}]" + non_repeating_flags=("${non_repeating_flags[@]}") break fi done @@ -98,7 +100,7 @@ __math_offer_flags_options() { fi # ${word} is neither a flag, nor an option, nor an option value - if [[ "${positional_number}" -lt "${positional_count}" ]]; then + if [[ "${positional_number}" -lt "${positional_count}" || "${positional_count}" -lt 0 ]]; then # ${word} is a positional ((positional_number++)) unset "unparsed_words[${word_index}]" @@ -121,7 +123,7 @@ __math_offer_flags_options() { && ! "${is_parsing_option_value}"\ && [[ ("${cur}" = -* && "${positional_number}" -ge 0) || "${positional_number}" -eq -1 ]] then - COMPREPLY+=($(compgen -W "${flags[*]} ${options[*]}" -- "${cur}")) + COMPREPLY+=($(compgen -W "${repeating_flags[*]} ${non_repeating_flags[*]} ${repeating_options[*]} ${non_repeating_options[*]}" -- "${cur}")) fi } @@ -158,8 +160,10 @@ _math() { local -i positional_number local -a unparsed_words=("${COMP_WORDS[@]:1:${COMP_CWORD}}") - local -a flags=(--version -h --help) - local -a options=() + local -a repeating_flags=() + local -a non_repeating_flags=(--version -h --help) + local -a repeating_options=() + local -a non_repeating_options=() __math_offer_flags_options 0 # Offer subcommand / subcommand argument completions @@ -179,20 +183,26 @@ _math() { } _math_add() { - flags=(--hex-output -x --version -h --help) - options=() - __math_offer_flags_options 1 + repeating_flags=() + non_repeating_flags=(--hex-output -x --version -h --help) + repeating_options=() + non_repeating_options=() + __math_offer_flags_options -1 } _math_multiply() { - flags=(--hex-output -x --version -h --help) - options=() - __math_offer_flags_options 1 + repeating_flags=() + non_repeating_flags=(--hex-output -x --version -h --help) + repeating_options=() + non_repeating_options=() + __math_offer_flags_options -1 } _math_stats() { - flags=(--version -h --help) - options=() + repeating_flags=() + non_repeating_flags=(--version -h --help) + repeating_options=() + non_repeating_options=() __math_offer_flags_options 0 # Offer subcommand / subcommand argument completions @@ -212,9 +222,11 @@ _math_stats() { } _math_stats_average() { - flags=(--version -h --help) - options=(--kind) - __math_offer_flags_options 1 + repeating_flags=() + non_repeating_flags=(--version -h --help) + repeating_options=() + non_repeating_options=(--kind) + __math_offer_flags_options -1 # Offer option value completions case "${prev}" in @@ -226,15 +238,19 @@ _math_stats_average() { } _math_stats_stdev() { - flags=(--version -h --help) - options=() - __math_offer_flags_options 1 + repeating_flags=() + non_repeating_flags=(--version -h --help) + repeating_options=() + non_repeating_options=() + __math_offer_flags_options -1 } _math_stats_quantiles() { - flags=(--version -h --help) - options=(--file --directory --shell --custom --custom-deprecated) - __math_offer_flags_options 4 + repeating_flags=() + non_repeating_flags=(--version -h --help) + repeating_options=() + non_repeating_options=(--file --directory --shell --custom --custom-deprecated) + __math_offer_flags_options -1 # Offer option value completions case "${prev}" in @@ -278,9 +294,11 @@ _math_stats_quantiles() { } _math_help() { - flags=(--version) - options=() - __math_offer_flags_options 1 + repeating_flags=() + non_repeating_flags=(--version) + repeating_options=() + non_repeating_options=() + __math_offer_flags_options -1 } complete -o filenames -F _math math diff --git a/Tests/ArgumentParserExampleTests/Snapshots/testMathFishCompletionScript().fish b/Tests/ArgumentParserExampleTests/Snapshots/testMathFishCompletionScript().fish index 269a72e5..0fd19c10 100644 --- a/Tests/ArgumentParserExampleTests/Snapshots/testMathFishCompletionScript().fish +++ b/Tests/ArgumentParserExampleTests/Snapshots/testMathFishCompletionScript().fish @@ -1,7 +1,29 @@ -function __math_should_offer_completions_for -a expected_commands -a expected_positional_index - set -l unparsed_tokens (__math_tokens -pc) +function __math_should_offer_completions_for_flags_or_options -a expected_commands + set -l non_repeating_flags_or_options $argv[2..] + + set -l non_repeating_flags_or_options_absent 0 + set -l positional_index 0 + set -l commands + __math_parse_tokens + test "$commands" = "$expected_commands"; and return $non_repeating_flags_or_options_absent +end + +function __math_should_offer_completions_for_positional -a expected_commands expected_positional_index positional_index_comparison + if test -z $positional_index_comparison + set positional_index_comparison -eq + end + + set -l non_repeating_flags_or_options + set -l non_repeating_flags_or_options_absent 0 set -l positional_index 0 set -l commands + __math_parse_tokens + test "$commands" = "$expected_commands" -a \( "$positional_index" "$positional_index_comparison" "$expected_positional_index" \) +end + +function __math_parse_tokens -S + set -l unparsed_tokens (__math_tokens -pc) + set -l present_flags_and_options switch $unparsed_tokens[1] case 'math' @@ -25,8 +47,6 @@ function __math_should_offer_completions_for -a expected_commands -a expected_po __math_parse_subcommand -r 1 'version' end end - - test "$commands" = "$expected_commands" -a \( -z "$expected_positional_index" -o "$expected_positional_index" -eq "$positional_index" \) end function __math_tokens @@ -37,9 +57,8 @@ function __math_tokens end end -function __math_parse_subcommand -S +function __math_parse_subcommand -S -a positional_count argparse -s r -- $argv - set -l positional_count $argv[1] set -l option_specs $argv[2..] set -a commands $unparsed_tokens[1] @@ -51,8 +70,16 @@ function __math_parse_subcommand -S argparse -sn "$commands" $option_specs -- $unparsed_tokens 2> /dev/null set unparsed_tokens $argv set positional_index (math $positional_index + 1) + + for non_repeating_flag_or_option in $non_repeating_flags_or_options + if set -ql _flag_$non_repeating_flag_or_option + set non_repeating_flags_or_options_absent 1 + break + end + end + if test (count $unparsed_tokens) -eq 0 -o \( -z "$_flag_r" -a "$positional_index" -gt "$positional_count" \) - return 0 + break end set -e unparsed_tokens[1] end @@ -78,36 +105,36 @@ function __math_custom_completion end complete -c 'math' -f -complete -c 'math' -n '__math_should_offer_completions_for "math"' -l 'version' -d 'Show the version.' -complete -c 'math' -n '__math_should_offer_completions_for "math"' -s 'h' -l 'help' -d 'Show help information.' -complete -c 'math' -n '__math_should_offer_completions_for "math" 1' -fa 'add' -d 'Print the sum of the values.' -complete -c 'math' -n '__math_should_offer_completions_for "math" 1' -fa 'multiply' -d 'Print the product of the values.' -complete -c 'math' -n '__math_should_offer_completions_for "math" 1' -fa 'stats' -d 'Calculate descriptive statistics.' -complete -c 'math' -n '__math_should_offer_completions_for "math" 1' -fa 'help' -d 'Show subcommand help information.' -complete -c 'math' -n '__math_should_offer_completions_for "math add"' -l 'hex-output' -s 'x' -d 'Use hexadecimal notation for the result.' -complete -c 'math' -n '__math_should_offer_completions_for "math add"' -l 'version' -d 'Show the version.' -complete -c 'math' -n '__math_should_offer_completions_for "math add"' -s 'h' -l 'help' -d 'Show help information.' -complete -c 'math' -n '__math_should_offer_completions_for "math multiply"' -l 'hex-output' -s 'x' -d 'Use hexadecimal notation for the result.' -complete -c 'math' -n '__math_should_offer_completions_for "math multiply"' -l 'version' -d 'Show the version.' -complete -c 'math' -n '__math_should_offer_completions_for "math multiply"' -s 'h' -l 'help' -d 'Show help information.' -complete -c 'math' -n '__math_should_offer_completions_for "math stats"' -l 'version' -d 'Show the version.' -complete -c 'math' -n '__math_should_offer_completions_for "math stats"' -s 'h' -l 'help' -d 'Show help information.' -complete -c 'math' -n '__math_should_offer_completions_for "math stats" 1' -fa 'average' -d 'Print the average of the values.' -complete -c 'math' -n '__math_should_offer_completions_for "math stats" 1' -fa 'stdev' -d 'Print the standard deviation of the values.' -complete -c 'math' -n '__math_should_offer_completions_for "math stats" 1' -fa 'quantiles' -d 'Print the quantiles of the values (TBD).' -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' -complete -c 'math' -n '__math_should_offer_completions_for "math stats average"' -l 'version' -d 'Show the version.' -complete -c 'math' -n '__math_should_offer_completions_for "math stats average"' -s 'h' -l 'help' -d 'Show help information.' -complete -c 'math' -n '__math_should_offer_completions_for "math stats stdev"' -l 'version' -d 'Show the version.' -complete -c 'math' -n '__math_should_offer_completions_for "math stats stdev"' -s 'h' -l 'help' -d 'Show help information.' -complete -c 'math' -n '__math_should_offer_completions_for "math stats quantiles" 1' -fka 'alphabet alligator branch braggart' -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))' -complete -c 'math' -n '__math_should_offer_completions_for "math stats quantiles" 3' -fka '(__math_custom_completion ---completion stats quantiles -- positional@2)' -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) \'\')' -complete -c 'math' -n '__math_should_offer_completions_for "math stats quantiles"' -l 'directory' -rfa '(__math_complete_directories)' -complete -c 'math' -n '__math_should_offer_completions_for "math stats quantiles"' -l 'shell' -rfka '(head -100 \'/usr/share/dict/words\' | tail -50)' -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))' -complete -c 'math' -n '__math_should_offer_completions_for "math stats quantiles"' -l 'custom-deprecated' -rfka '(__math_custom_completion ---completion stats quantiles -- --custom-deprecated)' -complete -c 'math' -n '__math_should_offer_completions_for "math stats quantiles"' -l 'version' -d 'Show the version.' -complete -c 'math' -n '__math_should_offer_completions_for "math stats quantiles"' -s 'h' -l 'help' -d 'Show help information.' -complete -c 'math' -n '__math_should_offer_completions_for "math help"' -l 'version' -d 'Show the version.' +complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math" version' -l 'version' -d 'Show the version.' +complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math" h help' -s 'h' -l 'help' -d 'Show help information.' +complete -c 'math' -n '__math_should_offer_completions_for_positional "math" 1' -fa 'add' -d 'Print the sum of the values.' +complete -c 'math' -n '__math_should_offer_completions_for_positional "math" 1' -fa 'multiply' -d 'Print the product of the values.' +complete -c 'math' -n '__math_should_offer_completions_for_positional "math" 1' -fa 'stats' -d 'Calculate descriptive statistics.' +complete -c 'math' -n '__math_should_offer_completions_for_positional "math" 1' -fa 'help' -d 'Show subcommand help information.' +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.' +complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math add" version' -l 'version' -d 'Show the version.' +complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math add" h help' -s 'h' -l 'help' -d 'Show help information.' +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.' +complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math multiply" version' -l 'version' -d 'Show the version.' +complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math multiply" h help' -s 'h' -l 'help' -d 'Show help information.' +complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math stats" version' -l 'version' -d 'Show the version.' +complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math stats" h help' -s 'h' -l 'help' -d 'Show help information.' +complete -c 'math' -n '__math_should_offer_completions_for_positional "math stats" 1' -fa 'average' -d 'Print the average of the values.' +complete -c 'math' -n '__math_should_offer_completions_for_positional "math stats" 1' -fa 'stdev' -d 'Print the standard deviation of the values.' +complete -c 'math' -n '__math_should_offer_completions_for_positional "math stats" 1' -fa 'quantiles' -d 'Print the quantiles of the values (TBD).' +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' +complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math stats average" version' -l 'version' -d 'Show the version.' +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.' +complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math stats stdev" version' -l 'version' -d 'Show the version.' +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.' +complete -c 'math' -n '__math_should_offer_completions_for_positional "math stats quantiles" 1' -fka 'alphabet alligator branch braggart' +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))' +complete -c 'math' -n '__math_should_offer_completions_for_positional "math stats quantiles" 3' -fka '(__math_custom_completion ---completion stats quantiles -- positional@2)' +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) \'\')' +complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math stats quantiles" directory' -l 'directory' -rfa '(__math_complete_directories)' +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)' +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))' +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)' +complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math stats quantiles" version' -l 'version' -d 'Show the version.' +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.' +complete -c 'math' -n '__math_should_offer_completions_for_flags_or_options "math help" version' -l 'version' -d 'Show the version.' diff --git a/Tests/ArgumentParserUnitTests/Snapshots/testBase_Bash().bash b/Tests/ArgumentParserUnitTests/Snapshots/testBase_Bash().bash index 3c57c860..d9b6394c 100644 --- a/Tests/ArgumentParserUnitTests/Snapshots/testBase_Bash().bash +++ b/Tests/ArgumentParserUnitTests/Snapshots/testBase_Bash().bash @@ -22,15 +22,17 @@ __base-test_cursor_index_in_current_word() { # # required variables: # -# - flags: the flags that the current (sub)command can accept -# - options: the options that the current (sub)command can accept +# - repeating_flags: the repeating flags that the current (sub)command can accept +# - non_repeating_flags: the non-repeating flags that the current (sub)command can accept +# - repeating_options: the repeating options that the current (sub)command can accept +# - non_repeating_options: the non-repeating options that the current (sub)command can accept # - positional_number: value ignored # - unparsed_words: unparsed words from the current command line # # modified variables: # -# - flags: remove flags for this (sub)command that are already on the command line -# - options: remove options for this (sub)command that are already on the command line +# - non_repeating_flags: remove flags for this (sub)command that are already on the command line +# - non_repeating_options: remove options for this (sub)command that are already on the command line # - positional_number: set to the current positional number # - unparsed_words: remove all flags, options, and option values for this (sub)command __base-test_offer_flags_options() { @@ -67,26 +69,26 @@ __base-test_offer_flags_options() { # ${word} is a flag or an option # If ${word} is an option, mark that the next word to be parsed is an option value local option - for option in "${options[@]}"; do + for option in "${repeating_options[@]}" "${non_repeating_options[@]}"; do [[ "${word}" = "${option}" ]] && is_parsing_option_value=true && break done - # Remove ${word} from ${flags} or ${options} so it isn't offered again + # Remove ${word} from ${non_repeating_flags} or ${non_repeating_options} so it isn't offered again local not_found=true local -i index - for index in "${!flags[@]}"; do - if [[ "${flags[${index}]}" = "${word}" ]]; then - unset "flags[${index}]" - flags=("${flags[@]}") + for index in "${!non_repeating_flags[@]}"; do + if [[ "${non_repeating_flags[${index}]}" = "${word}" ]]; then + unset "non_repeating_flags[${index}]" + non_repeating_flags=("${non_repeating_flags[@]}") not_found=false break fi done if "${not_found}"; then - for index in "${!options[@]}"; do - if [[ "${options[${index}]}" = "${word}" ]]; then - unset "options[${index}]" - options=("${options[@]}") + for index in "${!non_repeating_flags[@]}"; do + if [[ "${non_repeating_flags[${index}]}" = "${word}" ]]; then + unset "non_repeating_flags[${index}]" + non_repeating_flags=("${non_repeating_flags[@]}") break fi done @@ -98,7 +100,7 @@ __base-test_offer_flags_options() { fi # ${word} is neither a flag, nor an option, nor an option value - if [[ "${positional_number}" -lt "${positional_count}" ]]; then + if [[ "${positional_number}" -lt "${positional_count}" || "${positional_count}" -lt 0 ]]; then # ${word} is a positional ((positional_number++)) unset "unparsed_words[${word_index}]" @@ -121,7 +123,7 @@ __base-test_offer_flags_options() { && ! "${is_parsing_option_value}"\ && [[ ("${cur}" = -* && "${positional_number}" -ge 0) || "${positional_number}" -eq -1 ]] then - COMPREPLY+=($(compgen -W "${flags[*]} ${options[*]}" -- "${cur}")) + COMPREPLY+=($(compgen -W "${repeating_flags[*]} ${non_repeating_flags[*]} ${repeating_options[*]} ${non_repeating_options[*]}" -- "${cur}")) fi } @@ -158,8 +160,10 @@ _base-test() { local -i positional_number local -a unparsed_words=("${COMP_WORDS[@]:1:${COMP_CWORD}}") - local -a flags=(--one --two --custom-three --kind-counter -h --help) - local -a options=(--name --kind --other-kind --path1 --path2 --path3 --rep1 -r --rep2) + local -a repeating_flags=(--kind-counter) + local -a non_repeating_flags=(--one --two --custom-three -h --help) + local -a repeating_options=(--rep1 -r --rep2) + local -a non_repeating_options=(--name --kind --other-kind --path1 --path2 --path3) __base-test_offer_flags_options 2 # Offer option value completions @@ -224,14 +228,18 @@ _base-test() { } _base-test_sub-command() { - flags=(-h --help) - options=() + repeating_flags=() + non_repeating_flags=(-h --help) + repeating_options=() + non_repeating_options=() __base-test_offer_flags_options 0 } _base-test_escaped-command() { - flags=(-h --help) - options=(--o:n[e) + repeating_flags=() + non_repeating_flags=(-h --help) + repeating_options=() + non_repeating_options=(--o:n[e) __base-test_offer_flags_options 1 # Offer option value completions diff --git a/Tests/ArgumentParserUnitTests/Snapshots/testBase_Fish().fish b/Tests/ArgumentParserUnitTests/Snapshots/testBase_Fish().fish index 4f58f788..df9e309b 100644 --- a/Tests/ArgumentParserUnitTests/Snapshots/testBase_Fish().fish +++ b/Tests/ArgumentParserUnitTests/Snapshots/testBase_Fish().fish @@ -1,11 +1,33 @@ -function __base-test_should_offer_completions_for -a expected_commands -a expected_positional_index - set -l unparsed_tokens (__base-test_tokens -pc) +function __base-test_should_offer_completions_for_flags_or_options -a expected_commands + set -l non_repeating_flags_or_options $argv[2..] + + set -l non_repeating_flags_or_options_absent 0 set -l positional_index 0 set -l commands + __base-test_parse_tokens + test "$commands" = "$expected_commands"; and return $non_repeating_flags_or_options_absent +end + +function __base-test_should_offer_completions_for_positional -a expected_commands expected_positional_index positional_index_comparison + if test -z $positional_index_comparison + set positional_index_comparison -eq + end + + set -l non_repeating_flags_or_options + set -l non_repeating_flags_or_options_absent 0 + set -l positional_index 0 + set -l commands + __base-test_parse_tokens + test "$commands" = "$expected_commands" -a \( "$positional_index" "$positional_index_comparison" "$expected_positional_index" \) +end + +function __base-test_parse_tokens -S + set -l unparsed_tokens (__base-test_tokens -pc) + set -l present_flags_and_options switch $unparsed_tokens[1] case 'base-test' - __base-test_parse_subcommand 2 'name=' 'kind=' 'other-kind=' 'path1=' 'path2=' 'path3=' 'one' 'two' 'custom-three' 'kind-counter' 'rep1=' 'r/rep2=' 'h/help' + __base-test_parse_subcommand 2 'name=' 'kind=' 'other-kind=' 'path1=' 'path2=' 'path3=' 'one' 'two' 'custom-three' 'kind-counter' 'rep1=+' 'r/rep2=+' 'h/help' switch $unparsed_tokens[1] case 'sub-command' __base-test_parse_subcommand 0 'h/help' @@ -15,8 +37,6 @@ function __base-test_should_offer_completions_for -a expected_commands -a expect __base-test_parse_subcommand -r 1 end end - - test "$commands" = "$expected_commands" -a \( -z "$expected_positional_index" -o "$expected_positional_index" -eq "$positional_index" \) end function __base-test_tokens @@ -27,9 +47,8 @@ function __base-test_tokens end end -function __base-test_parse_subcommand -S +function __base-test_parse_subcommand -S -a positional_count argparse -s r -- $argv - set -l positional_count $argv[1] set -l option_specs $argv[2..] set -a commands $unparsed_tokens[1] @@ -41,8 +60,16 @@ function __base-test_parse_subcommand -S argparse -sn "$commands" $option_specs -- $unparsed_tokens 2> /dev/null set unparsed_tokens $argv set positional_index (math $positional_index + 1) + + for non_repeating_flag_or_option in $non_repeating_flags_or_options + if set -ql _flag_$non_repeating_flag_or_option + set non_repeating_flags_or_options_absent 1 + break + end + end + if test (count $unparsed_tokens) -eq 0 -o \( -z "$_flag_r" -a "$positional_index" -gt "$positional_count" \) - return 0 + break end set -e unparsed_tokens[1] end @@ -68,25 +95,25 @@ function __base-test_custom_completion end complete -c 'base-test' -f -complete -c 'base-test' -n '__base-test_should_offer_completions_for "base-test"' -l 'name' -d 'The user\'s name.' -rfka '' -complete -c 'base-test' -n '__base-test_should_offer_completions_for "base-test"' -l 'kind' -rfka 'one two custom-three' -complete -c 'base-test' -n '__base-test_should_offer_completions_for "base-test"' -l 'other-kind' -rfka 'b1_fish b2_fish b3_fish' -complete -c 'base-test' -n '__base-test_should_offer_completions_for "base-test"' -l 'path1' -rF -complete -c 'base-test' -n '__base-test_should_offer_completions_for "base-test"' -l 'path2' -rF -complete -c 'base-test' -n '__base-test_should_offer_completions_for "base-test"' -l 'path3' -rfka 'c1_fish c2_fish c3_fish' -complete -c 'base-test' -n '__base-test_should_offer_completions_for "base-test"' -l 'one' -complete -c 'base-test' -n '__base-test_should_offer_completions_for "base-test"' -l 'two' -complete -c 'base-test' -n '__base-test_should_offer_completions_for "base-test"' -l 'custom-three' -complete -c 'base-test' -n '__base-test_should_offer_completions_for "base-test"' -l 'kind-counter' -complete -c 'base-test' -n '__base-test_should_offer_completions_for "base-test"' -l 'rep1' -rfka '' -complete -c 'base-test' -n '__base-test_should_offer_completions_for "base-test"' -s 'r' -l 'rep2' -rfka '' -complete -c 'base-test' -n '__base-test_should_offer_completions_for "base-test" 1' -fka '(__base-test_custom_completion ---completion -- positional@0 (count (__base-test_tokens -pc)) (__base-test_tokens -tC))' -complete -c 'base-test' -n '__base-test_should_offer_completions_for "base-test" 2' -fka '(__base-test_custom_completion ---completion -- positional@1 (count (__base-test_tokens -pc)) (__base-test_tokens -tC))' -complete -c 'base-test' -n '__base-test_should_offer_completions_for "base-test"' -s 'h' -l 'help' -d 'Show help information.' -complete -c 'base-test' -n '__base-test_should_offer_completions_for "base-test" 3' -fa 'sub-command' -d '' -complete -c 'base-test' -n '__base-test_should_offer_completions_for "base-test" 3' -fa 'escaped-command' -d '' -complete -c 'base-test' -n '__base-test_should_offer_completions_for "base-test" 3' -fa 'help' -d 'Show subcommand help information.' -complete -c 'base-test' -n '__base-test_should_offer_completions_for "base-test sub-command"' -s 'h' -l 'help' -d 'Show help information.' -complete -c 'base-test' -n '__base-test_should_offer_completions_for "base-test escaped-command"' -l 'o:n[e' -d 'Escaped chars: \'[]\\.' -rfka '' -complete -c 'base-test' -n '__base-test_should_offer_completions_for "base-test escaped-command" 1' -fka '(__base-test_custom_completion ---completion escaped-command -- positional@0 (count (__base-test_tokens -pc)) (__base-test_tokens -tC))' -complete -c 'base-test' -n '__base-test_should_offer_completions_for "base-test escaped-command"' -s 'h' -l 'help' -d 'Show help information.' \ No newline at end of file +complete -c 'base-test' -n '__base-test_should_offer_completions_for_flags_or_options "base-test" name' -l 'name' -d 'The user\'s name.' -rfka '' +complete -c 'base-test' -n '__base-test_should_offer_completions_for_flags_or_options "base-test" kind' -l 'kind' -rfka 'one two custom-three' +complete -c 'base-test' -n '__base-test_should_offer_completions_for_flags_or_options "base-test" other-kind' -l 'other-kind' -rfka 'b1_fish b2_fish b3_fish' +complete -c 'base-test' -n '__base-test_should_offer_completions_for_flags_or_options "base-test" path1' -l 'path1' -rF +complete -c 'base-test' -n '__base-test_should_offer_completions_for_flags_or_options "base-test" path2' -l 'path2' -rF +complete -c 'base-test' -n '__base-test_should_offer_completions_for_flags_or_options "base-test" path3' -l 'path3' -rfka 'c1_fish c2_fish c3_fish' +complete -c 'base-test' -n '__base-test_should_offer_completions_for_flags_or_options "base-test" one' -l 'one' +complete -c 'base-test' -n '__base-test_should_offer_completions_for_flags_or_options "base-test" two' -l 'two' +complete -c 'base-test' -n '__base-test_should_offer_completions_for_flags_or_options "base-test" custom-three' -l 'custom-three' +complete -c 'base-test' -n '__base-test_should_offer_completions_for_flags_or_options "base-test"' -l 'kind-counter' +complete -c 'base-test' -n '__base-test_should_offer_completions_for_flags_or_options "base-test"' -l 'rep1' -rfka '' +complete -c 'base-test' -n '__base-test_should_offer_completions_for_flags_or_options "base-test"' -s 'r' -l 'rep2' -rfka '' +complete -c 'base-test' -n '__base-test_should_offer_completions_for_positional "base-test" 1' -fka '(__base-test_custom_completion ---completion -- positional@0 (count (__base-test_tokens -pc)) (__base-test_tokens -tC))' +complete -c 'base-test' -n '__base-test_should_offer_completions_for_positional "base-test" 2' -fka '(__base-test_custom_completion ---completion -- positional@1 (count (__base-test_tokens -pc)) (__base-test_tokens -tC))' +complete -c 'base-test' -n '__base-test_should_offer_completions_for_flags_or_options "base-test" h help' -s 'h' -l 'help' -d 'Show help information.' +complete -c 'base-test' -n '__base-test_should_offer_completions_for_positional "base-test" 3' -fa 'sub-command' -d '' +complete -c 'base-test' -n '__base-test_should_offer_completions_for_positional "base-test" 3' -fa 'escaped-command' -d '' +complete -c 'base-test' -n '__base-test_should_offer_completions_for_positional "base-test" 3' -fa 'help' -d 'Show subcommand help information.' +complete -c 'base-test' -n '__base-test_should_offer_completions_for_flags_or_options "base-test sub-command" h help' -s 'h' -l 'help' -d 'Show help information.' +complete -c 'base-test' -n '__base-test_should_offer_completions_for_flags_or_options "base-test escaped-command" o:n[e' -l 'o:n[e' -d 'Escaped chars: \'[]\\.' -rfka '' +complete -c 'base-test' -n '__base-test_should_offer_completions_for_positional "base-test escaped-command" 1' -fka '(__base-test_custom_completion ---completion escaped-command -- positional@0 (count (__base-test_tokens -pc)) (__base-test_tokens -tC))' +complete -c 'base-test' -n '__base-test_should_offer_completions_for_flags_or_options "base-test escaped-command" h help' -s 'h' -l 'help' -d 'Show help information.' \ No newline at end of file