Skip to content

Commit

Permalink
Merge pull request #1382 from urfave/generating-flags-again
Browse files Browse the repository at this point in the history
Generate flag types (again?)
  • Loading branch information
meatballhat committed May 7, 2022
2 parents cbd9bd9 + 2ac3904 commit 48f612c
Show file tree
Hide file tree
Showing 33 changed files with 1,495 additions and 519 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/cli.yml
Expand Up @@ -87,3 +87,8 @@ jobs:

- name: toc
run: go run internal/build/build.go toc docs/v2/manual.md

- name: diff check
run: |
git diff --exit-code
git diff --cached --exit-code
40 changes: 40 additions & 0 deletions Makefile
@@ -0,0 +1,40 @@
# NOTE: this Makefile is meant to provide a simplified entry point for humans to
# run all of the critical steps to verify one's changes are harmonious in
# nature. Keeping target bodies to one line each and abstaining from make magic
# are very important so that maintainers and contributors can focus their
# attention on files that are primarily Go.

.PHONY: all
all: generate lint tag-test test check-bin tag-check-bin gfmrun toc

.PHONY: generate
generate:
go run internal/build/build.go generate

.PHONY: lint
lint:
go run internal/build/build.go vet

.PHONY: tag-test
tag-test:
go run internal/build/build.go -tags urfave_cli_no_docs test

.PHONY: test
test:
go run internal/build/build.go test

.PHONY: check-bin
check-bin:
go run internal/build/build.go check-binary-size

.PHONY: tag-check-bin
tag-check-bin:
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

.PHONY: toc
toc:
go run internal/build/build.go toc docs/v2/manual.md
2 changes: 1 addition & 1 deletion cli.go
Expand Up @@ -20,4 +20,4 @@
// }
package cli

//go:generate go run flag-gen/main.go flag-gen/assets_vfsdata.go
//go:generate go run internal/genflags/cmd/genflags/main.go
116 changes: 100 additions & 16 deletions docs/CONTRIBUTING.md
@@ -1,18 +1,102 @@
## Contributing

Use @urfave/cli to ping the maintainers.

Feel free to put up a pull request to fix a bug or maybe add a feature. We will
give it a code review and make sure that it does not break backwards
compatibility. If collaborators agree that it is in line with
the vision of the project, we will work with you to get the code into
a mergeable state and merge it into the main branch.

If you have contributed something significant to the project, we will most
likely add you as a collaborator. As a collaborator you are given the ability
to merge others pull requests. It is very important that new code does not
break existing code, so be careful about what code you do choose to merge.

If you feel like you have contributed to the project but have not yet been added
as a collaborator, we probably forgot to add you :sweat_smile:. Please open an
issue!
Welcome to the `urfave/cli` contributor docs! This goal of this document is to help those
interested in joining the 200+ humans who have contributed to this project over the years.

> As a general guiding principle, the current maintainers may be notified via the
> @urfave/cli GitHub team.
All of the current maintainers are *volunteers* who live in various timezones with
different scheduling needs, so please understand that your contribution or question may
not get a response for many days.

### semantic versioning adherence

The `urfave/cli` project strives to strictly adhere to semantic versioning. The active
development branches and the milestones and import paths to which they correspond are:

#### `main` branch

<https://github.com/urfave/cli/tree/main>

The majority of active development and issue management is targeting the `main` branch,
which **MUST** *only* receive bug fixes and feature *additions*.

