this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

cmd/cue: refactor help texts and topics

Because additional help topics used to be non-runnable commands hanging
from the root `cue` command, they used to behave in rather odd ways.
For example, even though we often suggested using them via
`cue help filetypes`, they still worked as `cue filetypes` or
`cue filetypes --help` for no good reason.

Hang the non-runnable commands from the `cue help` subcommand,
meaning that `cue filetypes` is now treated as an unknown command.
This seems better for the user experience too; for example,
if a user tried to tab-complete `cue fi`, we should only suggest
`cue fix` and not `cue filetypes`.

Because help topics now hang as subcommands from `cue help`,
spf13/cobra's default help template would no longer show them
in the help text for the root command.
Start using our own template, as a simplified and tweaked version of
the default template, which resolves this issue.

Our own template also tweaks a few other sharp edges while here:
* Do not show global flags in `cue help`; they take up space,
and they aren't useful unless a user is running a subcommand.
Subcommand help texts already list the same global flags.
* Suggest `cue help [command]` rather than `cue [command] --help`,
which reads better and is shorter to type, and is also consistent
with additional help topics such as `cue help filetypes`.
* Hide `cue help` from the available commands list;
we already suggest it as the way to get help texts, so we don't need
to show it twice in the top-level help text.

This is a precursor to removing support for `cue foo` as a short-hand
for `cue cmd foo`, as some of the logic to handle these extra
root-level commands is shared.

For #2519.

Signed-off-by: Daniel Martí <mvdan@mvdan.cc>
Change-Id: I76d0c687e88bc3f237d952a98b4578516f36c5c0
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1199622
Unity-Result: CUE porcuepine <cue.porcuepine@gmail.com>
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>
Reviewed-by: Matthew Sackman <matthew@cue.works>

