From 41b22ba9eb59f7418ae3652095b6bc4a0c0158de Mon Sep 17 00:00:00 2001 From: Alex Dadgar Date: Fri, 8 Sep 2017 11:22:42 -0700 Subject: [PATCH] Hide non-user commands from autocomplete output This PR hides non-user CLI commands from the list of autocomplete suggestions. --- CHANGELOG.md | 2 ++ main.go | 22 ++++++++++-------- vendor/github.com/mitchellh/cli/cli.go | 31 ++++++++++++++++++++++++++ vendor/vendor.json | 6 ++--- 4 files changed, 49 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 536b41330..0990d9405 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ BUG FIXES: * cli: Fix autocompletion of paths that include directories on zsh [GH-3129] * cli: Fix job deployment -latest handling of jobs without deployments [GH-3166] + * cli: Hide CLI commands not expected to be run by user from autocomplete + suggestions [GH-3177] * cli: Status command honors exact job match even when it is the prefix of another job [GH-3120] * cli: Fix setting of TLSServerName for node API Client. This fixes an issue of diff --git a/main.go b/main.go index f33ac6f60..2699617e6 100644 --- a/main.go +++ b/main.go @@ -29,27 +29,31 @@ func RunCustom(args []string, commands map[string]cli.CommandFactory) int { commandsInclude := make([]string, 0, len(commands)) for k, _ := range commands { switch k { - case "check": case "deployment list", "deployment status", "deployment pause", "deployment resume", "deployment fail", "deployment promote": - case "executor": case "fs ls", "fs cat", "fs stat": case "job deployments", "job dispatch", "job history", "job promote", "job revert": case "namespace list", "namespace delete", "namespace apply": case "operator raft", "operator raft list-peers", "operator raft remove-peer": - case "syslog": default: commandsInclude = append(commandsInclude, k) } } + // Hidden hides the commands from both help and autocomplete. Commands that + // users should not be running should be placed here, versus hiding + // subcommands from the main help, which should be filtered out of the + // commands above. + hidden := []string{"check", "executor", "syslog"} + cli := &cli.CLI{ - Name: "nomad", - Version: version.GetVersion().FullVersionNumber(true), - Args: args, - Commands: commands, - Autocomplete: true, - HelpFunc: cli.FilteredHelpFunc(commandsInclude, helpFunc), + Name: "nomad", + Version: version.GetVersion().FullVersionNumber(true), + Args: args, + Commands: commands, + Autocomplete: true, + HiddenCommands: hidden, + HelpFunc: cli.FilteredHelpFunc(commandsInclude, helpFunc), } exitCode, err := cli.Run() diff --git a/vendor/github.com/mitchellh/cli/cli.go b/vendor/github.com/mitchellh/cli/cli.go index 6d0c75add..61206d6aa 100644 --- a/vendor/github.com/mitchellh/cli/cli.go +++ b/vendor/github.com/mitchellh/cli/cli.go @@ -59,8 +59,20 @@ type CLI struct { // For example, if the key is "foo bar", then to access it our CLI // must be accessed with "./cli foo bar". See the docs for CLI for // notes on how this changes some other behavior of the CLI as well. + // + // The factory should be as cheap as possible, ideally only allocating + // a struct. The factory may be called multiple times in the course + // of a command execution and certain events such as help require the + // instantiation of all commands. Expensive initialization should be + // deferred to function calls within the interface implementation. Commands map[string]CommandFactory + // HiddenCommands is a list of commands that are "hidden". Hidden + // commands are not given to the help function callback and do not + // show up in autocomplete. The values in the slice should be equivalent + // to the keys in the command map. + HiddenCommands []string + // Name defines the name of the CLI. Name string @@ -116,6 +128,7 @@ type CLI struct { autocomplete *complete.Complete commandTree *radix.Tree commandNested bool + commandHidden map[string]struct{} subcommand string subcommandArgs []string topFlags []string @@ -298,6 +311,14 @@ func (c *CLI) init() { c.HelpWriter = os.Stderr } + // Build our hidden commands + if len(c.HiddenCommands) > 0 { + c.commandHidden = make(map[string]struct{}) + for _, h := range c.HiddenCommands { + c.commandHidden[h] = struct{}{} + } + } + // Build our command tree c.commandTree = radix.New() c.commandNested = false @@ -419,6 +440,11 @@ func (c *CLI) initAutocompleteSub(prefix string) complete.Command { return false } + // If the command is hidden, don't record it at all + if _, ok := c.commandHidden[fullKey]; ok { + return false + } + if cmd.Sub == nil { cmd.Sub = complete.Commands(make(map[string]complete.Command)) } @@ -566,6 +592,11 @@ func (c *CLI) helpCommands(prefix string) map[string]CommandFactory { panic("not found: " + k) } + // If this is a hidden command, don't show it + if _, ok := c.commandHidden[k]; ok { + continue + } + result[k] = raw.(CommandFactory) } diff --git a/vendor/vendor.json b/vendor/vendor.json index 142fec0a0..e8ada02aa 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -1033,10 +1033,10 @@ "revision": "7e024ce8ce18b21b475ac6baf8fa3c42536bf2fa" }, { - "checksumSHA1": "mjxSVrqngLZSyaQoEW2OLUb3oDs=", + "checksumSHA1": "UIqCj7qI0hhIMpAhS9YYqs2jD48=", "path": "github.com/mitchellh/cli", - "revision": "7a1a617034de956eee640dfa5a7407ccc8c8d7e6", - "revisionTime": "2017-09-06T23:20:06Z" + "revision": "65fcae5817c8600da98ada9d7edf26dd1a84837b", + "revisionTime": "2017-09-08T18:10:43Z" }, { "checksumSHA1": "ttEN1Aupb7xpPMkQLqb3tzLFdXs=",