Skip to content

Commit

Permalink
- Update README
Browse files Browse the repository at this point in the history
- Fix issues / crashes with sub-commands handling
  • Loading branch information
maargenton committed Nov 5, 2023
1 parent a11653e commit 919a37a
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 3 deletions.
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"mode": "auto",
"program": "${workspaceFolder}/sample/subcmd-demo",
"args": [
"migrate",
// "migrate",
]
}
]
Expand Down
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,56 @@ completion machinery can be disabled by setting `cmd.DisableCompletion` on the
root command.


## Sub-command support

The `go-cli` package also provides support for sub-commands definition, to build
a command-line interface similar to `git`, `go` and `kubectl`, where a single
binary exposes a number of related actions.

Sub-commands are defined by adding multiple named commands to the `SubCommands`
field of the main command definition:

```
func main() {
cli.Run(&cli.Command{
SubCommands: []cli.Command{
{
Name: "migrate",
Description: "run DB migration",
Handler: &MigrateCmd{},
},
....
},
})
}
```

### No prefix argument

When defining sub-commands with `go-cli`, the sequence of sub-commands verbs and
noun are expected to appear at the beginning of the command-line, before any
option or argument. This is in contrast to e.g. `git` which allows a subset of
global arguments to appear before the sub-command.

With `go-cli`, each sub-command has its own set of command-line options and
arguments, defined in the command struct. Options that are shared between some
or all sub-commands can be defined on a shared nested struct.


### Bare command with sub-commands

In general, command-line utilities either have no sub-commands or only
sub-commands. With `gp-cli`, you can have both a default behavior and a list of
sub-command to provide additional related functionalities.


### Help

In general, utilities with sub-commands provide help through an `help`
sub-command that precede the specific command the inquiry is about. With
`go-cli`, help is by default requested with the `--help` option.


## Enum support

To help with command-line handling of enumerated types, the `go-cli` package
Expand Down
2 changes: 1 addition & 1 deletion cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func Run(cmd *Command) {

} else if errors.Is(err, cli.ErrHelpRequested) {
fmt.Print(cmd.Usage())

os.Exit(1)
} else if errors.Is(err, cli.ErrVersionRequested) {
var version = cmd.Version()
if version != "" {
Expand Down
3 changes: 3 additions & 0 deletions pkg/cli/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ func (cmd *Command) Run() error {
return err
}

if cmd.Handler == nil {
return ErrHelpRequested
}
if err := cmd.Handler.Run(); err != nil {
return err
}
Expand Down
3 changes: 3 additions & 0 deletions pkg/option/optionset.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ type Set struct {
// that can be set through commandline arguments
func NewOptionSet(v interface{}) (*Set, error) {
var pv = reflect.ValueOf(v)
if !pv.IsValid() {
return &Set{}, nil
}
if pv.Kind() != reflect.Ptr || pv.IsNil() || pv.Elem().Kind() != reflect.Struct {
return nil, fmt.Errorf("invalid argument of type '%v', non-null pointer to struct expected", pv.Type())
}
Expand Down
2 changes: 1 addition & 1 deletion sample/subcmd-demo/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (

func main() {
cli.Run(&cli.Command{
Handler: &ServerCmd{},
// Handler: &ServerCmd{},
Description: "API server for demo service",

SubCommands: []cli.Command{
Expand Down

0 comments on commit 919a37a

Please sign in to comment.