feat(diary): boot list, help and completion requests quietly (quick-261028-rqc)
- 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
This commit is contained in:
@@ -1,47 +1,100 @@
|
||||
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 for help: before "--" they hold --help or a
|
||||
// single-dash cluster that reaches h. 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 and
|
||||
// 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.
|
||||
// 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 == "--":
|
||||
return false
|
||||
break scan
|
||||
case a == "--env":
|
||||
i++
|
||||
case a == "--help":
|
||||
return true
|
||||
case len(a) >= 2 && a[0] == '-' && a[1] != '-':
|
||||
if clusterHasHelp(a[1:]) {
|
||||
return true
|
||||
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
|
||||
}
|
||||
}
|
||||
return false
|
||||
switch word {
|
||||
case "", "list", "help", completeRequestCmd, completeNoDescRequestCmd:
|
||||
return true
|
||||
}
|
||||
return help
|
||||
}
|
||||
|
||||
// clusterHasHelp reports whether a shorthand cluster (the letters after the
|
||||
// dash) reaches h before a letter that is not a global shorthand.
|
||||
func clusterHasHelp(cluster string) bool {
|
||||
// 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++ {
|
||||
switch 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':
|
||||
return true
|
||||
help, ok = true, true
|
||||
case 'v', 'q', 'n':
|
||||
default:
|
||||
return false
|
||||
return help, ok
|
||||
}
|
||||
}
|
||||
return false
|
||||
return help, ok
|
||||
}
|
||||
|
||||
// bootQuiet applies the help-only rule of Bootstrap and Setup: with Args
|
||||
|
||||
Reference in New Issue
Block a user