- helpOnly also counts no command word, list, help, cobra's shell completion requests and --help=<bool>, read the way pflag does - TestHelpOnlyAgreesWithCobra pins the classification against bonfire's real dispatch, with the passthrough --help case as the exception - console and logging docs describe which invocations boot quietly
109 lines
3.5 KiB
Go
109 lines
3.5 KiB
Go
package diary
|
|
|
|
import (
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// The hidden commands of cobra's shell completion (cobra.ShellCompRequestCmd
|
|
// and cobra.ShellCompNoDescRequestCmd), named here so diary does not link
|
|
// cobra; TestHelpOnlyAgreesWithCobra pins them.
|
|
const (
|
|
completeRequestCmd = "__complete"
|
|
completeNoDescRequestCmd = "__completeNoDesc"
|
|
)
|
|
|
|
// helpOnly reports whether args, a binary's command line without the
|
|
// program name, only ask the binary to describe itself, so no command runs:
|
|
//
|
|
// - there is no command word (the first token before "--" that is neither
|
|
// a flag nor the value of --env, bonfire's rule under which Execute
|
|
// prints the list): a bare invocation, only global options, -h or
|
|
// --help;
|
|
// - the command word is list, help or one of cobra's shell completion
|
|
// requests (__complete, __completeNoDesc);
|
|
// - the help flag is set before "--", also after the command word, the
|
|
// way cobra honours it: --help, --help=<bool> read by strconv.ParseBool
|
|
// the way pflag does (the last occurrence wins, an unparsable value is
|
|
// ignored), or a single-dash cluster that reaches h (-h, -vh, -nh).
|
|
//
|
|
// It is a tolerant pre-scan of the raw arguments, made before plugins boot,
|
|
// and reads them the way bonfire.PeekGlobals does: it stops at "--", skips
|
|
// the value of --env and reads a single-dash cluster letter by letter,
|
|
// stopping at the first letter that is not a global shorthand (v, q, n, h).
|
|
// It never fails. An unknown or misspelled command word is not help-only
|
|
// (that is unknowable before boot). It cannot tell a passthrough command
|
|
// (whose --help reaches its Run) from another, so "<passthrough> --help"
|
|
// counts; the root's OnGlobals hook (ApplyGlobals) restores the console
|
|
// levels before that command runs.
|
|
func helpOnly(args []string) bool {
|
|
help := false
|
|
word := ""
|
|
scan:
|
|
for i := 0; i < len(args); i++ {
|
|
a := args[i]
|
|
switch {
|
|
case a == "--":
|
|
break scan
|
|
case a == "--env":
|
|
i++
|
|
case a == "--help":
|
|
help = true
|
|
case strings.HasPrefix(a, "--help="):
|
|
if v, err := strconv.ParseBool(strings.TrimPrefix(a, "--help=")); err == nil {
|
|
help = v
|
|
}
|
|
case len(a) >= 2 && a[0] == '-' && a[1] != '-':
|
|
if v, ok := clusterHelp(a[1:]); ok {
|
|
help = v
|
|
}
|
|
case strings.HasPrefix(a, "-"):
|
|
case word == "":
|
|
word = a
|
|
}
|
|
}
|
|
switch word {
|
|
case "", "list", "help", completeRequestCmd, completeNoDescRequestCmd:
|
|
return true
|
|
}
|
|
return help
|
|
}
|
|
|
|
// clusterHelp reads a shorthand cluster (the letters after the dash) the
|
|
// way bonfire.PeekGlobals does and reports the help value it sets: ok is
|
|
// true when the cluster reaches h before a letter that is not a global
|
|
// shorthand, and -h=<bool> (-vh=false) sets the value read by
|
|
// strconv.ParseBool.
|
|
func clusterHelp(cluster string) (help, ok bool) {
|
|
for i := 0; i < len(cluster); i++ {
|
|
r := cluster[i]
|
|
if i+1 < len(cluster) && cluster[i+1] == '=' {
|
|
if r != 'h' {
|
|
return help, ok
|
|
}
|
|
if v, err := strconv.ParseBool(cluster[i+2:]); err == nil {
|
|
return v, true
|
|
}
|
|
return help, ok
|
|
}
|
|
switch r {
|
|
case 'h':
|
|
help, ok = true, true
|
|
case 'v', 'q', 'n':
|
|
default:
|
|
return help, ok
|
|
}
|
|
}
|
|
return help, ok
|
|
}
|
|
|
|
// bootQuiet applies the help-only rule of Bootstrap and Setup: with Args
|
|
// set, no -v and arguments that only ask for help, the setup is installed
|
|
// with Quiet, which raises only the console channels to warn.
|
|
func bootQuiet(opts Options) Options {
|
|
if opts.Args != nil && opts.Verbosity == 0 && helpOnly(opts.Args) {
|
|
opts.Quiet = true
|
|
}
|
|
return opts
|
|
}
|