+119 -90
+2 -2
cmd/cue/cmd/flags.go
··· 64 64 func addOutFlags(f *pflag.FlagSet, allowNonCUE bool) { 65 65 if allowNonCUE { 66 66 f.String(string(flagOut), "", 67 - `output format (run 'cue filetypes' for more info)`) 67 + `output format (run 'cue help filetypes' for more info)`) 68 68 } 69 69 f.StringP(string(flagOutFile), "o", "", 70 - `filename or - for stdout with optional file prefix (run 'cue filetypes' for more info)`) 70 + `filename or - for stdout with optional file prefix (run 'cue help filetypes' for more info)`) 71 71 f.BoolP(string(flagForce), "f", false, "force overwriting existing files") 72 72 } 73 73
+47 -5
cmd/cue/cmd/help.go
··· 36 36 // but knows how to load custom commands in `cue help cmd`. 37 37 func newHelpCmd(c *Command) *cobra.Command { 38 38 cmd := &cobra.Command{ 39 - Use: "help [command]", 40 - Short: "show help text for a command or topic", 39 + Use: "help [command]", 40 + Short: "show help text for a command or topic", 41 + Hidden: true, // not shown as a runnable command in `cue help` 41 42 Run: func(_ *cobra.Command, args []string) { 42 43 findCmd := func() (*cobra.Command, bool) { 43 44 cmd, rest, err := c.Root().Find(args) ··· 90 91 return cmd 91 92 } 92 93 93 - // TODO(mvdan): having the help topics as top-level commands means that `cue topic` 94 - // is taken and works as well as `cue help topic`, which is unnecessary. 95 - // Consider removing support for the short form at some point. 94 + // We use a custom Cobra help text template for the sake of being a bit more 95 + // in control of its formatting, as well as the contents of the root `cue help`. 96 + // 97 + // TODO(mvdan): the text below should not jump straight into `cue cmd`, 98 + // and instead give a high level overview of CUE and its commands. 99 + var helpTemplate = ` 100 + {{- if not .HasParent}}{{/* Special template for the root help. */ -}} 101 + cue evaluates CUE files, an extension of JSON, and sends them 102 + to user-defined commands for processing. 103 + 104 + Commands are defined in CUE as follows: 105 + 106 + import "tool/exec" 107 + command: deploy: { 108 + exec.Run 109 + cmd: "kubectl" 110 + args: ["-f", "deploy"] 111 + in: json.Encode(userValue) // encode the emitted configuration. 112 + } 113 + 114 + cue can also combine the results of http or grpc request with the input 115 + configuration for further processing. For more information on defining commands 116 + run 'cue help cmd' or go to cuelang.org/pkg/cmd. 117 + 118 + For more information on writing CUE configuration files see cuelang.org. 119 + 120 + Usage: 121 + {{.CommandPath}} [command] 122 + 123 + Available Commands:{{range .Commands}}{{if .IsAvailableCommand}} 124 + {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}} 125 + 126 + Use "{{.CommandPath}} help [command]" for more information about a command. 127 + 128 + {{/* We want to show additional help topics from the root command's help text 129 + even though they are only reachable via 'cue help'. */ -}} 130 + Additional help topics:{{range .Commands}}{{if eq .Name "help"}}{{range .Commands}} 131 + {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}} 132 + {{else}}{{/* Subcommands use a fairly standard template. */ -}} 133 + {{with (or .Long .Short)}}{{. | trimTrailingWhitespaces}} 134 + 135 + {{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}} 136 + {{- end -}} 137 + ` 96 138 97 139 var helpTopics = []*cobra.Command{ 98 140 commandsHelp,
+25 -46
cmd/cue/cmd/root.go
··· 186 186 // The returned error is always nil, and is a historical artifact. 187 187 func New(args []string) (*Command, error) { 188 188 cmd := &cobra.Command{ 189 - Use: "cue", 189 + Use: "cue", 190 + // TODO: the short help text below seems to refer to `cue cmd`, like helpTemplate. 190 191 Short: "cue emits configuration files to user-defined commands.", 191 - // TODO(mvdan): the text below should not jump straight into `cue cmd`, 192 - // and instead give a high level overview of CUE and its commands. 193 - // TODO(mvdan): cobra's help text template ends with 194 - // Use "cue [command] --help" for more information about a command. 195 - // which isn't great; use our own template to say 196 - // Use "cue help [command]" for more information about a command. 197 - // TODO(mvdan): cobra's help text template suggests help topics 198 - // such as `cue inputs`; swap with `cue help inputs`. 199 - Long: `cue evaluates CUE files, an extension of JSON, and sends them 200 - to user-defined commands for processing. 201 - 202 - Commands are defined in CUE as follows: 203 - 204 - import "tool/exec" 205 - command: deploy: { 206 - exec.Run 207 - cmd: "kubectl" 208 - args: ["-f", "deploy"] 209 - in: json.Encode(userValue) // encode the emitted configuration. 210 - } 211 - 212 - cue can also combine the results of http or grpc request with the input 213 - configuration for further processing. For more information on defining commands 214 - run 'cue help cmd' or go to cuelang.org/pkg/cmd. 215 - 216 - For more information on writing CUE configuration files see cuelang.org.`, 217 192 218 193 // ArbitraryArgs allows us to forward the top-level RunE to cmdCmd.RunE, 219 194 // which supports `cue mycmd` as a short-cut for `cue cmd mycmd`. ··· 243 218 cmdCmd := newCmdCmd(c) 244 219 c.cmd = cmdCmd 245 220 246 - subCommands := []*cobra.Command{ 221 + addGlobalFlags(cmd.PersistentFlags()) 222 + // We add the injection flags to the root command for the sake of the short form "cue -t foo=bar mycmd". 223 + // Note that they are not persistent, so that they aren't inherited by sub-commands like "cue fmt". 224 + addInjectionFlags(cmd.Flags(), false, true) 225 + 226 + // Cobra's --help flag shows up in help text by default, which is unnecessary. 227 + cmd.InitDefaultHelpFlag() 228 + cmd.Flag("help").Hidden = true 229 + 230 + // "help" is treated as a special command by cobra. 231 + // We use our own template to be more in control of the structure of `cue help`. 232 + // Note that we need to add helpCmd as a subcommand first, for cobra to work out 233 + // the proper help text paddings for additional help topics. 234 + helpCmd := newHelpCmd(c) 235 + cmd.AddCommand(helpCmd) 236 + for _, sub := range helpTopics { 237 + helpCmd.AddCommand(sub) 238 + } 239 + cmd.SetHelpCommand(helpCmd) 240 + cmd.SetHelpTemplate(helpTemplate) 241 + 242 + for _, sub := range []*cobra.Command{ 247 243 cmdCmd, 248 244 newCompletionCmd(c), 249 245 newEvalCmd(c), ··· 261 257 // Hidden 262 258 newAddCmd(c), 263 259 newLoginCmd(c), 264 - } 265 - subCommands = append(subCommands, helpTopics...) 266 - 267 - addGlobalFlags(cmd.PersistentFlags()) 268 - // We add the injection flags to the root command for the sake of the short form "cue -t foo=bar mycmd". 269 - // Note that they are not persistent, so that they aren't inherited by sub-commands like "cue fmt". 270 - addInjectionFlags(cmd.Flags(), false, true) 271 - 272 - for _, sub := range subCommands { 260 + } { 273 261 cmd.AddCommand(sub) 274 262 } 275 - 276 - // Cobra's --help flag shows up in help text by default, which is unnecessary. 277 - cmd.InitDefaultHelpFlag() 278 - cmd.Flag("help").Hidden = true 279 - 280 - // "help" is treated as a special command by cobra. 281 - // TODO(mvdan): hide this command; `cue help` showing itself in the list of commands 282 - // is not particularly helpful, and we already mention it as the way to get help. 283 - cmd.SetHelpCommand(newHelpCmd(c)) 284 263 285 264 // For `cue mycmd` to be a shortcut for `cue cmd mycmd`. 286 265 cmd.RunE = cmdCmd.RunE
+30 -37
cmd/cue/cmd/testdata/script/help.txtar
··· 28 28 exec cue mod publish --help 29 29 stdout -count=1 '^Publish the current module to an OCI registry\.' 30 30 31 - # Requesting additional help topics, with or without "help" in between. 31 + # Requesting additional help topics; the form without "help" is phased out. 32 32 33 33 exec cue help filetypes 34 34 stdout -count=1 '^The cue tools supports the following file types:$' 35 35 36 - exec cue filetypes 37 - stdout -count=1 '^The cue tools supports the following file types:$' 36 + ! exec cue filetypes 37 + ! stdout . 38 + stderr -count=1 '^no commands defined' 39 + # TODO(mvdan): once `cue somecmd` is phased out, we can give a better error message here. 40 + # stderr -count=1 '^unknown command' 38 41 39 42 # Requesting help for missing commands and sub-commands fails and prints the help text. 40 43 ··· 75 78 For more information on writing CUE configuration files see cuelang.org. 76 79 77 80 Usage: 78 - cue [flags] 79 81 cue [command] 80 82 81 83 Available Commands: 82 - cmd run a user-defined workflow command 83 - completion Generate completion script 84 - def print consolidated definitions 85 - eval evaluate and print a configuration 86 - export output data in a standard format 87 - fix rewrite packages to latest standards 88 - fmt formats CUE configuration files 89 - get add non-CUE dependencies to the current module 90 - help show help text for a command or topic 91 - import convert other formats to CUE files 92 - login log into a CUE registry 93 - mod module maintenance 94 - trim remove superfluous fields 95 - version print CUE version 96 - vet validate data 84 + cmd run a user-defined workflow command 85 + completion Generate completion script 86 + def print consolidated definitions 87 + eval evaluate and print a configuration 88 + export output data in a standard format 89 + fix rewrite packages to latest standards 90 + fmt formats CUE configuration files 91 + get add non-CUE dependencies to the current module 92 + import convert other formats to CUE files 93 + login log into a CUE registry 94 + mod module maintenance 95 + trim remove superfluous fields 96 + version print CUE version 97 + vet validate data 97 98 98 - Flags: 99 - -E, --all-errors print all available errors 100 - -i, --ignore proceed in the presence of errors 101 - -s, --simplify simplify output 102 - --strict report errors for lossy mappings 103 - --trace trace computation 104 - -v, --verbose print information about progress 99 + Use "cue help [command]" for more information about a command. 105 100 106 101 Additional help topics: 107 - cue commands user-defined commands 108 - cue embed file embedding 109 - cue environment environment variables 110 - cue filetypes supported file types and qualifiers 111 - cue flags common flags for composing packages 112 - cue injection inject files or values into specific fields for a build 113 - cue inputs package list, patterns, and files 114 - cue modules module support 115 - cue registryconfig module registry configuration 116 - 117 - Use "cue [command] --help" for more information about a command. 102 + cue help commands user-defined commands 103 + cue help embed file embedding 104 + cue help environment environment variables 105 + cue help filetypes supported file types and qualifiers 106 + cue help flags common flags for composing packages 107 + cue help injection inject files or values into specific fields for a build 108 + cue help inputs package list, patterns, and files 109 + cue help modules module support 110 + cue help registryconfig module registry configuration
+15
cmd/cue/cmd/testdata/script/unknown_args.txtar
··· 1 + ! exec cue unknown 2 + ! stdout . 3 + cmp stderr unknown_cmd.out 4 + 5 + ! exec cue --unknown 6 + ! stdout . 7 + cmp stderr unknown_flag.out 8 + 9 + -- unknown_cmd.out -- 10 + no commands defined 11 + Ensure custom commands are defined in a "_tool.cue" file. 12 + Run 'cue help cmd' to list available custom commands. 13 + Run 'cue help' to see the built-in 'cue' commands. 14 + -- unknown_flag.out -- 15 + unknown flag: --unknown