Documentation
¶
Overview ¶
Package flagparser bridges between pflag and the GNU-getopt wording that rshell builtins are expected to match.
pflag is a fine option-parsing library but its error wording diverges from GNU coreutils on every common failure mode (unknown flag, missing argument, no-arg flag given a value, etc.), and it has no notion of GNU's left-to-right `--help` short-circuit. Two helpers fix that without touching pflag itself:
RewriteError translates pflag's error messages to GNU's getopt-style wording, optionally consulting the original argv to recover information pflag strips (e.g. the `=value` suffix on an unknown long flag).
TrialHelpTrimIndex decides whether the suffix after a `--help` token can be safely discarded so the builtin's handler can short-circuit. It trial-parses the prefix on a throw-away FlagSet; if every preceding option parses cleanly the suffix is dropped, otherwise the caller leaves the args alone and the real parse surfaces the earlier error — matching GNU's leftmost-bad- option rule.
Keeping this code in a dedicated package isolates the parser-shim concern from builtin registration. If we ever replace pflag with a hand-written GNU-getopt parser, the swap is local to this package.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func RewriteError ¶
RewriteError translates pflag's default error messages to the GNU-getopt-style wording that matches GNU coreutils byte-for-byte. It returns the rewritten message without a trailing newline or any "cmd:" prefix; callers prepend the builtin name themselves.
args is the argv that was handed to fs.Parse. It is consulted only for the unknown-long-flag case, where pflag strips the `=value` suffix from its error string but GNU getopt reports the full token (`--no-such=value`, not just `--no-such`).
Patterns covered:
pflag → GNU
"unknown flag: --foo" → "unrecognized option '--foo'"
("--foo=value" if the original argv used =value)
"unknown shorthand flag: 'X' in -..." → "invalid option -- 'X'"
"flag needs an argument: --foo" → "option '--foo' requires an argument"
"flag needs an argument: 'X' in -Y" → "option requires an argument -- 'X'"
`invalid argument "..." for "DESC" flag: → "option '--LONG' doesn't allow
flag does not allow an argument` an argument"
Unknown messages are returned unchanged.
func TrialHelpTrimIndex ¶
TrialHelpTrimIndex returns the index of the first `--help` in args if trial-parsing the prefix [0..helpIdx] with a fresh FlagSet (1) succeeds and (2) actually sets the `help` flag. The second check matters because pflag can consume the `--help` token in ways that don't set the flag:
- As the value of a preceding value-taker. `grep -e --help` makes `--help` the pattern for -e, not a help request; the trial parse accepts it but `Lookup("help").Changed` stays false.
- As a positional, for FlagSets that called `SetInterspersed(false)` (xargs, tr, read). Anything after the first positional is left for the builtin's handler — `--help` included.
If the trial both parses and sets `help`, the suffix after `--help` is safely discardable and the builtin's handler can short-circuit — matching GNU coreutils' left-to-right semantics. Otherwise we return (0, false) so the real fs.Parse reports any later error and the handler sees the full argv.
registerFlags is invoked on a throw-away FlagSet to set up the trial; it must be safe to call multiple times. Every builtin's MakeFlags is pure flag-registration today, so this is fine.
Types ¶
This section is empty.