From c713d85bd34b896cdb70f3cf14f3f01d38cd0349 Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Tue, 11 Oct 2022 09:46:35 -0400 Subject: [PATCH] Like what would urfave/cli integration look --- cmd/argh-from-urfave-cli/main.go | 121 +++++++++++++++++++++++++++++++ go.mod | 4 + go.sum | 8 ++ parser_config.go | 30 +++++++- 4 files changed, 161 insertions(+), 2 deletions(-) create mode 100644 cmd/argh-from-urfave-cli/main.go diff --git a/cmd/argh-from-urfave-cli/main.go b/cmd/argh-from-urfave-cli/main.go new file mode 100644 index 0000000..68bb4ac --- /dev/null +++ b/cmd/argh-from-urfave-cli/main.go @@ -0,0 +1,121 @@ +package main + +import ( + "context" + "encoding/json" + "fmt" + "io" + "os" + + "git.meatballhat.com/x/argh" + "github.com/urfave/cli/v2" +) + +func main() { + pc := argh.NewParserConfig() + + app := &cli.App{ + Name: "argh-from-urfave-cli", + Flags: []cli.Flag{ + &cli.StringFlag{Name: "name", Aliases: []string{"n"}}, + &cli.BoolFlag{Name: "happy", Aliases: []string{"H"}}, + }, + Action: func(cCtx *cli.Context) error { + return dumpAST(cCtx.App.Writer, os.Args, pc) + }, + Commands: []*cli.Command{ + { + Name: "poof", + Flags: []cli.Flag{ + &cli.StringFlag{Name: "like", Aliases: []string{"L"}}, + &cli.BoolFlag{Name: "loudly", Aliases: []string{"l"}}, + }, + Action: func(cCtx *cli.Context) error { + return dumpAST(cCtx.App.Writer, os.Args, pc) + }, + Subcommands: []*cli.Command{ + { + Name: "immediately", + Flags: []cli.Flag{ + &cli.BoolFlag{Name: "really", Aliases: []string{"X"}}, + }, + Action: func(cCtx *cli.Context) error { + return dumpAST(cCtx.App.Writer, os.Args, pc) + }, + }, + }, + }, + }, + } + + mapFlags(pc.Prog.Flags, app.Flags, true) + mapCommands(pc.Prog, app.Commands) + + app.RunContext(context.Background(), os.Args) +} + +func dumpAST(w io.Writer, args []string, pc *argh.ParserConfig) error { + pt, err := argh.ParseArgs(args, pc) + if err != nil { + return err + } + + q := argh.NewQuerier(pt.Nodes) + + jsonBytes, err := json.MarshalIndent( + map[string]any{ + "ast": q.AST(), + "config": pc, + }, + "", " ", + ) + if err != nil { + return err + } + + _, err = fmt.Fprintln(w, string(jsonBytes)) + return err +} + +func mapFlags(cmdFlags *argh.Flags, flags []cli.Flag, persist bool) { + for _, fl := range flags { + nValue := argh.ZeroValue + + if df, ok := fl.(cli.DocGenerationFlag); ok { + if df.TakesValue() { + if dsf, ok := df.(cli.DocGenerationSliceFlag); ok && dsf.IsSliceFlag() { + nValue = argh.OneOrMoreValue + } else { + nValue = argh.NValue(1) + } + } + } + + flCfg := argh.FlagConfig{ + NValue: nValue, + Persist: persist, + ValueNames: []string{fl.Names()[0]}, + } + + for _, flAlias := range fl.Names() { + cmdFlags.Set(flAlias, flCfg) + } + } +} + +func mapCommands(cCfg *argh.CommandConfig, cmds []*cli.Command) { + for _, cmd := range cmds { + // TODO: vary nValue if/when cli.Command accepts positional args? + cmdCfg := argh.NewCommandConfig() + + mapFlags(cmdCfg.Flags, cmd.Flags, false) + + cCfg.Commands.Set(cmd.Name, *cmdCfg) + + if len(cmd.Subcommands) == 0 { + return + } + + mapCommands(cmdCfg, cmd.Subcommands) + } +} diff --git a/go.mod b/go.mod index 98f3d7f..12f9001 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,10 @@ require ( ) require ( + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/urfave/cli/v2 v2.19.2 // indirect + github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 5164829..9746cd3 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,21 @@ +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/urfave/cli/v2 v2.19.2 h1:eXu5089gqqiDQKSnFW+H/FhjrxRGztwSxlTsVK7IuqQ= +github.com/urfave/cli/v2 v2.19.2/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/parser_config.go b/parser_config.go index 0226425..468341f 100644 --- a/parser_config.go +++ b/parser_config.go @@ -44,8 +44,7 @@ func NewParserConfig(opts ...ParserOption) *ParserConfig { } if pCfg.Prog == nil { - pCfg.Prog = &CommandConfig{} - pCfg.Prog.init() + pCfg.Prog = NewCommandConfig() } if pCfg.ScannerConfig == nil { @@ -62,6 +61,13 @@ type CommandConfig struct { Commands *Commands } +func NewCommandConfig() *CommandConfig { + cmdCfg := &CommandConfig{} + cmdCfg.init() + + return cmdCfg +} + func (cCfg *CommandConfig) init() { if cCfg.ValueNames == nil { cCfg.ValueNames = []string{} @@ -131,6 +137,16 @@ func (fl *Flags) Get(name string) (FlagConfig, bool) { return flCfg, ok } +func (fl *Flags) Set(name string, flCfg FlagConfig) { + tracef("Flags.Set(%[1]q, %+#[2]v)", name, flCfg) + + if fl.Map == nil { + fl.Map = map[string]FlagConfig{} + } + + fl.Map[name] = flCfg +} + type Commands struct { Map map[string]CommandConfig } @@ -145,3 +161,13 @@ func (cmd *Commands) Get(name string) (CommandConfig, bool) { cmdCfg, ok := cmd.Map[name] return cmdCfg, ok } + +func (cmd *Commands) Set(name string, cmdCfg CommandConfig) { + tracef("Commands.Set(%[1]q, %+#[2]v)", name, cmdCfg) + + if cmd.Map == nil { + cmd.Map = map[string]CommandConfig{} + } + + cmd.Map[name] = cmdCfg +}