From 367a0f41c57953e487ebabaab2cfd477cf238ce9 Mon Sep 17 00:00:00 2001 From: David Gamba Date: Wed, 12 Jun 2024 23:28:00 -0600 Subject: [PATCH] wip: start printing tree --- bake/ast.go | 12 ++++-- bake/main.go | 79 ------------------------------------ bake/plugin.go | 2 +- bake/tree.go | 107 +++++++++++++++++++++++++++++++++++++++++++++++++ bake/utils.go | 13 ++++++ 5 files changed, 129 insertions(+), 84 deletions(-) create mode 100644 bake/tree.go diff --git a/bake/ast.go b/bake/ast.go index b6d9159..6927a8b 100644 --- a/bake/ast.go +++ b/bake/ast.go @@ -185,7 +185,8 @@ func LoadAst(ctx context.Context, opt *getoptions.GetOpt, dir string) error { // Check function declarations for exported functions case *ast.FuncDecl: if x.Name.IsExported() { - name := x.Name.Name + fnName := x.Name.Name + name := "" description := strings.TrimSpace(x.Doc.Text()) // var buf bytes.Buffer // printer.Fprint(&buf, p.fset, x.Type) @@ -233,13 +234,13 @@ func LoadAst(ctx context.Context, opt *getoptions.GetOpt, dir string) error { if re.MatchString(description) { // Get first word from string name = strings.Split(description, " ")[0] - description = strings.TrimPrefix(description, name+" -") + description = strings.TrimPrefix(description, fnName+" -") description = strings.TrimSpace(description) } } else { - name = camelToKebab(name) + name = camelToKebab(fnName) } - cmd := ot.AddCommand(name, description) + cmd := ot.AddCommand(fnName, name, description) // Check for Expressions of opt type ast.Inspect(n, func(n ast.Node) bool { @@ -295,6 +296,9 @@ func LoadAst(ctx context.Context, opt *getoptions.GetOpt, dir string) error { return true }) } + + fmt.Printf("OptTree: %s\n", ot) + return nil } diff --git a/bake/main.go b/bake/main.go index 727f4b8..45430a3 100644 --- a/bake/main.go +++ b/bake/main.go @@ -1,17 +1,13 @@ package main import ( - "bytes" "context" "errors" "fmt" "io" "log" "os" - "strings" - "unicode" - "github.com/DavidGamba/dgtools/run" "github.com/DavidGamba/go-getoptions" ) @@ -91,81 +87,6 @@ func program(args []string) int { return 0 } -type TaskDefinitionFn func(ctx context.Context, opt *getoptions.GetOpt) error -type TaskFn func(*getoptions.GetOpt) getoptions.CommandFn - -type OptTree struct { - Root *OptNode -} - -type OptNode struct { - Name string - Opt *getoptions.GetOpt - Children map[string]*OptNode -} - -func NewOptTree(opt *getoptions.GetOpt) *OptTree { - return &OptTree{ - Root: &OptNode{ - Name: "root", - Opt: opt, - Children: make(map[string]*OptNode), - }, - } -} - -func (ot *OptTree) AddCommand(name, description string) *getoptions.GetOpt { - keys := strings.Split(name, ":") - // Logger.Printf("keys: %v\n", keys) - node := ot.Root - var cmd *getoptions.GetOpt - for i, key := range keys { - n, ok := node.Children[key] - if ok { - // Logger.Printf("key: %v already defined, parent: %s\n", key, node.Name) - node = n - cmd = n.Opt - if len(keys) == i+1 { - cmd.Self(key, description) - } - continue - } - // Logger.Printf("key: %v not defined, parent: %s\n", key, node.Name) - desc := "" - if len(keys) == i+1 { - desc = description - } - cmd = node.Opt.NewCommand(key, desc) - node.Children[key] = &OptNode{ - Name: key, - Opt: cmd, - Children: make(map[string]*OptNode), - } - node = node.Children[key] - if len(keys) == i+1 { - cmd.SetCommandFn(func(ctx context.Context, opt *getoptions.GetOpt, args []string) error { - // TODO: Run os.exec call to the built binary with keys as the arguments - fmt.Printf("Running %v\n", InputArgs) - c := []string{"./bake"} - run.CMD(append(c, InputArgs...)...).Dir(Dir).Run() - return nil - }) - } - } - return cmd -} - -func camelToKebab(camel string) string { - var buffer bytes.Buffer - for i, ch := range camel { - if unicode.IsUpper(ch) && i > 0 && !unicode.IsUpper([]rune(camel)[i-1]) { - buffer.WriteRune('-') - } - buffer.WriteRune(unicode.ToLower(ch)) - } - return buffer.String() -} - func ListDescriptionsRun(dir string) getoptions.CommandFn { return func(ctx context.Context, opt *getoptions.GetOpt, args []string) error { m := make(map[string]FuncDecl) diff --git a/bake/plugin.go b/bake/plugin.go index 9448134..d1446db 100644 --- a/bake/plugin.go +++ b/bake/plugin.go @@ -80,7 +80,7 @@ func loadOptFns(ctx context.Context, plug *plugin.Plugin, opt *getoptions.GetOpt } else { name = camelToKebab(name) } - cmd := ot.AddCommand(name, description) + cmd := ot.AddCommand(name, name, description) fnr := tfn(cmd) cmd.SetCommandFn(fnr) if tmOk { diff --git a/bake/tree.go b/bake/tree.go new file mode 100644 index 0000000..f2023e8 --- /dev/null +++ b/bake/tree.go @@ -0,0 +1,107 @@ +package main + +import ( + "context" + "fmt" + "regexp" + "strings" + + "github.com/DavidGamba/dgtools/run" + "github.com/DavidGamba/go-getoptions" +) + +// type TaskDefinitionFn func(ctx context.Context, opt *getoptions.GetOpt) error +// type TaskFn func(*getoptions.GetOpt) getoptions.CommandFn + +type OptTree struct { + Root *OptNode +} + +type OptNode struct { + Name string + Opt *getoptions.GetOpt + Children map[string]*OptNode + Parent string + Description string + FnName string +} + +func NewOptTree(opt *getoptions.GetOpt) *OptTree { + return &OptTree{ + Root: &OptNode{ + Name: "", + Parent: "", + Opt: opt, + Description: "", + Children: make(map[string]*OptNode), + FnName: "", + }, + } +} + +// Regex for description: fn-name - description +var descriptionRe = regexp.MustCompile(`^\w\S+ -`) + +func (ot *OptTree) AddCommand(fnName, name, description string) *getoptions.GetOpt { + keys := strings.Split(name, ":") + // Logger.Printf("keys: %v\n", keys) + node := ot.Root + var cmd *getoptions.GetOpt + for i, key := range keys { + n, ok := node.Children[key] + if ok { + // Logger.Printf("key: %v already defined, parent: %s\n", key, node.Name) + node = n + cmd = n.Opt + if len(keys) == i+1 { + cmd.Self(key, description) + } + continue + } + // Logger.Printf("key: %v not defined, parent: %s\n", key, node.Name) + desc := "" + if len(keys) == i+1 { + desc = description + } + cmd = node.Opt.NewCommand(key, desc) + node.Children[key] = &OptNode{ + Name: key, + Parent: node.Name, + Opt: cmd, + Children: make(map[string]*OptNode), + Description: desc, + FnName: fnName, + } + node = node.Children[key] + if len(keys) == i+1 { + cmd.SetCommandFn(func(ctx context.Context, opt *getoptions.GetOpt, args []string) error { + // TODO: Run os.exec call to the built binary with keys as the arguments + fmt.Printf("Running %v\n", InputArgs) + c := []string{"./bake"} + run.CMD(append(c, InputArgs...)...).Dir(Dir).Run() + return nil + }) + } + } + return cmd +} + +func (ot *OptTree) String() string { + return ot.Root.String() +} + +func (on *OptNode) String() string { + out := "" + parent := on.Parent + if parent == "" { + parent = "opt" + } + if on.Name != "" { + out += fmt.Sprintf("%s := %s.NewCommand(\"%s\", \"%s\")\n", on.Name, parent, on.Name, on.Description) + out += fmt.Sprintf("%s.SetCommandFn(%s(%s))\n", on.Name, on.FnName, on.Name) + } + for _, child := range on.Children { + out += child.String() + } + return out +} diff --git a/bake/utils.go b/bake/utils.go index efc01a1..148a344 100644 --- a/bake/utils.go +++ b/bake/utils.go @@ -1,11 +1,13 @@ package main import ( + "bytes" "fmt" "go/ast" "go/parser" "go/token" "iter" + "unicode" "golang.org/x/tools/go/packages" ) @@ -45,3 +47,14 @@ func parsedFiles(dir string) iter.Seq2[parsedFile, error] { } } } + +func camelToKebab(camel string) string { + var buffer bytes.Buffer + for i, ch := range camel { + if unicode.IsUpper(ch) && i > 0 && !unicode.IsUpper([]rune(camel)[i-1]) { + buffer.WriteRune('-') + } + buffer.WriteRune(unicode.ToLower(ch)) + } + return buffer.String() +}