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:
Jakub Zych
2026-10-28 21:47:42 +01:00
parent 6b9becd994
commit 6c606c666b
7 changed files with 231 additions and 24 deletions

View File

@@ -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