Skip to content

Commit c47181d

Browse files
Breaking: Change the way flags are configured to be consistent with Args (#186)
* Breaking: Add cli.FlagOption for configuring flags * Update the demo gifs
1 parent 17a4e7a commit c47181d

16 files changed

Lines changed: 218 additions & 168 deletions

File tree

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ func run() error {
7777
cli.Stdout(os.Stdout),
7878
cli.Example("Do a thing", "quickstart something"),
7979
cli.Example("Count the things", "quickstart something --count 3"),
80-
cli.Flag(&count, "count", 'c', 0, "Count the things"),
80+
cli.Flag(&count, "count", 'c', "Count the things"),
8181
cli.Run(func(ctx context.Context, cmd *cli.Command) error {
8282
fmt.Fprintf(cmd.Stdout(), "Hello from quickstart!, my args were: %v, count was %d\n", cmd.Args(), count)
8383
return nil
@@ -168,10 +168,10 @@ func buildCmd() (*cli.Command, error) {
168168
return cli.New(
169169
// ...
170170
// Signature is cli.Flag(*T, name, shorthand, default, description)
171-
cli.Flag(&options.name, "name", 'n', "", "The name of something"),
172-
cli.Flag(&options.force, "force", cli.NoShortHand, false, "Force delete without confirmation"),
173-
cli.Flag(&options.size, "size", 's', 0, "Size of something"),
174-
cli.Flag(&options.items, "items", 'i', nil, "Items to include"),
171+
cli.Flag(&options.name, "name", 'n', "The name of something"),
172+
cli.Flag(&options.force, "force", cli.NoShortHand, "Force delete without confirmation"),
173+
cli.Flag(&options.size, "size", 's', "Size of something"),
174+
cli.Flag(&options.items, "items", 'i', "Items to include"),
175175
// ...
176176
)
177177
}
@@ -374,7 +374,7 @@ Consider the following example of a bad shorthand value:
374374
var delete bool
375375

376376
// Note: "de" is a bad shorthand, it's two letters
377-
cli.New("demo", cli.Flag(&delete, "delete", "de", false, "Delete something"))
377+
cli.New("demo", cli.Flag(&delete, "delete", "de", "Delete something"))
378378
```
379379

380380
In `cli` this is impossible as we use `rune` as the type for a flag shorthand, so the above example would not compile. Instead you must specify a valid rune:
@@ -383,14 +383,14 @@ In `cli` this is impossible as we use `rune` as the type for a flag shorthand, s
383383
var delete bool
384384

385385
// Ahhh, that's better
386-
cli.New("demo", cli.Flag(&delete, "delete", 'd', false, "Delete something"))
386+
cli.New("demo", cli.Flag(&delete, "delete", 'd', "Delete something"))
387387
```
388388

389389
And if you don't want a shorthand? i.e. just `--delete` with no `-d` option:
390390

391391
```go
392392
var delete bool
393-
cli.New("demo", cli.Flag(&delete, "delete", cli.NoShortHand, false, "Delete something"))
393+
cli.New("demo", cli.Flag(&delete, "delete", cli.NoShortHand, "Delete something"))
394394
```
395395

396396
## In the Wild

command.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,10 @@ func New(name string, options ...Option) (*Command, error) {
6565
}
6666

6767
// Ensure we always have at least help and version flags
68-
err := Flag(&cfg.helpCalled, "help", 'h', false, "Show help for "+name).apply(&cfg)
68+
err := Flag(&cfg.helpCalled, "help", 'h', "Show help for "+name).apply(&cfg)
6969
errs = errors.Join(errs, err) // nil errors are discarded in join
7070

71-
err = Flag(&cfg.versionCalled, "version", 'V', false, "Show version info for "+name).apply(&cfg)
71+
err = Flag(&cfg.versionCalled, "version", 'V', "Show version info for "+name).apply(&cfg)
7272

7373
errs = errors.Join(errs, err)
7474
if errs != nil {

command_test.go

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ func TestExecute(t *testing.T) {
105105

106106
return nil
107107
}),
108-
cli.Flag(&force, "force", 'f', false, "Force something"),
108+
cli.Flag(&force, "force", 'f', "Force something"),
109109
}
110110

111111
cmd, err := cli.New("test", slices.Concat(options, tt.options)...)
@@ -270,8 +270,8 @@ func TestSubCommandExecute(t *testing.T) {
270270

271271
sub1 := func() (*cli.Command, error) {
272272
defaultOpts := []cli.Option{
273-
cli.Flag(&force, "force", 'f', false, "Force for sub1"),
274-
cli.Flag(&something, "something", 's', "", "Something for sub1"),
273+
cli.Flag(&force, "force", 'f', "Force for sub1"),
274+
cli.Flag(&something, "something", 's', "Something for sub1"),
275275
cli.Run(func(ctx context.Context, cmd *cli.Command) error {
276276
if something == "" {
277277
something = "<empty>"
@@ -315,8 +315,8 @@ func TestSubCommandExecute(t *testing.T) {
315315

316316
return nil
317317
}),
318-
cli.Flag(&deleteMe, "delete", 'd', false, "Delete for sub2"),
319-
cli.Flag(&number, "number", 'n', -1, "Number for sub2"),
318+
cli.Flag(&deleteMe, "delete", 'd', "Delete for sub2"),
319+
cli.Flag(&number, "number", 'n', "Number for sub2", cli.FlagDefault(-1)),
320320
}
321321

322322
opts := slices.Concat(defaultOpts, tt.sub2Options)
@@ -433,7 +433,7 @@ func TestHelp(t *testing.T) {
433433
cli.OverrideArgs([]string{"--help"}),
434434
cli.Arg(new(string), "src", "The file to copy"), // This one is required
435435
cli.Arg(new(string), "dest", "Destination to copy to", cli.ArgDefault("destination.txt")), // This one is optional
436-
cli.Flag(new(flag.Count), "verbosity", 'v', 0, "Increase the verbosity level"),
436+
cli.Flag(new(flag.Count), "verbosity", 'v', "Increase the verbosity level"),
437437
cli.Run(func(ctx context.Context, cmd *cli.Command) error { return nil }),
438438
},
439439
wantErr: false,
@@ -493,10 +493,16 @@ func TestHelp(t *testing.T) {
493493
cli.Short("A cool CLI to do things"),
494494
cli.Long("A longer, probably multiline description"),
495495
cli.SubCommands(sub1, sub2),
496-
cli.Flag(new(bool), "delete", 'd', false, "Delete something"),
497-
cli.Flag(new(int), "count", flag.NoShortHand, -1, "Count something"),
498-
cli.Flag(new([]string), "things", flag.NoShortHand, nil, "Names of things"),
499-
cli.Flag(new([]string), "more", flag.NoShortHand, []string{"one", "two"}, "Names of things with a default"),
496+
cli.Flag(new(bool), "delete", 'd', "Delete something"),
497+
cli.Flag(new(int), "count", flag.NoShortHand, "Count something", cli.FlagDefault(-1)),
498+
cli.Flag(new([]string), "things", flag.NoShortHand, "Names of things"),
499+
cli.Flag(
500+
new([]string),
501+
"more",
502+
flag.NoShortHand,
503+
"Names of things with a default",
504+
cli.FlagDefault([]string{"one", "two"}),
505+
),
500506
},
501507
wantErr: false,
502508
},
@@ -735,16 +741,16 @@ func TestOptionValidation(t *testing.T) {
735741
{
736742
name: "flag already exists",
737743
options: []cli.Option{
738-
cli.Flag(new(int), "count", 'c', 0, "Count something"),
739-
cli.Flag(new(int), "count", 'c', 0, "Count something (again)"),
744+
cli.Flag(new(int), "count", 'c', "Count something"),
745+
cli.Flag(new(int), "count", 'c', "Count something (again)"),
740746
},
741747
errMsg: `flag "count" already defined`,
742748
},
743749
{
744750
name: "flag short already exists",
745751
options: []cli.Option{
746-
cli.Flag(new(int), "count", 'c', 0, "Count something"),
747-
cli.Flag(new(string), "config", 'c', "", "Path to config file"),
752+
cli.Flag(new(int), "count", 'c', "Count something"),
753+
cli.Flag(new(string), "config", 'c', "Path to config file"),
748754
},
749755
errMsg: `could not add flag "config" to command "test": shorthand "c" already in use for flag "count"`,
750756
},
@@ -884,8 +890,8 @@ func TestCommandOptionOrder(t *testing.T) {
884890
cli.Arg(new(string), "third", "Third arg"),
885891
cli.Version("v1.2.3"),
886892
cli.SubCommands(sub),
887-
cli.Flag(&f, "flag", 'f', false, "Set a bool flag"),
888-
cli.Flag(&count, "count", 'c', 0, "Count a thing"),
893+
cli.Flag(&f, "flag", 'f', "Set a bool flag"),
894+
cli.Flag(&count, "count", 'c', "Count a thing"),
889895
}
890896

891897
baseLineOptions := slices.Concat(
@@ -1001,9 +1007,9 @@ func BenchmarkNew(b *testing.B) {
10011007
cli.Version("dev"),
10021008
cli.Commit("dfdddaf"),
10031009
cli.Example("An example", "bench --help"),
1004-
cli.Flag(new(bool), "force", 'f', false, "Force something"),
1005-
cli.Flag(new(string), "name", 'n', "", "The name of something"),
1006-
cli.Flag(new(int), "count", 'c', 1, "Count something"),
1010+
cli.Flag(new(bool), "force", 'f', "Force something"),
1011+
cli.Flag(new(string), "name", 'n', "The name of something"),
1012+
cli.Flag(new(int), "count", 'c', "Count something", cli.FlagDefault(1)),
10071013
cli.Run(func(ctx context.Context, cmd *cli.Command) error { return nil }),
10081014
)
10091015
if err != nil {

docs/img/cancel.gif

-1.41 KB
Loading

docs/img/demo.png

-2.17 KB
Loading

docs/img/namedargs.gif

906 Bytes
Loading

docs/img/quickstart.gif

-1.07 KB
Loading

docs/img/subcommands.gif

-2.28 KB
Loading

examples/cover/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ func main() {
2020
cli.Version("v1.2.3"),
2121
cli.Stdout(os.Stdout),
2222
cli.Example("Do a thing", "demo thing --count"),
23-
cli.Flag(&count, "count", 'c', 0, "Count the thing"),
23+
cli.Flag(&count, "count", 'c', "Count the thing"),
2424
cli.Run(func(ctx context.Context, cmd *cli.Command) error {
2525
fmt.Fprintln(cmd.Stdout(), "Hello from demo, my arguments were: ", cmd.Args())
2626
return nil

examples/quickstart/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func run() error {
2929
cli.Stdout(os.Stdout),
3030
cli.Example("Do a thing", "quickstart something"),
3131
cli.Example("Count the things", "quickstart something --count 3"),
32-
cli.Flag(&count, "count", 'c', 0, "Count the things"),
32+
cli.Flag(&count, "count", 'c', "Count the things"),
3333
cli.Run(func(ctx context.Context, cmd *cli.Command) error {
3434
fmt.Fprintf(cmd.Stdout(), "Hello from quickstart!, my args were: %v, count was %d\n", cmd.Args(), count)
3535
return nil

0 commit comments

Comments
 (0)