diff options
| author | Ophestra <cat@gensokyo.uk> | 2025-02-22 23:11:17 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2025-02-22 23:11:17 +0900 |
| commit | dfa3217037d8c24181be24484892ecb950a2a5ba (patch) | |
| tree | e2022ad6ce2e11bbb7b4d0b38731a6c67561235f /command/parse.go | |
| parent | 8000a2febb546b3b68eddd9330d5709281068e9f (diff) | |
command: implement builder and parser
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'command/parse.go')
| -rw-r--r-- | command/parse.go | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/command/parse.go b/command/parse.go new file mode 100644 index 00000000..6081ca63 --- /dev/null +++ b/command/parse.go @@ -0,0 +1,72 @@ +package command + +import ( + "errors" + "log" +) + +var ( + ErrEmptyTree = errors.New("subcommand tree has no nodes") + ErrNoMatch = errors.New("did not match any subcommand") +) + +func (n *node) Parse(arguments []string) error { + if n.usage == "" { // root node has zero length usage + if n.next != nil { + panic("invalid toplevel state") + } + goto match + } + + if len(arguments) == 0 { + // unreachable: zero length args cause upper level to return with a help message + panic("attempted to parse with zero length args") + } + if arguments[0] != n.name { + if n.next == nil { + n.printf("%q is not a valid command", arguments[0]) + return ErrNoMatch + } + n.next.prefix = n.prefix + return n.next.Parse(arguments) + } + arguments = arguments[1:] + +match: + if n.child != nil { + if n.f != nil { + panic("invalid subcommand tree state") + } + // propagate help prefix early: flag set usage dereferences help + n.child.prefix = append(n.prefix, n.name) + } + + if n.set.Parsed() { + panic("invalid set state") + } + if err := n.set.Parse(arguments); err != nil { + return FlagError{err} + } + args := n.set.Args() + + if n.child != nil { + if len(args) == 0 { + return n.writeHelp() + } + return n.child.Parse(args) + } + + if n.f == nil { + n.printf("%q has no subcommands", n.name) + return ErrEmptyTree + } + return n.f(args) +} + +func (n *node) printf(format string, a ...any) { + if n.logf == nil { + log.Printf(format, a...) + } else { + n.logf(format, a...) + } +} |