- :arrow_right: [`v2.x`](https://github.com/urfave/cli/milestone/16)
- :arrow_right: `github.com/urfave/cli/v2`

#### `v1` branch

<https://github.com/urfave/cli/tree/v1>

The `v1` branch **MUST** only receive bug fixes in the `v1.22.x` series. There is no
strict rule regarding bug fixes to the `v2.x` series being backported to the `v1.22.x`
series.

- :arrow_right: [`v1.22.x`](https://github.com/urfave/cli/milestone/11)
- :arrow_right: `github.com/urfave/cli`

#### `v3-dev-main` branch

<https://github.com/urfave/cli/tree/v3-dev-main>

The `v3-dev-branch` **MUST** receive all bug fixes and features added to the `main` branch
and **MAY** receive feature *removals* and other changes that are otherwise
*backward-incompatible* with the `v2.x` series.

- :arrow_right: [`v3.x`](https://github.com/urfave/cli/milestone/5)
- unreleased / unsupported

### development workflow

Most of the tooling around the development workflow strives for effective
[dogfooding](https://en.wikipedia.org/wiki/Eating_your_own_dog_food). There is a top-level
`Makefile` that is maintained strictly for the purpose of easing verification of one's
development environment and any changes one may have introduced:

```sh
make
```

Running the default `make` target (`all`) will ensure all of the critical steps are run to
verify one's changes are harmonious in nature. The same steps are also run during the
[continuous integration
phase](https://github.com/urfave/cli/blob/main/.github/workflows/cli.yml).

#### generated code

A significant portion of the project's source code is generated, with the goal being to
eliminate repetetive maintenance where other type-safe abstraction is impractical or
impossible with Go versions `< 1.18`. In a future where the eldest Go version supported is
`1.18.x`, there will likely be efforts to take advantage of
[generics](https://go.dev/doc/tutorial/generics).

The built-in `go generate` command is used to run the commands specified in
`//go:generate` directives. Each such command runs a file that also supports a command
line help system which may be consulted for further information, e.g.:

```sh
go run internal/genflags/cmd/genflags/main.go --help
```

### pull requests

Please feel free to open a pull request to fix a bug or add a feature. The @urfave/cli
team will review it as soon as possible, giving special attention to maintaining backward
compatibility. If the @urfave/cli team agrees that your contribution is in line with the
vision of the project, they will work with you to get the code into a mergeable state,
merged, and then released.

### granting of commit bit / admin mode

Those with a history of contributing to this project will likely be invited to join the
@urfave/cli team. As a member of the @urfave/cli team, you will have the ability to fully
administer pull requests, issues, and other repository bits.

If you feel that you should be a member of the @urfave/cli team but have not yet been
added, the most likely explanation is that this is an accidental oversight! :sweat_smile:.
Please open an issue!

<!--
vim:tw=90
-->
50 changes: 50 additions & 0 deletions flag-spec.yaml
@@ -0,0 +1,50 @@
# NOTE: this file is used by the tool defined in
# ./internal/genflags/cmd/genflags/main.go which uses the
# `genflags.Spec` type that maps to this file structure.

flag_types:
bool: {}
float64: {}
int64: {}
int: {}
time.Duration: {}
uint64: {}
uint: {}

string:
struct_fields:
- { name: TakesFile, type: bool }
Generic:
struct_fields:
- { name: TakesFile, type: bool }
Path:
struct_fields:
- { name: TakesFile, type: bool }

Float64Slice:
value_pointer: true
skip_interfaces:
- fmt.Stringer
Int64Slice:
value_pointer: true
skip_interfaces:
- fmt.Stringer
IntSlice:
value_pointer: true
skip_interfaces:
- fmt.Stringer
StringSlice:
value_pointer: true
skip_interfaces:
- fmt.Stringer
struct_fields:
- { name: TakesFile, type: bool }
Timestamp:
value_pointer: true
struct_fields:
- { name: Layout, type: string }

# TODO: enable UintSlice
# UintSlice: {}
# TODO: enable Uint64Slice once #1334 lands
# Uint64Slice: {}
2 changes: 1 addition & 1 deletion flag.go
Expand Up @@ -258,7 +258,7 @@ func withEnvHint(envVars []string, str string) string {
return str + envText
}

func flagNames(name string, aliases []string) []string {
func FlagNames(name string, aliases []string) []string {
var ret []string

for _, part := range append([]string{name}, aliases...) {
Expand Down
31 changes: 0 additions & 31 deletions flag_bool.go
Expand Up @@ -6,37 +6,6 @@ import (
"strconv"
)

// BoolFlag is a flag with type bool
type BoolFlag struct {
Name string
Aliases []string
Usage string
EnvVars []string
FilePath string
Required bool
Hidden bool
Value bool
DefaultText string
Destination *bool
HasBeenSet bool
}

// IsSet returns whether or not the flag has been set through env or file
func (f *BoolFlag) IsSet() bool {
return f.HasBeenSet
}

// String returns a readable representation of this value
// (for usage defaults)
func (f *BoolFlag) String() string {
return FlagStringer(f)
}

// Names returns the names of the flag
func (f *BoolFlag) Names() []string {
return flagNames(f.Name, f.Aliases)
}

// IsRequired returns whether or not the flag is required
func (f *BoolFlag) IsRequired() bool {
return f.Required
Expand Down
31 changes: 0 additions & 31 deletions flag_duration.go
Expand Up @@ -6,37 +6,6 @@ import (
"time"
)

// DurationFlag is a flag with type time.Duration (see https://golang.org/pkg/time/#ParseDuration)
type DurationFlag struct {
Name string
Aliases []string
Usage string
EnvVars []string
FilePath string
Required bool
Hidden bool
Value time.Duration
DefaultText string
Destination *time.Duration
HasBeenSet bool
}

// IsSet returns whether or not the flag has been set through env or file
func (f *DurationFlag) IsSet() bool {
return f.HasBeenSet
}

// String returns a readable representation of this value
// (for usage defaults)
func (f *DurationFlag) String() string {
return FlagStringer(f)
}

// Names returns the names of the flag
func (f *DurationFlag) Names() []string {
return flagNames(f.Name, f.Aliases)
}

// IsRequired returns whether or not the flag is required
func (f *DurationFlag) IsRequired() bool {
return f.Required
Expand Down
31 changes: 0 additions & 31 deletions flag_float64.go
Expand Up @@ -6,37 +6,6 @@ import (
"strconv"
)

// Float64Flag is a flag with type float64
type Float64Flag struct {
Name string
Aliases []string
Usage string
EnvVars []string
FilePath string
Required bool
Hidden bool
Value float64
DefaultText string
Destination *float64
HasBeenSet bool
}

// IsSet returns whether or not the flag has been set through env or file
func (f *Float64Flag) IsSet() bool {
return f.HasBeenSet
}

// String returns a readable representation of this value
// (for usage defaults)
func (f *Float64Flag) String() string {
return FlagStringer(f)
}

// Names returns the names of the flag
func (f *Float64Flag) Names() []string {
return flagNames(f.Name, f.Aliases)
}

// IsRequired returns whether or not the flag is required
func (f *Float64Flag) IsRequired() bool {
return f.Required
Expand Down
24 changes: 0 additions & 24 deletions flag_float64_slice.go
Expand Up @@ -75,36 +75,12 @@ func (f *Float64Slice) Get() interface{} {
return *f
}

// Float64SliceFlag is a flag with type *Float64Slice
type Float64SliceFlag struct {
Name string
Aliases []string
Usage string
EnvVars []string
FilePath string
Required bool
Hidden bool
Value *Float64Slice
DefaultText string
HasBeenSet bool
}

// IsSet returns whether or not the flag has been set through env or file
func (f *Float64SliceFlag) IsSet() bool {
return f.HasBeenSet
}

// String returns a readable representation of this value
// (for usage defaults)
func (f *Float64SliceFlag) String() string {
return withEnvHint(f.GetEnvVars(), stringifyFloat64SliceFlag(f))
}

// Names returns the names of the flag
func (f *Float64SliceFlag) Names() []string {
return flagNames(f.Name, f.Aliases)
}

// IsRequired returns whether or not the flag is required
func (f *Float64SliceFlag) IsRequired() bool {
return f.Required
Expand Down

0 comments on commit 48f612c

Please sign in to comment.