diff --git a/argh.go b/argh.go index f1cc2f9..47f3ca1 100644 --- a/argh.go +++ b/argh.go @@ -26,7 +26,7 @@ func tracef(format string, v ...any) { return } - if _, file, line, ok := runtime.Caller(2); ok { + if _, file, line, ok := runtime.Caller(1); ok { format = fmt.Sprintf("%v:%v ", filepath.Base(file), line) + format } diff --git a/node.go b/node.go index a18e7b0..b4ce2e9 100644 --- a/node.go +++ b/node.go @@ -42,3 +42,5 @@ type StdinFlag struct{} type StopFlag struct{} type ArgDelimiter struct{} + +type Assign struct{} diff --git a/parser2.go b/parser2.go index c57c51c..66a0142 100644 --- a/parser2.go +++ b/parser2.go @@ -65,7 +65,7 @@ func (p *parser2) parseArgs() (*ParseTree, error) { tracef("parseArgs() returning ParseTree") - return &ParseTree{Nodes: nodes}, nil + return &ParseTree{Nodes: nodes}, p.errors.Err() } func (p *parser2) next() { @@ -149,6 +149,12 @@ func (p *parser2) parseCommand(cCfg *CommandConfig) Node { tracef("parseCommand(...) appending %s node=%+#v", tok, flagNode) nodes = append(nodes, flagNode) + case ASSIGN: + tracef("parseCommand(...) error on bare %s", p.tok) + + p.errors.Add(Position{Column: int(p.pos)}, "invalid bare assignment") + + break default: tracef("parseCommand(...) breaking on %s", p.tok) break @@ -175,10 +181,13 @@ func (p *parser2) parseIdent() Node { func (p *parser2) parseFlag(flCfgMap map[string]FlagConfig) Node { switch p.tok { case SHORT_FLAG: + tracef("parseFlag(...) parsing short flag with config=%+#v", flCfgMap) return p.parseShortFlag(flCfgMap) case LONG_FLAG: + tracef("parseFlag(...) parsing long flag with config=%+#v", flCfgMap) return p.parseLongFlag(flCfgMap) case COMPOUND_SHORT_FLAG: + tracef("parseFlag(...) parsing compound short flag with config=%+#v", flCfgMap) return p.parseCompoundShortFlag(flCfgMap) } @@ -238,7 +247,7 @@ func (p *parser2) parseConfiguredFlag(node *Flag, flCfg FlagConfig) Node { for i := 0; p.tok != EOL; i++ { if !flCfg.NValue.Contains(identIndex) { - tracef("parseLongFlag(...) identIndex=%d exceeds expected=%s; breaking") + tracef("parseConfiguredFlag(...) identIndex=%d exceeds expected=%v; breaking", identIndex, flCfg.NValue) break } @@ -248,18 +257,24 @@ func (p *parser2) parseConfiguredFlag(node *Flag, flCfg FlagConfig) Node { case ARG_DELIMITER: nodes = append(nodes, &ArgDelimiter{}) + continue + case ASSIGN: + nodes = append(nodes, &Assign{}) + continue case IDENT, STDIN_FLAG: name := fmt.Sprintf("%d", identIndex) - tracef("parseLongFlag(...) checking for name of identIndex=%d", identIndex) + tracef("parseConfiguredFlag(...) checking for name of identIndex=%d", identIndex) if len(flCfg.ValueNames) > identIndex { name = flCfg.ValueNames[identIndex] - tracef("parseLongFlag(...) setting name=%s from config value names", name) + tracef("parseConfiguredFlag(...) setting name=%s from config value names", name) } else if len(flCfg.ValueNames) == 1 && (flCfg.NValue == OneOrMoreValue || flCfg.NValue == ZeroOrMoreValue) { name = fmt.Sprintf("%s.%d", flCfg.ValueNames[0], identIndex) - tracef("parseLongFlag(...) setting name=%s from repeating value name", name) + tracef("parseConfiguredFlag(...) setting name=%s from repeating value name", name) + } else { + tracef("parseConfiguredFlag(...) setting name=%s", name) } values[name] = p.lit @@ -272,7 +287,7 @@ func (p *parser2) parseConfiguredFlag(node *Flag, flCfg FlagConfig) Node { identIndex++ default: - tracef("parseLongFlag(...) breaking on %s %q %v; setting buffered=true", p.tok, p.lit, p.pos) + tracef("parseConfiguredFlag(...) breaking on %s %q %v; setting buffered=true", p.tok, p.lit, p.pos) p.buffered = true if len(nodes) > 0 { diff --git a/parser2_test.go b/parser2_test.go index a355e2d..5265e09 100644 --- a/parser2_test.go +++ b/parser2_test.go @@ -673,21 +673,23 @@ func TestParser2(t *testing.T) { }, }, { - skip: true, - name: "total weirdo", args: []string{"PIZZAs", "^wAT@golf", "^^hecKing", "goose", "bonk", "^^FIERCENESS@-2"}, cfg: &argh.ParserConfig{ Prog: argh.CommandConfig{ Commands: map[string]argh.CommandConfig{ - "goose": argh.CommandConfig{NValue: 1}, + "goose": argh.CommandConfig{ + NValue: 1, + Flags: map[string]argh.FlagConfig{ + "FIERCENESS": argh.FlagConfig{NValue: 1}, + }, + }, }, Flags: map[string]argh.FlagConfig{ - "w": argh.FlagConfig{}, - "A": argh.FlagConfig{}, - "T": argh.FlagConfig{NValue: 1}, - "hecking": argh.FlagConfig{}, - "FIERCENESS": argh.FlagConfig{NValue: 1}, + "w": argh.FlagConfig{}, + "A": argh.FlagConfig{}, + "T": argh.FlagConfig{NValue: 1}, + "hecking": argh.FlagConfig{}, }, }, ScannerConfig: &argh.ScannerConfig{ @@ -705,25 +707,46 @@ func TestParser2(t *testing.T) { Nodes: []argh.Node{ &argh.Flag{Name: "w"}, &argh.Flag{Name: "A"}, - &argh.Flag{Name: "T", Values: map[string]string{"0": "golf"}}, + &argh.Flag{ + Name: "T", + Values: map[string]string{"0": "golf"}, + Nodes: []argh.Node{ + &argh.Assign{}, + &argh.Ident{Literal: "golf"}, + }, + }, }, }, &argh.ArgDelimiter{}, &argh.Flag{Name: "hecKing"}, &argh.ArgDelimiter{}, - &argh.Command{Name: "goose", Values: map[string]string{"0": "bonk"}}, - &argh.ArgDelimiter{}, - &argh.Flag{Name: "FIERCENESS", Values: map[string]string{"0": "-2"}}, + &argh.Command{ + Name: "goose", + Values: map[string]string{"0": "bonk"}, + Nodes: []argh.Node{ + &argh.ArgDelimiter{}, + &argh.Ident{Literal: "bonk"}, + &argh.ArgDelimiter{}, + &argh.Flag{ + Name: "FIERCENESS", + Values: map[string]string{"0": "-2"}, + Nodes: []argh.Node{ + &argh.Assign{}, + &argh.Ident{Literal: "-2"}, + }, + }, + }, + }, }, }, }, }, { - skip: true, - - name: "invalid bare assignment", - args: []string{"pizzas", "=", "--wat"}, - expErr: argh.ErrSyntax, + name: "invalid bare assignment", + args: []string{"pizzas", "=", "--wat"}, + expErr: argh.ScannerErrorList{ + &argh.ScannerError{Pos: argh.Position{Column: 8}, Msg: "invalid bare assignment"}, + }, expPT: []argh.Node{ &argh.Command{ Name: "pizzas", @@ -745,7 +768,10 @@ func TestParser2(t *testing.T) { pt, err := argh.ParseArgs2(tc.args, tc.cfg) if err != nil || tc.expErr != nil { - assert.ErrorIs(ct, err, tc.expErr) + if !assert.ErrorIs(ct, err, tc.expErr) { + spew.Dump(err, tc.expErr) + spew.Dump(pt) + } return } @@ -764,7 +790,9 @@ func TestParser2(t *testing.T) { pt, err := argh.ParseArgs2(tc.args, tc.cfg) if err != nil || tc.expErr != nil { - assert.ErrorIs(ct, err, tc.expErr) + if !assert.ErrorIs(ct, err, tc.expErr) { + spew.Dump(pt) + } return } diff --git a/scanner_error.go b/scanner_error.go index c9b7441..e5b634b 100644 --- a/scanner_error.go +++ b/scanner_error.go @@ -16,6 +16,7 @@ func (e ScannerError) Error() string { if e.Pos.IsValid() { return e.Pos.String() + ":" + e.Msg } + return e.Msg } @@ -64,6 +65,18 @@ func (el ScannerErrorList) Err() error { return el } +func (el ScannerErrorList) Is(other error) bool { + if _, ok := other.(ScannerErrorList); ok { + return el.Error() == other.Error() + } + + if v, ok := other.(*ScannerErrorList); ok { + return el.Error() == (*v).Error() + } + + return false +} + func PrintScannerError(w io.Writer, err error) { if list, ok := err.(ScannerErrorList); ok { for _, e := range list {