From ae9066d3ccfeff429c9a67c62577cb806f2a468b Mon Sep 17 00:00:00 2001 From: Robert Kaussow Date: Mon, 1 Jan 2024 17:54:09 +0100 Subject: [PATCH] feat: generate required and type information for docs (#45) --- docs/docs.go | 32 +++++++++++ docs/docs_test.go | 88 ++++++++++++++++++++++++++++-- docs/templates/markdown.md.tmpl | 2 +- docs/testdata/expected-doc-full.md | 8 ++- go.mod | 1 + go.sum | 2 + 6 files changed, 126 insertions(+), 7 deletions(-) diff --git a/docs/docs.go b/docs/docs.go index c775e63..38c6980 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -4,6 +4,8 @@ import ( "bytes" "embed" "html/template" + "reflect" + "regexp" "sort" "strings" @@ -17,6 +19,8 @@ type PluginArg struct { EnvVars []string Description string Default string + Type string + Required bool } type CliTemplate struct { @@ -90,6 +94,12 @@ func parseFlags(flags []cli.Flag) []*PluginArg { modArg.Description = flag.GetUsage() modArg.Default = flag.GetDefaultText() + if rf, _ := f.(cli.RequiredFlag); ok { + modArg.Required = rf.IsRequired() + } + + modArg.Type = parseType(reflect.TypeOf(f).String()) + args = append(args, modArg) } @@ -99,3 +109,25 @@ func parseFlags(flags []cli.Flag) []*PluginArg { return args } + +func parseType(raw string) string { + reSlice := regexp.MustCompile(`^\*cli\.(.+?)SliceFlag$`) + + if reSlice.MatchString(raw) { + return "list" + } + + re := regexp.MustCompile(`^\*cli\.(.+?)Flag$`) + match := re.FindStringSubmatch(raw) + + if len(match) > 1 { + switch ctype := strings.ToLower(match[1]); ctype { + case "int", "int64", "uint", "uint64", "float64": + return "number" + default: + return ctype + } + } + + return "" +} diff --git a/docs/docs_test.go b/docs/docs_test.go index af861ac..0133de4 100644 --- a/docs/docs_test.go +++ b/docs/docs_test.go @@ -5,6 +5,7 @@ import ( "os" "testing" + "github.com/google/go-cmp/cmp" "github.com/urfave/cli/v2" ) @@ -13,11 +14,19 @@ func testApp() *cli.App { Name: "test", Description: "test description", Flags: []cli.Flag{ + &cli.Int64Flag{ + Name: "dummy-flag-int", + Usage: "dummy int flag desc", + EnvVars: []string{"PLUGIN_DUMMY_FLAG_INT"}, + Value: 10, + Required: true, + }, &cli.StringFlag{ - Name: "dummy-flag", - Usage: "dummy flag desc", - EnvVars: []string{"PLUGIN_DUMMY_FLAG"}, - Value: "test", + Name: "dummy-flag", + Usage: "dummy flag desc", + EnvVars: []string{"PLUGIN_DUMMY_FLAG"}, + Value: "test", + Required: true, }, &cli.StringFlag{ Name: "simpe-flag", @@ -28,6 +37,11 @@ func testApp() *cli.App { Usage: "other flag with desc", EnvVars: []string{"PLUGIN_Z_OTHER_FLAG"}, }, + &cli.StringSliceFlag{ + Name: "slice.flag", + Usage: "slice flag", + EnvVars: []string{"PLUGIN_SLICE_FLAG"}, + }, }, } @@ -53,7 +67,11 @@ func TestToMarkdownFull(t *testing.T) { app *cli.App want string }{ - {"normal branch", testApp(), "testdata/expected-doc-full.md"}, + { + "normal branch", + testApp(), + "testdata/expected-doc-full.md", + }, } for _, tt := range tests { @@ -65,3 +83,63 @@ func TestToMarkdownFull(t *testing.T) { }) } } + +func TestToData(t *testing.T) { + tests := []struct { + name string + app *cli.App + want *CliTemplate + }{ + { + "normal branch", + testApp(), + &CliTemplate{ + Name: "test", + Description: "test description", + GlobalArgs: []*PluginArg{ + { + Name: "dummy_flag", + Description: "dummy flag desc", + Default: "\"test\"", + Type: "string", + Required: true, + }, + { + Name: "dummy_flag_int", + Description: "dummy int flag desc", + Default: "10", + Type: "number", + Required: true, + }, + { + Name: "slice_flag", + Description: "slice flag", + Default: "", + Type: "list", + Required: false, + }, + { + Name: "x_simple_flag", + Type: "string", + Required: false, + }, + { + Name: "z_other_flag", + Description: "other flag with desc", + Type: "string", + Required: false, + }, + }, + }, + }, + } + + for _, tt := range tests { + got := GetTemplateData(tt.app) + t.Run(tt.name, func(t *testing.T) { + if diff := cmp.Diff(tt.want, got); diff != "" { + t.Errorf("data mismatch (-want +got):\n%s", diff) + } + }) + } +} diff --git a/docs/templates/markdown.md.tmpl b/docs/templates/markdown.md.tmpl index 2356ed4..2ceb661 100644 --- a/docs/templates/markdown.md.tmpl +++ b/docs/templates/markdown.md.tmpl @@ -7,7 +7,7 @@ ## Parameters {{ range $v := .GlobalArgs }} -**_{{ $v.Name }}_**{{ with $v.Default }} (defaut: {{ . }}){{ end }}{{ if $v.Description }}{{ "\\" }}{{ end }} +**_{{ $v.Name }}_**{{ with $v.Default }}{{ if $v.Required }} _required_{{ end }} (defaut: {{ . }}){{ end }}{{ if $v.Description }}{{ "\\" }}{{ end }} {{- with $v.Description }}  {{ . }} {{- end }} diff --git a/docs/testdata/expected-doc-full.md b/docs/testdata/expected-doc-full.md index 4daab5b..60c14ac 100644 --- a/docs/testdata/expected-doc-full.md +++ b/docs/testdata/expected-doc-full.md @@ -4,9 +4,15 @@ test description ## Parameters -**_dummy_flag_** (defaut: "test")\ +**_dummy_flag_** _required_ (defaut: "test")\  dummy flag desc +**_dummy_flag_int_** _required_ (defaut: 10)\ + dummy int flag desc + +**_slice_flag_**\ + slice flag + **_x_simple_flag_** **_z_other_flag_**\ diff --git a/go.mod b/go.mod index e462a13..bcec21f 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.21 require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/Masterminds/sprig/v3 v3.2.3 + github.com/google/go-cmp v0.6.0 github.com/joho/godotenv v1.5.1 github.com/rs/zerolog v1.31.0 github.com/urfave/cli/v2 v2.27.1 diff --git a/go.sum b/go.sum index 25ffa6d..b51f482 100644 --- a/go.sum +++ b/go.sum @@ -12,6 +12,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs 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/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4=