Skip to content

Commit

Permalink
Update docs and README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
mfridman committed Jan 7, 2025
1 parent 864da5e commit 97a5afa
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 31 deletions.
61 changes: 31 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
[![GoDoc](https://godoc.org/github.com/mfridman/cli?status.svg)](https://pkg.go.dev/github.com/mfridman/cli#section-documentation)
[![CI](https://github.com/mfridman/cli/actions/workflows/ci.yaml/badge.svg)](https://github.com/mfridman/cli/actions/workflows/ci.yaml)

A Go framework for building CLI applications. Extends the standard library's `flag` package to
support [flags anywhere](https://mfridman.com/blog/2024/allowing-flags-anywhere-on-the-cli/) in
command arguments.
A Go package for building CLI applications. Extends the standard library's `flag` package to support
[flags anywhere](https://mfridman.com/blog/2024/allowing-flags-anywhere-on-the-cli/) in command
arguments.

## Features

Expand All @@ -21,8 +21,8 @@ package.

### But why?

This framework is intentionally minimal. It aims to be a building block for CLI applications that
want to leverage the standard library's `flag` package while providing a bit more structure and
This package is intentionally minimal. It aims to be a building block for CLI applications that want
to leverage the standard library's `flag` package while providing a bit more structure and
flexibility.

- Build maintainable command-line tools quickly
Expand All @@ -42,7 +42,8 @@ Required go version: 1.21 or higher

## Quick Start

Here's a simple example of a CLI application that echoes back the input:
Here's a simple example of a CLI application that echoes back the input with a required `-c` flag to
capitalize the output:

```go
root := &cli.Command{
Expand Down Expand Up @@ -83,12 +84,9 @@ if err := cli.Run(context.Background(), root, nil); err != nil {
}
```

This code defines a simple `echo` command that echoes back the input. It supports a `-c` flag to
capitalize the input.

## Command Structure

Each command in your CLI application is represented by a `Command` struct:
Each command is represented by a `Command` struct:

```go
type Command struct {
Expand Down Expand Up @@ -126,20 +124,20 @@ root := &cli.Command{
}
```

The `FlagsMetadata` field is a slice of `FlagMetadata` structs that define metadata for each flag.
Unfortunatly, the `flag` package alone is a bit limiting, so this package adds a layer on top to
provide the most common features, such as automatic handling of required flags.
The optional `FlagsMetadata` field is a way to extend defined flags. The `flag` package alone is a
bit limiting, so we add this to provide the most common features, such as handling of required
flags.

The `SubCommands` field is a slice of `*Command` structs that represent subcommands. This allows you
to organize your CLI application into a hierarchy of commands. Each subcommand can have its own
flags and business logic.
The `SubCommands` field is a list of `*Command` structs that represent subcommands. This allows you
to organize CLI applications into a hierarchy of commands. Each subcommand can have its own flags
and business logic.

The `Exec` field is a function that is called when the command is executed. This is where you put
your business logic.
business logic.

## Flag Access

Flags can be accessed using the type-safe `GetFlag` function, called inside your `Exec` function:
Flags can be accessed using the type-safe `GetFlag` function, called inside the `Exec` function:

```go
// Access boolean flag
Expand Down Expand Up @@ -180,6 +178,20 @@ sub := cli.Command{

Help text is automatically generated, but you can customize it by setting the `UsageFunc` field.

There is a `DefaultUsage` function that generates a default help text for a command, which is useful
to display when `flag.ErrHelp` is returned from `Parse`:

```go
if err := cli.Parse(root, os.Args[1:]); err != nil {
if errors.Is(err, flag.ErrHelp) {
fmt.Fprintf(os.Stdout, "%s\n", cli.DefaultUsage(root)) // Display help text and exit
return
}
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
```

## Usage Syntax Conventions

When reading command usage strings, the following syntax is used:
Expand Down Expand Up @@ -221,25 +233,14 @@ kubectl [-n <namespace>] (get|delete) (pod|service) <name>
This project is in active development and undergoing changes as the API gets refined. Please open an
issue if you encounter any problems or have suggestions for improvement.

- [x] Nail down required flags implementation
- [x] Add tests for typos and command suggestions, crude levenstein distance for now
- [x] Internal implementation (not user-facing), track selected `*Command` in `*State` and remove
`flags *flag.FlagSet` from `*State`
- [x] Figure out whether to keep `*Error` and whether to catch `ErrShowHelp` in `ParseAndRun`
- [x] Should `Parse`, `Run` and `ParseAndRun` be methods on `*Command`? No.
- [ ] What to do with `showHelp()`, should it be a standalone function or an exported method on
`*Command`?
- [ ] Is there room for `clihelp` package for standalone use?

## Acknowledgements

There are many great CLI libraries out there, but I always felt [they were too heavy for my
needs](https://mfridman.com/blog/2021/a-simpler-building-block-for-go-clis/).

I was inspired by Peter Bourgon's [ff](https://github.com/peterbourgon/ff) library, specifically the
`v3` branch, which was soooo close to what I wanted. But the `v4` branch took a different direction
and I wanted to keep the simplicity of the `v3` branch. This library aims to pick up where the `v3`
left off.
and I wanted to keep the simplicity of `v3`. This library aims to pick up where `v3` left off.

## License

Expand Down
2 changes: 1 addition & 1 deletion doc.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Package cli provides a lightweight framework for building command-line applications using Go's
// Package cli provides a lightweight library for building command-line applications using Go's
// standard library flag package. It extends flag functionality to support flags anywhere in command
// arguments.
//
Expand Down

0 comments on commit 97a5afa

Please sign in to comment.