helpFn returns a function that generates usage (help) output for a given command.
()
| 320 | // helpFn returns a function that generates usage (help) |
| 321 | // output for a given command. |
| 322 | func helpFn() serpent.HandlerFunc { |
| 323 | return func(inv *serpent.Invocation) error { |
| 324 | // Check for invalid subcommands before printing help. |
| 325 | if len(inv.Args) > 0 && !usageWantsArgRe.MatchString(inv.Command.Use) { |
| 326 | _, _ = fmt.Fprintf(inv.Stderr, "---\nerror: unrecognized subcommand %q\n", inv.Args[0]) |
| 327 | } |
| 328 | if len(inv.Args) > 0 { |
| 329 | // Return an error so that exit status is non-zero when |
| 330 | // a subcommand is not found. |
| 331 | err := xerrors.Errorf("unrecognized subcommand %q", strings.Join(inv.Args, " ")) |
| 332 | if slices.Contains(os.Args, "--help") { |
| 333 | // Subcommand error is not wrapped in RunCommandErr if command |
| 334 | // is invoked with --help with no HelpHandler |
| 335 | return &serpent.RunCommandError{ |
| 336 | Cmd: inv.Command, |
| 337 | Err: err, |
| 338 | } |
| 339 | } |
| 340 | return err |
| 341 | } |
| 342 | |
| 343 | // We use stdout for help and not stderr since there's no straightforward |
| 344 | // way to distinguish between a user error and a help request. |
| 345 | // |
| 346 | // We buffer writes to stdout because the newlineLimiter writes one |
| 347 | // rune at a time. |
| 348 | outBuf := bufio.NewWriter(inv.Stdout) |
| 349 | out := newlineLimiter{w: outBuf, limit: 2} |
| 350 | tabwriter := tabwriter.NewWriter(&out, 0, 0, 2, ' ', 0) |
| 351 | err := usageTemplate.Execute(tabwriter, inv.Command) |
| 352 | if err != nil { |
| 353 | return xerrors.Errorf("execute template: %w", err) |
| 354 | } |
| 355 | err = tabwriter.Flush() |
| 356 | if err != nil { |
| 357 | return err |
| 358 | } |
| 359 | err = outBuf.Flush() |
| 360 | if err != nil { |
| 361 | return err |
| 362 | } |
| 363 | return nil |
| 364 | } |
| 365 | } |