diff --git a/.github/workflows/cli.yml b/.github/workflows/cli.yml index a28a3d8cba..5caeafe5ac 100644 --- a/.github/workflows/cli.yml +++ b/.github/workflows/cli.yml @@ -1,5 +1,4 @@ name: Run Tests - on: push: branches: @@ -9,10 +8,8 @@ on: pull_request: branches: - main - permissions: contents: read - jobs: test: strategy: @@ -22,84 +19,53 @@ jobs: name: ${{ matrix.os }} @ Go ${{ matrix.go }} runs-on: ${{ matrix.os }} steps: - - name: Set up Go ${{ matrix.go }} - uses: actions/setup-go@v3 + - uses: actions/setup-go@v3 with: go-version: ${{ matrix.go }} - - name: Set PATH run: echo "${GITHUB_WORKSPACE}/.local/bin" >>"${GITHUB_PATH}" - - - name: install goimports - if: matrix.go == '1.19.x' && matrix.os == 'ubuntu-latest' - run: GOBIN=${PWD}/.local/bin go install golang.org/x/tools/cmd/goimports@latest - - - name: Checkout Code - uses: actions/checkout@v3 - - - name: goimports check - if: matrix.go == '1.19.x' && matrix.os == 'ubuntu-latest' - run: test -z $(goimports -l .) - - - name: vet - run: go run internal/build/build.go vet - - - name: test with urfave_cli_no_docs tag - run: go run internal/build/build.go -tags urfave_cli_no_docs test - - - name: 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 - run: go run internal/build/build.go check-binary-size - - - name: check-binary-size with tags (informational only) - run: go run internal/build/build.go -tags urfave_cli_no_docs check-binary-size - - - name: Upload coverage to Codecov - if: success() && matrix.go == '1.19.x' && matrix.os == 'ubuntu-latest' + - uses: actions/checkout@v3 + - if: matrix.go == '1.19.x' && matrix.os == 'ubuntu-latest' + run: make ensure-goimports + - if: matrix.go == '1.19.x' && matrix.os == 'ubuntu-latest' + run: make lint + - run: make vet + - run: make test + env: + GFLAGS: -tags urfave_cli_no_docs + - run: make test + - run: make -C cmd/urfave-cli-genflags + - run: make check-binary-size + env: + GFLAGS: -tags urfave_cli_no_docs + - run: make check-binary-size + - run: make yamlfmt + - run: make diffcheck + - if: matrix.go == '1.19.x' && matrix.os == 'ubuntu-latest' + run: make v2diff + - if: success() && matrix.go == '1.19.x' && matrix.os == 'ubuntu-latest' uses: codecov/codecov-action@v3 with: token: ${{ secrets.CODECOV_TOKEN }} fail_ci_if_error: true - test-docs: name: test-docs runs-on: ubuntu-latest steps: - - name: Set up Go - uses: actions/setup-go@v3 + - uses: actions/setup-go@v3 with: go-version: 1.19.x - - - name: Use Node.js 16 - uses: actions/setup-node@v3 + - uses: actions/setup-node@v3 with: node-version: '16' - - name: Set PATH run: echo "${GITHUB_WORKSPACE}/.local/bin" >>"${GITHUB_PATH}" - - - name: Checkout Code - uses: actions/checkout@v3 - - - name: Install Dependencies - run: | - mkdir -p "${GITHUB_WORKSPACE}/.local/bin" - curl -fsSL -o "${GITHUB_WORKSPACE}/.local/bin/gfmrun" "https://github.com/urfave/gfmrun/releases/download/v1.3.0/gfmrun-$(go env GOOS)-$(go env GOARCH)-v1.3.0" - chmod +x "${GITHUB_WORKSPACE}/.local/bin/gfmrun" - - - name: gfmrun - run: go run internal/build/build.go gfmrun --walk docs/v2/ - - - name: diff check - run: | - git diff --exit-code - git diff --cached --exit-code - + - uses: actions/checkout@v3 + - run: make ensure-gfmrun + - run: make gfmrun + env: + FLAGS: --walk docs/v2/ + - run: make diffcheck publish: permissions: contents: write @@ -108,18 +74,13 @@ jobs: needs: [test-docs] runs-on: ubuntu-latest steps: - - name: Checkout Code - uses: actions/checkout@v3 + - uses: actions/checkout@v3 with: fetch-depth: 0 - - - name: Setup mkdocs - run: | - pip install -U pip - pip install -r mkdocs-requirements.txt - git remote rm origin - git remote add origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/urfave/cli.git - - - name: Publish Docs - run: | - mkdocs gh-deploy --force + - run: make ensure-mkdocs + env: + FLAGS: --upgrade-pip + - run: make set-mkdocs-remote + env: + MKDOCS_REMOTE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - run: make deploy-mkdocs diff --git a/Makefile b/Makefile index 3b0e5e0bbd..797d093e9f 100644 --- a/Makefile +++ b/Makefile @@ -4,8 +4,10 @@ # are very important so that maintainers and contributors can focus their # attention on files that are primarily Go. +GO_RUN_BUILD := go run internal/build/build.go + .PHONY: all -all: generate vet tag-test test check-binary-size tag-check-binary-size gfmrun v2diff +all: generate vet tag-test test check-binary-size tag-check-binary-size gfmrun yamlfmt v2diff # NOTE: this is a special catch-all rule to run any of the commands # defined in internal/build/build.go with optional arguments passed @@ -13,28 +15,12 @@ all: generate vet tag-test test check-binary-size tag-check-binary-size gfmrun v # # $ make test GFLAGS='--packages cli' %: - go run internal/build/build.go $(GFLAGS) $* $(FLAGS) - -.PHONY: tag-test -tag-test: - go run internal/build/build.go -tags urfave_cli_no_docs test - -.PHONY: tag-check-binary-size -tag-check-binary-size: - go run internal/build/build.go -tags urfave_cli_no_docs check-binary-size - -.PHONY: gfmrun -gfmrun: - go run internal/build/build.go gfmrun docs/v2/manual.md + $(GO_RUN_BUILD) $(GFLAGS) $* $(FLAGS) .PHONY: docs docs: mkdocs build -.PHONY: docs-deps -docs-deps: - pip install -r mkdocs-requirements.txt - .PHONY: serve-docs serve-docs: mkdocs serve diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 4462899fdd..d657477f5f 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -107,7 +107,7 @@ following `make` targets may be used if desired: ```sh # install documentation dependencies with `pip` -make docs-deps +make ensure-mkdocs ``` ```sh diff --git a/flag-spec.yaml b/flag-spec.yaml index 72e3c15d6a..5c480bb09f 100644 --- a/flag-spec.yaml +++ b/flag-spec.yaml @@ -1,14 +1,13 @@ # NOTE: this file is used by the tool defined in # ./cmd/urfave-cli-genflags/main.go which uses the # `Spec` type that maps to this file structure. - flag_types: - bool: + bool: struct_fields: - - name: Count + - name: Count type: int pointer: true - float64: + float64: Float64Slice: value_pointer: true skip_interfaces: @@ -33,7 +32,7 @@ flag_types: struct_fields: - name: Base type: int - UintSlice: + UintSlice: value_pointer: true skip_interfaces: - fmt.Stringer @@ -41,10 +40,10 @@ flag_types: struct_fields: - name: Base type: int - Uint64Slice: + Uint64Slice: value_pointer: true skip_interfaces: - - fmt.Stringer + - fmt.Stringer string: struct_fields: - name: TakesFile @@ -56,12 +55,12 @@ flag_types: struct_fields: - name: TakesFile type: bool - time.Duration: + time.Duration: Timestamp: value_pointer: true struct_fields: - - name: Layout - type: string + - name: Layout + type: string - name: Timezone type: "*time.Location" Generic: diff --git a/internal/build/build.go b/internal/build/build.go index 930e30bb55..58ef4df2a4 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -5,12 +5,17 @@ package main import ( "bufio" "bytes" + "errors" "fmt" + "io" "log" "math" + "net/http" + "net/url" "os" "os/exec" "path/filepath" + "runtime" "strings" "github.com/urfave/cli/v2" @@ -21,6 +26,8 @@ const ( goodNewsEmoji = "✨" checksPassedEmoji = "✅" + gfmrunVersion = "v1.3.0" + v2diffWarning = ` # The unified diff above indicates that the public API surface area # has changed. If you feel that the changes are acceptable and adhere @@ -45,63 +52,108 @@ func main() { log.Fatal(err) } - app := cli.NewApp() - - app.Name = "builder" - app.Usage = "Generates a new urfave/cli build!" - - app.Commands = cli.Commands{ - { - Name: "vet", - Action: VetActionFunc, - }, - { - Name: "test", - Action: TestActionFunc, - }, - { - Name: "gfmrun", - Flags: []cli.Flag{ - &cli.BoolFlag{ - Name: "walk", - Value: false, - Usage: "Walk the specified directory and perform validation on all markdown files", + app := &cli.App{ + Name: "builder", + Usage: "Do a thing for urfave/cli! (maybe build?)", + Commands: cli.Commands{ + { + Name: "vet", + Action: topRunAction("go", "vet", "./..."), + }, + { + Name: "test", + Action: TestActionFunc, + }, + { + Name: "gfmrun", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "walk", + Value: false, + Usage: "Walk the specified directory and perform validation on all markdown files", + }, }, + Action: GfmrunActionFunc, }, - Action: GfmrunActionFunc, - }, - { - Name: "check-binary-size", - Action: checkBinarySizeActionFunc, - }, - { - Name: "generate", - Action: GenerateActionFunc, - }, - { - Name: "v2diff", - Flags: []cli.Flag{ - &cli.BoolFlag{Name: "color", Value: false}, + { + Name: "check-binary-size", + Action: checkBinarySizeActionFunc, + }, + { + Name: "generate", + Action: GenerateActionFunc, + }, + { + Name: "yamlfmt", + Flags: []cli.Flag{ + &cli.BoolFlag{Name: "strict", Value: false, Usage: "require presence of yq"}, + }, + Action: YAMLFmtActionFunc, + }, + { + Name: "diffcheck", + Action: DiffCheckActionFunc, + }, + { + Name: "ensure-goimports", + Action: EnsureGoimportsActionFunc, + }, + { + Name: "ensure-gfmrun", + Action: EnsureGfmrunActionFunc, + }, + { + Name: "ensure-mkdocs", + Action: EnsureMkdocsActionFunc, + Flags: []cli.Flag{ + &cli.BoolFlag{Name: "upgrade-pip"}, + }, + }, + { + Name: "set-mkdocs-remote", + Action: SetMkdocsRemoteActionFunc, + Flags: []cli.Flag{ + &cli.StringFlag{Name: "github-token", Required: true}, + }, + }, + { + Name: "deploy-mkdocs", + Action: topRunAction("mkdocs", "gh-deploy", "--force"), + }, + { + Name: "lint", + Action: LintActionFunc, + }, + { + Name: "v2diff", + Flags: []cli.Flag{ + &cli.BoolFlag{Name: "color", Value: false}, + }, + Action: V2Diff, + }, + { + Name: "v2approve", + Action: topRunAction( + "cp", + "-v", + "godoc-current.txt", + filepath.Join("testdata", "godoc-v2.x.txt"), + ), }, - Action: V2Diff, - }, - { - Name: "v2approve", - Action: V2Approve, - }, - } - app.Flags = []cli.Flag{ - &cli.StringFlag{ - Name: "tags", - Usage: "set build tags", - }, - &cli.PathFlag{ - Name: "top", - Value: top, }, - &cli.StringSliceFlag{ - Name: "packages", - Value: cli.NewStringSlice("cli", "altsrc", "internal/build"), + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "tags", + Usage: "set build tags", + }, + &cli.PathFlag{ + Name: "top", + Value: top, + }, + &cli.StringSliceFlag{ + Name: "packages", + Value: cli.NewStringSlice("cli", "altsrc", "internal/build"), + }, }, } @@ -120,6 +172,14 @@ func sh(exe string, args ...string) (string, error) { return string(outBytes), err } +func topRunAction(arg string, args ...string) cli.ActionFunc { + return func(cCtx *cli.Context) error { + os.Chdir(cCtx.Path("top")) + + return runCmd(arg, args...) + } +} + func runCmd(arg string, args ...string) error { cmd := exec.Command(arg, args...) @@ -131,6 +191,43 @@ func runCmd(arg string, args ...string) error { return cmd.Run() } +func downloadFile(src, dest string, dirPerm, perm os.FileMode) error { + req, err := http.NewRequest(http.MethodGet, src, nil) + if err != nil { + return err + } + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + + defer resp.Body.Close() + + if resp.StatusCode >= 300 { + return fmt.Errorf("download response %[1]v", resp.StatusCode) + } + + if err := os.MkdirAll(filepath.Dir(dest), dirPerm); err != nil { + return err + } + + out, err := os.Create(dest) + if err != nil { + return err + } + + if _, err := io.Copy(out, resp.Body); err != nil { + return err + } + + if err := out.Close(); err != nil { + return err + } + + return os.Chmod(dest, perm) +} + func VetActionFunc(cCtx *cli.Context) error { return runCmd("go", "vet", cCtx.Path("top")+"/...") } @@ -145,15 +242,20 @@ func TestActionFunc(c *cli.Context) error { packageName = fmt.Sprintf("github.com/urfave/cli/v2/%s", pkg) } - if err := runCmd( - "go", "test", - "-tags", tags, + args := []string{"test"} + if tags != "" { + args = append(args, []string{"-tags", tags}...) + } + + args = append(args, []string{ "-v", - "--coverprofile", pkg+".coverprofile", + "--coverprofile", pkg + ".coverprofile", "--covermode", "count", "--cover", packageName, packageName, - ); err != nil { + }...) + + if err := runCmd("go", args...); err != nil { return err } } @@ -411,6 +513,125 @@ func GenerateActionFunc(cCtx *cli.Context) error { return runCmd("go", "generate", cCtx.Path("top")+"/...") } +func YAMLFmtActionFunc(cCtx *cli.Context) error { + yqBin, err := exec.LookPath("yq") + if err != nil { + if !cCtx.Bool("strict") { + fmt.Fprintln(cCtx.App.ErrWriter, "# ---> no yq found; skipping") + return nil + } + + return err + } + + os.Chdir(cCtx.Path("top")) + + return runCmd(yqBin, "eval", "--inplace", "flag-spec.yaml") +} + +func DiffCheckActionFunc(cCtx *cli.Context) error { + os.Chdir(cCtx.Path("top")) + + if err := runCmd("git", "diff", "--exit-code"); err != nil { + return err + } + + return runCmd("git", "diff", "--cached", "--exit-code") +} + +func EnsureGoimportsActionFunc(cCtx *cli.Context) error { + top := cCtx.Path("top") + os.Chdir(top) + + if err := runCmd( + "goimports", + "-d", + filepath.Join(top, "internal/build/build.go"), + ); err == nil { + return nil + } + + os.Setenv("GOBIN", filepath.Join(top, ".local/bin")) + + return runCmd("go", "install", "golang.org/x/tools/cmd/goimports@latest") +} + +func EnsureGfmrunActionFunc(cCtx *cli.Context) error { + top := cCtx.Path("top") + gfmrunExe := filepath.Join(top, ".local/bin/gfmrun") + + os.Chdir(top) + + if v, err := sh(gfmrunExe, "--version"); err == nil && strings.TrimSpace(v) == gfmrunVersion { + return nil + } + + gfmrunURL, err := url.Parse( + fmt.Sprintf( + "https://github.com/urfave/gfmrun/releases/download/%[1]s/gfmrun-%[2]s-%[3]s-%[1]s", + gfmrunVersion, runtime.GOOS, runtime.GOARCH, + ), + ) + if err != nil { + return err + } + + return downloadFile(gfmrunURL.String(), gfmrunExe, 0755, 0755) +} + +func EnsureMkdocsActionFunc(cCtx *cli.Context) error { + os.Chdir(cCtx.Path("top")) + + if err := runCmd("mkdocs", "--version"); err == nil { + return nil + } + + if cCtx.Bool("upgrade-pip") { + if err := runCmd("pip", "install", "-U", "pip"); err != nil { + return err + } + } + + return runCmd("pip", "install", "-r", "mkdocs-requirements.txt") +} + +func SetMkdocsRemoteActionFunc(cCtx *cli.Context) error { + ghToken := strings.TrimSpace(cCtx.String("github-token")) + if ghToken == "" { + return errors.New("empty github token") + } + + os.Chdir(cCtx.Path("top")) + + if err := runCmd("git", "remote", "rm", "origin"); err != nil { + return err + } + + return runCmd( + "git", "remote", "add", "origin", + fmt.Sprintf("https://x-access-token:%[1]s@github.com/urfave/cli.git", ghToken), + ) +} + +func LintActionFunc(cCtx *cli.Context) error { + top := cCtx.Path("top") + os.Chdir(top) + + out, err := sh(filepath.Join(top, ".local/bin/goimports"), "-l", ".") + if err != nil { + return err + } + + if strings.TrimSpace(out) != "" { + fmt.Fprintln(cCtx.App.ErrWriter, "# ---> goimports -l is non-empty:") + fmt.Fprintln(cCtx.App.ErrWriter, out) + + return errors.New("goimports needed") + } + + return nil +} + func V2Diff(cCtx *cli.Context) error { os.Chdir(cCtx.Path("top")) @@ -439,34 +660,29 @@ func V2Diff(cCtx *cli.Context) error { return err } -func V2Approve(cCtx *cli.Context) error { - top := cCtx.Path("top") +func getSize(sourcePath, builtPath, tags string) (int64, error) { + args := []string{"build"} - return runCmd( - "cp", - "-v", - filepath.Join(top, "godoc-current.txt"), - filepath.Join(top, "testdata", "godoc-v2.x.txt"), - ) -} + if tags != "" { + args = append(args, []string{"-tags", tags}...) + } -func getSize(sourcePath string, builtPath string, tags string) (size int64, err error) { - // build example binary - err = runCmd("go", "build", "-tags", tags, "-o", builtPath, "-ldflags", "-s -w", sourcePath) - if err != nil { + args = append(args, []string{ + "-o", builtPath, + "-ldflags", "-s -w", + sourcePath, + }...) + + if err := runCmd("go", args...); err != nil { fmt.Println("issue getting size for example binary") return 0, err } - // get file info fileInfo, err := os.Stat(builtPath) if err != nil { fmt.Println("issue getting size for example binary") return 0, err } - // size! - size = fileInfo.Size() - - return size, nil + return fileInfo.Size(), nil } diff --git a/testdata/godoc-v2.x.txt b/testdata/godoc-v2.x.txt index 6d0a908753..fbeeb5fb8b 100644 --- a/testdata/godoc-v2.x.txt +++ b/testdata/godoc-v2.x.txt @@ -5,24 +5,24 @@ line Go applications. cli is designed to be easy to understand and write, the most simple cli application can be written as follows: func main() { - (&cli.App{}).Run(os.Args) + (&cli.App{}).Run(os.Args) } 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) + } VARIABLES @@ -49,8 +49,8 @@ AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}: COMMANDS:{{range .VisibleCategories}}{{if .Name}} {{.Name}}:{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlagCategories}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}} + {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlagCategories}} GLOBAL OPTIONS:{{range .VisibleFlagCategories}} {{if .Name}}{{.Name}} @@ -157,8 +157,8 @@ DESCRIPTION: COMMANDS:{{range .VisibleCategories}}{{if .Name}} {{.Name}}:{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{if .VisibleFlags}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}} + {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{if .VisibleFlags}} OPTIONS: {{range .VisibleFlags}}{{.}} @@ -300,6 +300,8 @@ type App struct { CommandNotFound CommandNotFoundFunc // Execute this function if a usage error occurs OnUsageError OnUsageErrorFunc + // Execute this function when an invalid flag is accessed from the context + InvalidFlagAccessHandler InvalidFlagAccessFunc // Compilation date Compiled time.Time // List of all authors who contributed @@ -450,6 +452,8 @@ type BoolFlag struct { Aliases []string EnvVars []string + + Count *int } BoolFlag is a flag with type bool @@ -629,6 +633,9 @@ func (cCtx *Context) Args() Args func (cCtx *Context) Bool(name string) bool Bool looks up the value of a local BoolFlag, returns false if not found +func (cCtx *Context) Count(name string) int + Count returns the num of occurences of this flag + func (cCtx *Context) Duration(name string) time.Duration Duration looks up the value of a local DurationFlag, returns 0 if not found @@ -698,9 +705,23 @@ func (cCtx *Context) Uint(name string) uint func (cCtx *Context) Uint64(name string) uint64 Uint64 looks up the value of a local Uint64Flag, returns 0 if not found +func (cCtx *Context) Uint64Slice(name string) []uint64 + Uint64Slice looks up the value of a local Uint64SliceFlag, returns nil if + not found + +func (cCtx *Context) UintSlice(name string) []uint + UintSlice looks up the value of a local UintSliceFlag, returns nil if not + found + func (cCtx *Context) Value(name string) interface{} Value returns the value of the flag corresponding to `name` +type Countable interface { + Count() int +} + Countable is an interface to enable detection of flag values which support + repetitive flags + type DocGenerationFlag interface { Flag @@ -1064,7 +1085,7 @@ type GenericFlag struct { HasBeenSet bool Value Generic - Destination *Generic + Destination Generic Aliases []string EnvVars []string @@ -1073,7 +1094,7 @@ type GenericFlag struct { } GenericFlag is a flag with type Generic -func (f GenericFlag) Apply(set *flag.FlagSet) error +func (f *GenericFlag) Apply(set *flag.FlagSet) error Apply takes the flagset and calls Set on the generic flag with the value provided by the user for parsing by the flag @@ -1131,6 +1152,8 @@ type Int64Flag struct { Aliases []string EnvVars []string + + Base int } Int64Flag is a flag with type int64 @@ -1280,6 +1303,8 @@ type IntFlag struct { Aliases []string EnvVars []string + + Base int } IntFlag is a flag with type int @@ -1416,6 +1441,10 @@ func (f *IntSliceFlag) String() string func (f *IntSliceFlag) TakesValue() bool TakesValue returns true of the flag takes a value, otherwise false +type InvalidFlagAccessFunc func(*Context, string) + InvalidFlagAccessFunc is executed when an invalid flag is accessed from the + context. + type MultiError interface { error Errors() []error @@ -1850,6 +1879,8 @@ type Uint64Flag struct { Aliases []string EnvVars []string + + Base int } Uint64Flag is a flag with type uint64 @@ -1893,6 +1924,89 @@ func (f *Uint64Flag) String() string func (f *Uint64Flag) TakesValue() bool TakesValue returns true of the flag takes a value, otherwise false +type Uint64Slice struct { + // Has unexported fields. +} + Uint64Slice wraps []int64 to satisfy flag.Value + +func NewUint64Slice(defaults ...uint64) *Uint64Slice + NewUint64Slice makes an *Uint64Slice with default values + +func (i *Uint64Slice) Get() interface{} + Get returns the slice of ints set by this flag + +func (i *Uint64Slice) Serialize() string + Serialize allows Uint64Slice to fulfill Serializer + +func (i *Uint64Slice) Set(value string) error + Set parses the value into an integer and appends it to the list of values + +func (i *Uint64Slice) String() string + String returns a readable representation of this value (for usage defaults) + +func (i *Uint64Slice) Value() []uint64 + Value returns the slice of ints set by this flag + +type Uint64SliceFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value *Uint64Slice + Destination *Uint64Slice + + Aliases []string + EnvVars []string +} + Uint64SliceFlag is a flag with type *Uint64Slice + +func (f *Uint64SliceFlag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *Uint64SliceFlag) Get(ctx *Context) []uint64 + Get returns the flag’s value in the given Context. + +func (f *Uint64SliceFlag) GetCategory() string + GetCategory returns the category for the flag + +func (f *Uint64SliceFlag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *Uint64SliceFlag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *Uint64SliceFlag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *Uint64SliceFlag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *Uint64SliceFlag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *Uint64SliceFlag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *Uint64SliceFlag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *Uint64SliceFlag) Names() []string + Names returns the names of the flag + +func (f *Uint64SliceFlag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *Uint64SliceFlag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + type UintFlag struct { Name string @@ -1910,6 +2024,8 @@ type UintFlag struct { Aliases []string EnvVars []string + + Base int } UintFlag is a flag with type uint @@ -1953,6 +2069,93 @@ func (f *UintFlag) String() string func (f *UintFlag) TakesValue() bool TakesValue returns true of the flag takes a value, otherwise false +type UintSlice struct { + // Has unexported fields. +} + UintSlice wraps []int to satisfy flag.Value + +func NewUintSlice(defaults ...uint) *UintSlice + NewUintSlice makes an *UintSlice with default values + +func (i *UintSlice) Get() interface{} + Get returns the slice of ints set by this flag + +func (i *UintSlice) Serialize() string + Serialize allows UintSlice to fulfill Serializer + +func (i *UintSlice) Set(value string) error + Set parses the value into an integer and appends it to the list of values + +func (i *UintSlice) SetUint(value uint) + TODO: Consistently have specific Set function for Int64 and Float64 ? SetInt + directly adds an integer to the list of values + +func (i *UintSlice) String() string + String returns a readable representation of this value (for usage defaults) + +func (i *UintSlice) Value() []uint + Value returns the slice of ints set by this flag + +type UintSliceFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value *UintSlice + Destination *UintSlice + + Aliases []string + EnvVars []string +} + UintSliceFlag is a flag with type *UintSlice + +func (f *UintSliceFlag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *UintSliceFlag) Get(ctx *Context) []uint + Get returns the flag’s value in the given Context. + +func (f *UintSliceFlag) GetCategory() string + GetCategory returns the category for the flag + +func (f *UintSliceFlag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *UintSliceFlag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *UintSliceFlag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *UintSliceFlag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *UintSliceFlag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *UintSliceFlag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *UintSliceFlag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *UintSliceFlag) Names() []string + Names returns the names of the flag + +func (f *UintSliceFlag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *UintSliceFlag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + type VisibleFlag interface { Flag