From 4f63cee9520fe34b4e064322881d72608b11197c Mon Sep 17 00:00:00 2001 From: Rauhul Varma Date: Sat, 23 Apr 2022 18:56:15 -0700 Subject: [PATCH] Hide hidden subcommands from completions (#443) --- .../BashCompletionsGenerator.swift | 1 + .../FishCompletionsGenerator.swift | 1 + .../Completions/ZshCompletionsGenerator.swift | 1 + .../CompletionScriptTests.swift | 111 ++++++++++++++++++ 4 files changed, 114 insertions(+) diff --git a/Sources/ArgumentParser/Completions/BashCompletionsGenerator.swift b/Sources/ArgumentParser/Completions/BashCompletionsGenerator.swift index 8755c4298..e444f81dd 100644 --- a/Sources/ArgumentParser/Completions/BashCompletionsGenerator.swift +++ b/Sources/ArgumentParser/Completions/BashCompletionsGenerator.swift @@ -35,6 +35,7 @@ struct BashCompletionsGenerator { // Include 'help' in the list of subcommands for the root command. var subcommands = type.configuration.subcommands + .filter { $0.configuration.shouldDisplay } if !subcommands.isEmpty && isRootCommand { subcommands.append(HelpCommand.self) } diff --git a/Sources/ArgumentParser/Completions/FishCompletionsGenerator.swift b/Sources/ArgumentParser/Completions/FishCompletionsGenerator.swift index 638783d0c..cfbe9a9fe 100644 --- a/Sources/ArgumentParser/Completions/FishCompletionsGenerator.swift +++ b/Sources/ArgumentParser/Completions/FishCompletionsGenerator.swift @@ -30,6 +30,7 @@ struct FishCompletionsGenerator { let isRootCommand = commands.count == 1 let programName = commandChain[0] var subcommands = type.configuration.subcommands + .filter { $0.configuration.shouldDisplay } if !subcommands.isEmpty { if isRootCommand { diff --git a/Sources/ArgumentParser/Completions/ZshCompletionsGenerator.swift b/Sources/ArgumentParser/Completions/ZshCompletionsGenerator.swift index ddcf0edd4..dea09615e 100644 --- a/Sources/ArgumentParser/Completions/ZshCompletionsGenerator.swift +++ b/Sources/ArgumentParser/Completions/ZshCompletionsGenerator.swift @@ -37,6 +37,7 @@ struct ZshCompletionsGenerator { var args = generateCompletionArguments(commands) var subcommands = type.configuration.subcommands + .filter { $0.configuration.shouldDisplay } var subcommandHandler = "" if !subcommands.isEmpty { args.append("'(-): :->command'") diff --git a/Tests/ArgumentParserUnitTests/CompletionScriptTests.swift b/Tests/ArgumentParserUnitTests/CompletionScriptTests.swift index e376b6655..ab8b3adc2 100644 --- a/Tests/ArgumentParserUnitTests/CompletionScriptTests.swift +++ b/Tests/ArgumentParserUnitTests/CompletionScriptTests.swift @@ -268,3 +268,114 @@ complete -c base -n '_swift_base_using_command base' -f -r -l path3 complete -c base -n '_swift_base_using_command base --path3' -f -k -a 'a b c' complete -c base -n '_swift_base_using_command base' -f -s h -l help -d 'Show help information.' """ + +// MARK: - Test Hidden Subcommand +struct Parent: ParsableCommand { + static var configuration = CommandConfiguration(subcommands: [HiddenChild.self]) +} + +struct HiddenChild: ParsableCommand { + static var configuration = CommandConfiguration(shouldDisplay: false) +} + +extension CompletionScriptTests { + func testHiddenSubcommand_Zsh() throws { + let script1 = try CompletionsGenerator(command: Parent.self, shell: .zsh) + .generateCompletionScript() + XCTAssertEqual(zshHiddenCompletion, script1) + + let script2 = try CompletionsGenerator(command: Parent.self, shellName: "zsh") + .generateCompletionScript() + XCTAssertEqual(zshHiddenCompletion, script2) + + let script3 = Parent.completionScript(for: .zsh) + XCTAssertEqual(zshHiddenCompletion, script3) + } + + func testHiddenSubcommand_Bash() throws { + let script1 = try CompletionsGenerator(command: Parent.self, shell: .bash) + .generateCompletionScript() + XCTAssertEqual(bashHiddenCompletion, script1) + + let script2 = try CompletionsGenerator(command: Parent.self, shellName: "bash") + .generateCompletionScript() + XCTAssertEqual(bashHiddenCompletion, script2) + + let script3 = Parent.completionScript(for: .bash) + XCTAssertEqual(bashHiddenCompletion, script3) + } + + func testHiddenSubcommand_Fish() throws { + let script1 = try CompletionsGenerator(command: Parent.self, shell: .fish) + .generateCompletionScript() + XCTAssertEqual(fishHiddenCompletion, script1) + + let script2 = try CompletionsGenerator(command: Parent.self, shellName: "fish") + .generateCompletionScript() + XCTAssertEqual(fishHiddenCompletion, script2) + + let script3 = Parent.completionScript(for: .fish) + XCTAssertEqual(fishHiddenCompletion, script3) + } +} + +let zshHiddenCompletion = """ +#compdef parent +local context state state_descr line +_parent_commandname=$words[1] +typeset -A opt_args + +_parent() { + integer ret=1 + local -a args + args+=( + '(-h --help)'{-h,--help}'[Show help information.]' + ) + _arguments -w -s -S $args[@] && ret=0 + + return ret +} + + +_custom_completion() { + local completions=("${(@f)$($*)}") + _describe '' completions +} + +_parent +""" + +let bashHiddenCompletion = """ +#!/bin/bash + +_parent() { + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + COMPREPLY=() + opts="-h --help" + if [[ $COMP_CWORD == "1" ]]; then + COMPREPLY=( $(compgen -W "$opts" -- "$cur") ) + return + fi + COMPREPLY=( $(compgen -W "$opts" -- "$cur") ) +} + + +complete -F _parent parent +""" + +let fishHiddenCompletion = """ +function _swift_parent_using_command + set -l cmd (commandline -opc) + if [ (count $cmd) -eq (count $argv) ] + for i in (seq (count $argv)) + if [ $cmd[$i] != $argv[$i] ] + return 1 + end + end + return 0 + end + return 1 +end +complete -c parent -n '_swift_parent_using_command parent' -f -s h -l help -d 'Show help information.' +"""