Skip to content

Commit

Permalink
added scrape from carapace-bin
Browse files Browse the repository at this point in the history
  • Loading branch information
rsteube committed Oct 26, 2022
1 parent 60c8d41 commit a5c1b8a
Show file tree
Hide file tree
Showing 3 changed files with 194 additions and 3 deletions.
19 changes: 16 additions & 3 deletions cmd/carapace-spec/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ var rootCmd = &cobra.Command{
xonsh: exec($(carapace-spec example.yaml))
zsh: source <(carapace-spec example.yaml)
`,
Args: cobra.MinimumNArgs(1),
DisableFlagParsing: true,
Args: cobra.MinimumNArgs(1),
//DisableFlagParsing: true,
CompletionOptions: cobra.CompletionOptions{
DisableDefaultCmd: true,
},
Expand All @@ -53,7 +53,12 @@ var rootCmd = &cobra.Command{
if err := yaml.Unmarshal(content, &specCmd); err != nil {
return err
}
bridgeCompletion(specCmd.ToCobra(), abs, args[1:]...)

if cmd.Flag("scrape").Changed {
specCmd.Scrape()
} else {
bridgeCompletion(specCmd.ToCobra(), abs, args[1:]...)
}
return nil
},
}
Expand All @@ -62,6 +67,8 @@ func Execute() error {
return rootCmd.Execute()
}
func init() {
rootCmd.Flags().Bool("scrape", false, "scrape to go code")

carapace.Gen(rootCmd).PositionalCompletion(
carapace.ActionFiles(".yaml"),
)
Expand Down Expand Up @@ -91,6 +98,12 @@ func init() {
return carapace.ActionExecute(specCmd.ToCobra()).Invoke(c).ToA()
}),
)

carapace.Gen(rootCmd).PreRun(func(cmd *cobra.Command, args []string) {
if len(args) > 1 && args[0] != "--scrape" {
cmd.DisableFlagParsing = true
}
})
}

func bridgeCompletion(cmd *cobra.Command, spec string, args ...string) {
Expand Down
4 changes: 4 additions & 0 deletions command.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,7 @@ func (c *Command) ToCobra() *cobra.Command {

return cmd
}

func (c *Command) Scrape() {
Scrape(c.ToCobra())
}
174 changes: 174 additions & 0 deletions scrape.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
package spec

import (
"bytes"
"encoding/csv"
"fmt"
"os"
"strings"

"github.com/spf13/cobra"
"github.com/spf13/pflag"
)

var tmpDir string = getTmpDir()

func getTmpDir() string {
dir, err := os.MkdirTemp(os.TempDir(), "carascrape")
if err != nil {
panic(err.Error())
}
return dir
}

func Scrape(cmd *cobra.Command) {
out := &bytes.Buffer{}

if len(cmd.Aliases) > 0 {
fmt.Fprintf(out, `package cmd
import (
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
)
var %vCmd = &cobra.Command{
Use: "%v",
Short: "%v",
Aliases: []string{"%v"},
Run: func(cmd *cobra.Command, args []string) {},
}
`, cmdVarName(cmd), cmd.Name(), cmd.Short, strings.Join(cmd.Aliases, `", "`))
} else {

fmt.Fprintf(out, `package cmd
import (
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
)
var %vCmd = &cobra.Command{
Use: "%v",
Short: "%v",
Run: func(cmd *cobra.Command, args []string) {},
}
`, cmdVarName(cmd), cmd.Name(), cmd.Short)
}
if !cmd.HasParent() {
fmt.Fprintf(out, `func Execute() error {
return rootCmd.Execute()
}
`)
}

fmt.Fprintf(out, `func init() {
carapace.Gen(%vCmd).Standalone()
`, cmdVarName(cmd))

cmd.LocalFlags().VisitAll(func(f *pflag.Flag) {
if f.Deprecated != "" {
return
}

isShortHand := f.Shorthand != ""

persistentPrefix := ""
if cmd.PersistentFlags().Lookup(f.Name) != nil {
persistentPrefix = "Persistent"
}

if isShortHand {
fmt.Fprintf(out, ` %vCmd.%vFlags().%vP("%v", "%v", %v, "%v")`+"\n", cmdVarName(cmd), persistentPrefix, flagType(f), f.Name, f.Shorthand, flagValue(f), formatUsage(f.Usage))
} else {
fmt.Fprintf(out, ` %vCmd.%vFlags().%v("%v", %v, "%v")`+"\n", cmdVarName(cmd), persistentPrefix, flagType(f), f.Name, flagValue(f), formatUsage(f.Usage))
}
})

cmd.LocalFlags().VisitAll(func(f *pflag.Flag) {
if f.Deprecated != "" {
return
}

if f.Value.Type() != "bool" && f.NoOptDefVal != "" {
fmt.Fprintf(out, ` %vCmd.Flag("%v").NoOptDefVal = "%v"`+"\n", cmdVarName(cmd), f.Name, f.NoOptDefVal)
}
})

if cmd.HasParent() {
fmt.Fprintf(out, ` %vCmd.AddCommand(%vCmd)`+"\n", cmdVarName(cmd.Parent()), cmdVarName(cmd))
}

fmt.Fprintln(out, "}")

filename := fmt.Sprintf(`%v/%v.go`, tmpDir, cmdVarName(cmd))
println(filename)
os.WriteFile(filename, out.Bytes(), 0644)

for _, subcmd := range cmd.Commands() {
if !subcmd.Hidden && subcmd.Deprecated == "" {
Scrape(subcmd)
}
}
}

func formatUsage(usage string) string {
return strings.Replace(strings.Split(usage, "\n")[0], `"`, `\"`, -1)
}

func cmdVarName(cmd *cobra.Command) string {
if !cmd.HasParent() {
return "root"
}
return strings.TrimPrefix(fmt.Sprintf(`%v_%v`, cmdVarName(cmd.Parent()), normaliceVarName(cmd.Name())), "root_")
}

func normaliceVarName(s string) string {
normalized := make([]string, 0)
capitalize := false

for _, c := range s {
if c == '-' {
capitalize = true
continue
} else if capitalize {
normalized = append(normalized, strings.ToUpper(string(c)))
capitalize = false
} else {
normalized = append(normalized, string(c))
}
}
return strings.Join(normalized, "")
}

func flagType(f *pflag.Flag) string {
return strings.ToUpper(f.Value.Type()[:1]) + f.Value.Type()[1:]
}

func flagValue(f *pflag.Flag) string {
if strings.HasSuffix(f.Value.Type(), "Slice") ||
strings.HasSuffix(f.Value.Type(), "Array") {
if strings.HasPrefix(f.Value.Type(), "string") {
if len(f.Value.String()) == 0 {
return ""
}

vals, _ := csv.NewReader(strings.NewReader(f.Value.String()[1 : len(f.Value.String())-1])).Read()
formatted := strings.Join(vals, `", "`)
if len(formatted) > 0 {
formatted = fmt.Sprintf(`"%v"`, formatted)
}
return fmt.Sprintf(`[]string{%v}`, formatted)
}
return fmt.Sprintf(`[]%v{%v}`, strings.TrimSuffix(strings.TrimSuffix(f.Value.Type(), "Slice"), "Array"), f.Value.String()[1:len(f.Value.String())-1])
}

if f.Value.Type() == "string" {
return fmt.Sprintf(`"%v"`, f.Value.String())
}

return f.Value.String()
}

0 comments on commit a5c1b8a

Please sign in to comment.