Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 0 additions & 34 deletions .rumdl.toml

This file was deleted.

21 changes: 13 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ go get go.followtheprocess.codes/cli@latest
package main

import (
"context"
"fmt"
"os"

Expand Down Expand Up @@ -77,7 +78,7 @@ func run() error {
cli.Example("Do a thing", "quickstart something"),
cli.Example("Count the things", "quickstart something --count 3"),
cli.Flag(&count, "count", 'c', 0, "Count the things"),
cli.Run(func(cmd *cli.Command) error {
cli.Run(func(ctx context.Context, cmd *cli.Command) error {
fmt.Fprintf(cmd.Stdout(), "Hello from quickstart!, my args were: %v, count was %d\n", cmd.Args(), count)
return nil
}),
Expand All @@ -86,7 +87,7 @@ func run() error {
return err
}

return cmd.Execute()
return cmd.Execute(context.Background())
}
```

Expand All @@ -107,9 +108,9 @@ To create CLI commands, you simply call `cli.New`:
cmd, err := cli.New(
"name", // The name of your command
cli.Short("A new command") // Shown in the help
cli.Run(func(cmd *cli.Command, args []string) error {
cli.Run(func(ctx context.Context, cmd *cli.Command) error {
// This function is what your command does
fmt.Printf("name called with args: %v\n", args)
fmt.Printf("name called with args: %v\n", cmd.Args())
return nil
})
)
Expand All @@ -124,7 +125,7 @@ To add a subcommand underneath the command you've just created, it's again `cli.

```go
// Best to abstract it into a function
func buildSubcommand() (*cli.Command, error) {
func buildSubcommand(ctx context.Context) (*cli.Command, error) {
return cli.New(
"sub", // Name of the sub command e.g. 'clone' for 'git clone'
cli.Short("A sub command"),
Expand All @@ -136,11 +137,13 @@ func buildSubcommand() (*cli.Command, error) {
And add it to your parent command:

```go
ctx := context.Background()

// From the example above
cmd, err := cli.New(
"name", // The name of your command
// ...
cli.SubCommands(buildSubcommand),
cli.SubCommands(buildSubcommand(ctx)),
)
```

Expand All @@ -151,6 +154,8 @@ This pattern can be repeated recursively to create complex command structures.
Flags in `cli` are generic, that is, there is *one* way to add a flag to your command, and that's with the `cli.Flag` option to `cli.New`

```go
// These will get set at command line parse time
// based on your flags
type options struct {
name string
force bool
Expand All @@ -167,7 +172,7 @@ func buildCmd() (*cli.Command, error) {
cli.Flag(&options.force, "force", cli.NoShortHand, false, "Force delete without confirmation"),
cli.Flag(&options.size, "size", 's', 0, "Size of something"),
cli.Flag(&options.items, "items", 'i', nil, "Items to include"),
cli.Run(runCmd(&options)), // Pass the parsed flag values to your command run function
// ...
)
}
```
Expand Down Expand Up @@ -220,7 +225,7 @@ There are two approaches to positional arguments in `cli`, you can either just g
cli.New(
"my-command",
// ...
cli.Run(func(cmd *cli.Command) error {
cli.Run(func(ctx context.Context, cmd *cli.Command) error {
fmt.Fprintf(cmd.Stdout(), "Hello! My arguments were: %v\n", cmd.Args())
return nil
})
Expand Down
8 changes: 0 additions & 8 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,12 @@ tasks:
preconditions:
- sh: command -v golangci-lint
msg: golangci-lint not installed, see https://golangci-lint.run/usage/install/#local-installation

- sh: command -v rumdl
msg: rumdl not installed, see https://github.com/rvben/rumdl#installation
sources:
- "**/*.go"
- .golangci.yml
- "**/*.md"
cmds:
- golangci-lint fmt ./...
- rumdl fmt --fix .

test:
desc: Run the test suite
Expand Down Expand Up @@ -73,12 +69,8 @@ tasks:

- sh: command -v typos
msg: requires typos-cli, run `brew install typos-cli`

- sh: command -v rumdl
msg: rumdl not installed, see https://github.com/rvben/rumdl#installation
cmds:
- golangci-lint run --fix
- rumdl check --fix .
- typos
- nilaway ./...

Expand Down
7 changes: 4 additions & 3 deletions command.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
package cli // import "go.followtheprocess.codes/cli"

import (
"context"
"errors"
"fmt"
"io"
Expand Down Expand Up @@ -116,7 +117,7 @@ type Command struct {

// run is the function actually implementing the command, the command is passed into the function for access
// to things like cmd.Stdout().
run func(cmd *Command) error
run func(ctx context.Context, cmd *Command) error

// flags is the set of flags for this command.
flags *flag.Set
Expand Down Expand Up @@ -184,7 +185,7 @@ type example struct {
//
// If the flags fail to parse, an error will be returned and the Run function
// will not be called.
func (cmd *Command) Execute() error {
func (cmd *Command) Execute(ctx context.Context) error {
if cmd == nil {
return errors.New("Execute called on a nil Command")
}
Expand Down Expand Up @@ -265,7 +266,7 @@ func (cmd *Command) Execute() error {

// If the command is runnable, go and execute its run function
if cmd.run != nil {
return cmd.run(cmd)
return cmd.run(ctx, cmd)
}

// The only way we get here is if the command has subcommands defined but got no arguments given to it
Expand Down
Loading
Loading