Move genflags tool to cmd/ and pin to previous release
to alleviate problems caused by the circular dependency of using the same code as a library that is potentially being generated to adhere to a different API.
This commit is contained in:
parent
45a1375078
commit
2ca91434a8
3
.github/workflows/cli.yml
vendored
3
.github/workflows/cli.yml
vendored
@ -46,6 +46,9 @@ jobs:
|
|||||||
- name: test
|
- name: test
|
||||||
run: go run internal/build/build.go test
|
run: go run internal/build/build.go test
|
||||||
|
|
||||||
|
- name: test urfave-cli-genflags
|
||||||
|
run: make -C cmd/urfave-cli-genflags
|
||||||
|
|
||||||
- name: check-binary-size
|
- name: check-binary-size
|
||||||
run: go run internal/build/build.go check-binary-size
|
run: go run internal/build/build.go check-binary-size
|
||||||
|
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -6,5 +6,6 @@ internal/*/built-example
|
|||||||
coverage.txt
|
coverage.txt
|
||||||
/.local/
|
/.local/
|
||||||
/site/
|
/site/
|
||||||
|
/cmd/urfave-cli-genflags/urfave-cli-genflags
|
||||||
|
|
||||||
*.exe
|
*.exe
|
||||||
|
32
cli.go
32
cli.go
@ -1,23 +1,25 @@
|
|||||||
// Package cli provides a minimal framework for creating and organizing command line
|
// Package cli provides a minimal framework for creating and organizing command line
|
||||||
// Go applications. cli is designed to be easy to understand and write, the most simple
|
// Go applications. cli is designed to be easy to understand and write, the most simple
|
||||||
// cli application can be written as follows:
|
// cli application can be written as follows:
|
||||||
// func main() {
|
//
|
||||||
// (&cli.App{}).Run(os.Args)
|
// func main() {
|
||||||
// }
|
// (&cli.App{}).Run(os.Args)
|
||||||
|
// }
|
||||||
//
|
//
|
||||||
// Of course this application does not do much, so let's make this an actual application:
|
// Of course this application does not do much, so let's make this an actual application:
|
||||||
// func main() {
|
|
||||||
// app := &cli.App{
|
|
||||||
// Name: "greet",
|
|
||||||
// Usage: "say a greeting",
|
|
||||||
// Action: func(c *cli.Context) error {
|
|
||||||
// fmt.Println("Greetings")
|
|
||||||
// return nil
|
|
||||||
// },
|
|
||||||
// }
|
|
||||||
//
|
//
|
||||||
// app.Run(os.Args)
|
// func main() {
|
||||||
// }
|
// app := &cli.App{
|
||||||
|
// Name: "greet",
|
||||||
|
// Usage: "say a greeting",
|
||||||
|
// Action: func(c *cli.Context) error {
|
||||||
|
// fmt.Println("Greetings")
|
||||||
|
// return nil
|
||||||
|
// },
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// app.Run(os.Args)
|
||||||
|
// }
|
||||||
package cli
|
package cli
|
||||||
|
|
||||||
//go:generate go run internal/genflags/cmd/genflags/main.go
|
//go:generate go run cmd/urfave-cli-genflags/main.go
|
||||||
|
21
cmd/urfave-cli-genflags/Makefile
Normal file
21
cmd/urfave-cli-genflags/Makefile
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
GOTEST_FLAGS ?= -v --coverprofile main.coverprofile --covermode count --cover github.com/urfave/cli/v2/cmd/urfave-cli-genflags
|
||||||
|
GOBUILD_FLAGS ?= -x
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
all: test build smoke-test
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test:
|
||||||
|
go test $(GOTEST_FLAGS) ./...
|
||||||
|
|
||||||
|
.PHONY: build
|
||||||
|
build:
|
||||||
|
go build $(GOBUILD_FLAGS) ./...
|
||||||
|
|
||||||
|
.PHONY: smoke-test
|
||||||
|
smoke-test: build
|
||||||
|
./urfave-cli-genflags --help
|
||||||
|
|
||||||
|
.PHONY: show-cover
|
||||||
|
show-cover:
|
||||||
|
go tool cover -func main.coverprofile
|
15
cmd/urfave-cli-genflags/README.md
Normal file
15
cmd/urfave-cli-genflags/README.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# urfave-cli-genflags
|
||||||
|
|
||||||
|
This is a tool that is used internally by [urfave/cli] to generate
|
||||||
|
flag types and methods from a YAML input. It intentionally pins
|
||||||
|
usage of `github.com/urfave/cli/v2` to a *release* rather than
|
||||||
|
using the adjacent code so that changes don't result in *this* tool
|
||||||
|
refusing to compile. It's almost like dogfooding?
|
||||||
|
|
||||||
|
## support warning
|
||||||
|
|
||||||
|
This tool is maintained as a sub-project and is not covered by the
|
||||||
|
API and backward compatibility guaranteed by releases of
|
||||||
|
[urfave/cli].
|
||||||
|
|
||||||
|
[urfave/cli]: https://github.com/urfave/cli
|
15
cmd/urfave-cli-genflags/go.mod
Normal file
15
cmd/urfave-cli-genflags/go.mod
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
module github.com/urfave/cli/v2/cmd/urfave-cli-genflags
|
||||||
|
|
||||||
|
go 1.18
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/urfave/cli/v2 v2.11.2
|
||||||
|
golang.org/x/text v0.3.7
|
||||||
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
|
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||||
|
)
|
14
cmd/urfave-cli-genflags/go.sum
Normal file
14
cmd/urfave-cli-genflags/go.sum
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
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/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/urfave/cli/v2 v2.11.2 h1:FVfNg4m3vbjbBpLYxW//WjxUoHvJ9TlppXcqY9Q9ZfA=
|
||||||
|
github.com/urfave/cli/v2 v2.11.2/go.mod h1:f8iq5LtQ/bLxafbdBSLPPNsgaW0l/2fYYEHhAyPlwvo=
|
||||||
|
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=
|
||||||
|
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
@ -9,12 +9,14 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
"github.com/urfave/cli/v2/internal/genflags"
|
"golang.org/x/text/cases"
|
||||||
|
"golang.org/x/text/language"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -22,6 +24,16 @@ const (
|
|||||||
defaultPackageName = "cli"
|
defaultPackageName = "cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
//go:embed generated.gotmpl
|
||||||
|
TemplateString string
|
||||||
|
|
||||||
|
//go:embed generated_test.gotmpl
|
||||||
|
TestTemplateString string
|
||||||
|
|
||||||
|
titler = cases.Title(language.Und, cases.NoLower)
|
||||||
|
)
|
||||||
|
|
||||||
func sh(ctx context.Context, exe string, args ...string) (string, error) {
|
func sh(ctx context.Context, exe string, args ...string) (string, error) {
|
||||||
cmd := exec.CommandContext(ctx, exe, args...)
|
cmd := exec.CommandContext(ctx, exe, args...)
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
@ -92,7 +104,7 @@ func runGenFlags(cCtx *cli.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
spec := &genflags.Spec{}
|
spec := &Spec{}
|
||||||
if err := yaml.Unmarshal(specBytes, spec); err != nil {
|
if err := yaml.Unmarshal(specBytes, spec); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -123,12 +135,12 @@ func runGenFlags(cCtx *cli.Context) error {
|
|||||||
spec.UrfaveCLITestNamespace = "cli."
|
spec.UrfaveCLITestNamespace = "cli."
|
||||||
}
|
}
|
||||||
|
|
||||||
genTmpl, err := template.New("gen").Parse(genflags.TemplateString)
|
genTmpl, err := template.New("gen").Parse(TemplateString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
genTestTmpl, err := template.New("gen_test").Parse(genflags.TestTemplateString)
|
genTestTmpl, err := template.New("gen_test").Parse(TestTemplateString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -161,3 +173,120 @@ func runGenFlags(cCtx *cli.Context) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TypeName(goType string, fc *FlagTypeConfig) string {
|
||||||
|
if fc != nil && strings.TrimSpace(fc.TypeName) != "" {
|
||||||
|
return strings.TrimSpace(fc.TypeName)
|
||||||
|
}
|
||||||
|
|
||||||
|
dotSplit := strings.Split(goType, ".")
|
||||||
|
goType = dotSplit[len(dotSplit)-1]
|
||||||
|
|
||||||
|
if strings.HasPrefix(goType, "[]") {
|
||||||
|
return titler.String(strings.TrimPrefix(goType, "[]")) + "SliceFlag"
|
||||||
|
}
|
||||||
|
|
||||||
|
return titler.String(goType) + "Flag"
|
||||||
|
}
|
||||||
|
|
||||||
|
type Spec struct {
|
||||||
|
FlagTypes map[string]*FlagTypeConfig `yaml:"flag_types"`
|
||||||
|
PackageName string `yaml:"package_name"`
|
||||||
|
TestPackageName string `yaml:"test_package_name"`
|
||||||
|
UrfaveCLINamespace string `yaml:"urfave_cli_namespace"`
|
||||||
|
UrfaveCLITestNamespace string `yaml:"urfave_cli_test_namespace"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gfs *Spec) SortedFlagTypes() []*FlagType {
|
||||||
|
typeNames := []string{}
|
||||||
|
|
||||||
|
for name := range gfs.FlagTypes {
|
||||||
|
if strings.HasPrefix(name, "[]") {
|
||||||
|
name = strings.TrimPrefix(name, "[]") + "Slice"
|
||||||
|
}
|
||||||
|
|
||||||
|
typeNames = append(typeNames, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Strings(typeNames)
|
||||||
|
|
||||||
|
ret := make([]*FlagType, len(typeNames))
|
||||||
|
|
||||||
|
for i, typeName := range typeNames {
|
||||||
|
ret[i] = &FlagType{
|
||||||
|
GoType: typeName,
|
||||||
|
Config: gfs.FlagTypes[typeName],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
type FlagTypeConfig struct {
|
||||||
|
SkipInterfaces []string `yaml:"skip_interfaces"`
|
||||||
|
StructFields []*FlagStructField `yaml:"struct_fields"`
|
||||||
|
TypeName string `yaml:"type_name"`
|
||||||
|
ValuePointer bool `yaml:"value_pointer"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FlagStructField struct {
|
||||||
|
Name string
|
||||||
|
Type string
|
||||||
|
}
|
||||||
|
|
||||||
|
type FlagType struct {
|
||||||
|
GoType string
|
||||||
|
Config *FlagTypeConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ft *FlagType) StructFields() []*FlagStructField {
|
||||||
|
if ft.Config == nil || ft.Config.StructFields == nil {
|
||||||
|
return []*FlagStructField{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ft.Config.StructFields
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ft *FlagType) ValuePointer() bool {
|
||||||
|
if ft.Config == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return ft.Config.ValuePointer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ft *FlagType) TypeName() string {
|
||||||
|
return TypeName(ft.GoType, ft.Config)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ft *FlagType) GenerateFmtStringerInterface() bool {
|
||||||
|
return ft.skipInterfaceNamed("fmt.Stringer")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ft *FlagType) GenerateFlagInterface() bool {
|
||||||
|
return ft.skipInterfaceNamed("Flag")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ft *FlagType) GenerateRequiredFlagInterface() bool {
|
||||||
|
return ft.skipInterfaceNamed("RequiredFlag")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ft *FlagType) GenerateVisibleFlagInterface() bool {
|
||||||
|
return ft.skipInterfaceNamed("VisibleFlag")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ft *FlagType) skipInterfaceNamed(name string) bool {
|
||||||
|
if ft.Config == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
lowName := strings.ToLower(name)
|
||||||
|
|
||||||
|
for _, interfaceName := range ft.Config.SkipInterfaces {
|
||||||
|
if strings.ToLower(interfaceName) == lowName {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
@ -1,29 +1,63 @@
|
|||||||
package genflags_test
|
package main_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/urfave/cli/v2/internal/genflags"
|
main "github.com/urfave/cli/v2/cmd/urfave-cli-genflags"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestTypeName(t *testing.T) {
|
||||||
|
for _, tc := range []struct {
|
||||||
|
gt string
|
||||||
|
fc *main.FlagTypeConfig
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{gt: "int", fc: nil, expected: "IntFlag"},
|
||||||
|
{gt: "int", fc: &main.FlagTypeConfig{}, expected: "IntFlag"},
|
||||||
|
{gt: "int", fc: &main.FlagTypeConfig{TypeName: "VeryIntyFlag"}, expected: "VeryIntyFlag"},
|
||||||
|
{gt: "[]bool", fc: nil, expected: "BoolSliceFlag"},
|
||||||
|
{gt: "[]bool", fc: &main.FlagTypeConfig{}, expected: "BoolSliceFlag"},
|
||||||
|
{gt: "[]bool", fc: &main.FlagTypeConfig{TypeName: "ManyTruthsFlag"}, expected: "ManyTruthsFlag"},
|
||||||
|
{gt: "time.Rumination", fc: nil, expected: "RuminationFlag"},
|
||||||
|
{gt: "time.Rumination", fc: &main.FlagTypeConfig{}, expected: "RuminationFlag"},
|
||||||
|
{gt: "time.Rumination", fc: &main.FlagTypeConfig{TypeName: "PonderFlag"}, expected: "PonderFlag"},
|
||||||
|
} {
|
||||||
|
t.Run(
|
||||||
|
fmt.Sprintf("type=%s,cfg=%v", tc.gt, func() string {
|
||||||
|
if tc.fc != nil {
|
||||||
|
return tc.fc.TypeName
|
||||||
|
}
|
||||||
|
return "nil"
|
||||||
|
}()),
|
||||||
|
func(ct *testing.T) {
|
||||||
|
actual := main.TypeName(tc.gt, tc.fc)
|
||||||
|
if tc.expected != actual {
|
||||||
|
ct.Errorf("expected %q, got %q", tc.expected, actual)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestSpec_SortedFlagTypes(t *testing.T) {
|
func TestSpec_SortedFlagTypes(t *testing.T) {
|
||||||
spec := &genflags.Spec{
|
spec := &main.Spec{
|
||||||
FlagTypes: map[string]*genflags.FlagTypeConfig{
|
FlagTypes: map[string]*main.FlagTypeConfig{
|
||||||
"nerf": &genflags.FlagTypeConfig{},
|
"nerf": &main.FlagTypeConfig{},
|
||||||
"gerf": nil,
|
"gerf": nil,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
actual := spec.SortedFlagTypes()
|
actual := spec.SortedFlagTypes()
|
||||||
expected := []*genflags.FlagType{
|
expected := []*main.FlagType{
|
||||||
{
|
{
|
||||||
GoType: "gerf",
|
GoType: "gerf",
|
||||||
Config: nil,
|
Config: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
GoType: "nerf",
|
GoType: "nerf",
|
||||||
Config: &genflags.FlagTypeConfig{},
|
Config: &main.FlagTypeConfig{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(expected, actual) {
|
if !reflect.DeepEqual(expected, actual) {
|
||||||
@ -31,12 +65,12 @@ func TestSpec_SortedFlagTypes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func genFlagType() *genflags.FlagType {
|
func genFlagType() *main.FlagType {
|
||||||
return &genflags.FlagType{
|
return &main.FlagType{
|
||||||
GoType: "blerf",
|
GoType: "blerf",
|
||||||
Config: &genflags.FlagTypeConfig{
|
Config: &main.FlagTypeConfig{
|
||||||
SkipInterfaces: []string{"fmt.Stringer"},
|
SkipInterfaces: []string{"fmt.Stringer"},
|
||||||
StructFields: []*genflags.FlagStructField{
|
StructFields: []*main.FlagStructField{
|
||||||
{
|
{
|
||||||
Name: "Foibles",
|
Name: "Foibles",
|
||||||
Type: "int",
|
Type: "int",
|
@ -95,7 +95,7 @@ The built-in `go generate` command is used to run the commands specified in
|
|||||||
line help system which may be consulted for further information, e.g.:
|
line help system which may be consulted for further information, e.g.:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
go run internal/genflags/cmd/genflags/main.go --help
|
go run cmd/urfave-cli-genflags/main.go --help
|
||||||
```
|
```
|
||||||
|
|
||||||
#### docs output
|
#### docs output
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# NOTE: this file is used by the tool defined in
|
# NOTE: this file is used by the tool defined in
|
||||||
# ./internal/genflags/cmd/genflags/main.go which uses the
|
# ./cmd/urfave-cli-genflags/main.go which uses the
|
||||||
# `genflags.Spec` type that maps to this file structure.
|
# `Spec` type that maps to this file structure.
|
||||||
|
|
||||||
flag_types:
|
flag_types:
|
||||||
bool:
|
bool:
|
||||||
|
@ -94,7 +94,7 @@ func main() {
|
|||||||
},
|
},
|
||||||
&cli.StringSliceFlag{
|
&cli.StringSliceFlag{
|
||||||
Name: "packages",
|
Name: "packages",
|
||||||
Value: cli.NewStringSlice("cli", "altsrc", "internal/build", "internal/genflags"),
|
Value: cli.NewStringSlice("cli", "altsrc", "internal/build"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
package genflags
|
|
||||||
|
|
||||||
import (
|
|
||||||
_ "embed"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"golang.org/x/text/cases"
|
|
||||||
"golang.org/x/text/language"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
//go:embed generated.gotmpl
|
|
||||||
TemplateString string
|
|
||||||
|
|
||||||
//go:embed generated_test.gotmpl
|
|
||||||
TestTemplateString string
|
|
||||||
|
|
||||||
titler = cases.Title(language.Und, cases.NoLower)
|
|
||||||
)
|
|
||||||
|
|
||||||
func TypeName(goType string, fc *FlagTypeConfig) string {
|
|
||||||
if fc != nil && strings.TrimSpace(fc.TypeName) != "" {
|
|
||||||
return strings.TrimSpace(fc.TypeName)
|
|
||||||
}
|
|
||||||
|
|
||||||
dotSplit := strings.Split(goType, ".")
|
|
||||||
goType = dotSplit[len(dotSplit)-1]
|
|
||||||
|
|
||||||
if strings.HasPrefix(goType, "[]") {
|
|
||||||
return titler.String(strings.TrimPrefix(goType, "[]")) + "SliceFlag"
|
|
||||||
}
|
|
||||||
|
|
||||||
return titler.String(goType) + "Flag"
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
package genflags_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/urfave/cli/v2/internal/genflags"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestTypeName(t *testing.T) {
|
|
||||||
for _, tc := range []struct {
|
|
||||||
gt string
|
|
||||||
fc *genflags.FlagTypeConfig
|
|
||||||
expected string
|
|
||||||
}{
|
|
||||||
{gt: "int", fc: nil, expected: "IntFlag"},
|
|
||||||
{gt: "int", fc: &genflags.FlagTypeConfig{}, expected: "IntFlag"},
|
|
||||||
{gt: "int", fc: &genflags.FlagTypeConfig{TypeName: "VeryIntyFlag"}, expected: "VeryIntyFlag"},
|
|
||||||
{gt: "[]bool", fc: nil, expected: "BoolSliceFlag"},
|
|
||||||
{gt: "[]bool", fc: &genflags.FlagTypeConfig{}, expected: "BoolSliceFlag"},
|
|
||||||
{gt: "[]bool", fc: &genflags.FlagTypeConfig{TypeName: "ManyTruthsFlag"}, expected: "ManyTruthsFlag"},
|
|
||||||
{gt: "time.Rumination", fc: nil, expected: "RuminationFlag"},
|
|
||||||
{gt: "time.Rumination", fc: &genflags.FlagTypeConfig{}, expected: "RuminationFlag"},
|
|
||||||
{gt: "time.Rumination", fc: &genflags.FlagTypeConfig{TypeName: "PonderFlag"}, expected: "PonderFlag"},
|
|
||||||
} {
|
|
||||||
t.Run(
|
|
||||||
fmt.Sprintf("type=%s,cfg=%v", tc.gt, func() string {
|
|
||||||
if tc.fc != nil {
|
|
||||||
return tc.fc.TypeName
|
|
||||||
}
|
|
||||||
return "nil"
|
|
||||||
}()),
|
|
||||||
func(ct *testing.T) {
|
|
||||||
actual := genflags.TypeName(tc.gt, tc.fc)
|
|
||||||
if tc.expected != actual {
|
|
||||||
ct.Errorf("expected %q, got %q", tc.expected, actual)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,105 +0,0 @@
|
|||||||
package genflags
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Spec struct {
|
|
||||||
FlagTypes map[string]*FlagTypeConfig `yaml:"flag_types"`
|
|
||||||
PackageName string `yaml:"package_name"`
|
|
||||||
TestPackageName string `yaml:"test_package_name"`
|
|
||||||
UrfaveCLINamespace string `yaml:"urfave_cli_namespace"`
|
|
||||||
UrfaveCLITestNamespace string `yaml:"urfave_cli_test_namespace"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gfs *Spec) SortedFlagTypes() []*FlagType {
|
|
||||||
typeNames := []string{}
|
|
||||||
|
|
||||||
for name := range gfs.FlagTypes {
|
|
||||||
if strings.HasPrefix(name, "[]") {
|
|
||||||
name = strings.TrimPrefix(name, "[]") + "Slice"
|
|
||||||
}
|
|
||||||
|
|
||||||
typeNames = append(typeNames, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Strings(typeNames)
|
|
||||||
|
|
||||||
ret := make([]*FlagType, len(typeNames))
|
|
||||||
|
|
||||||
for i, typeName := range typeNames {
|
|
||||||
ret[i] = &FlagType{
|
|
||||||
GoType: typeName,
|
|
||||||
Config: gfs.FlagTypes[typeName],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
type FlagTypeConfig struct {
|
|
||||||
SkipInterfaces []string `yaml:"skip_interfaces"`
|
|
||||||
StructFields []*FlagStructField `yaml:"struct_fields"`
|
|
||||||
TypeName string `yaml:"type_name"`
|
|
||||||
ValuePointer bool `yaml:"value_pointer"`
|
|
||||||
NoDefaultText bool `yaml:"no_default_text"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type FlagStructField struct {
|
|
||||||
Name string
|
|
||||||
Type string
|
|
||||||
}
|
|
||||||
|
|
||||||
type FlagType struct {
|
|
||||||
GoType string
|
|
||||||
Config *FlagTypeConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ft *FlagType) StructFields() []*FlagStructField {
|
|
||||||
if ft.Config == nil || ft.Config.StructFields == nil {
|
|
||||||
return []*FlagStructField{}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ft.Config.StructFields
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ft *FlagType) ValuePointer() bool {
|
|
||||||
if ft.Config == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return ft.Config.ValuePointer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ft *FlagType) TypeName() string {
|
|
||||||
return TypeName(ft.GoType, ft.Config)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ft *FlagType) GenerateFmtStringerInterface() bool {
|
|
||||||
return ft.skipInterfaceNamed("fmt.Stringer")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ft *FlagType) GenerateFlagInterface() bool {
|
|
||||||
return ft.skipInterfaceNamed("Flag")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ft *FlagType) GenerateDefaultText() bool {
|
|
||||||
return !ft.Config.NoDefaultText
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ft *FlagType) skipInterfaceNamed(name string) bool {
|
|
||||||
if ft.Config == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
lowName := strings.ToLower(name)
|
|
||||||
|
|
||||||
for _, interfaceName := range ft.Config.SkipInterfaces {
|
|
||||||
if strings.ToLower(interfaceName) == lowName {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user