argh/cmd/argh-from-urfave-cli/main.go

122 lines
2.5 KiB
Go

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)
}
}