cli

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 4, 2023 License: MIT Imports: 7 Imported by: 0

README

Go Report Card

CLI

CLI is a go package for creating command line interfaces. It is intended to be very simple to use and easy to read.

Commands

Commands and flags are declarative, which makes code easy to read and compose.

Positional arguments are loaded into a map, allowing access by name. This improves readability and developer experience. Positional args are included in the help text.

func main(){
    app := cli.App{
        Name:        "cli",
        Description: "An example CLI",
        SubCmds: []cli.Cmd{
            createUserCmd,
        },
    }

    app.Run()
}

// createUserCmd is a simple cmd using a positional arg
var createUserCmd = cli.Cmd{
    Name:        "create",
    Description: "Create a new user",
    Args:        []string{"name"}, // name is a positional arg
    Action: func(args map[string]string) {
        name := args["name"]
        fmt.Println("Creating user:", name)
    },
}

Sub-commands

Every command can have sub-commands, allowing for a tree-like structure.

var userCmd = cli.Cmd{
    Name:        "user",
    Description: "Manage users",
    SubCmds: []cli.Cmd{
        createUserCmd,
        listUsersCmd,
    },
}

Flags

Flags are defined as an interface, allowing for custom flag types to be created.

A number of flag types are included in this package: StringFlag, IntFlag and JSONFlag.

Note that there are additional options for these flags that have not been set

var dbConnFlag = &cli.StringFlag{
    Name:        "db-conn",
    EnvVar:      "DB_CONN",
    Description: "Database connection string",
}

var countFlag = &cli.IntFlag{
    Name:  "count",
    Alias: "n",
    Value: 5, // default value, since countFlag is optional
}

// personFlag demonstrates a generic JSONFlag, using the Person type
var personFlag = &cli.JSONFlag[Person]{
    Name:        "person",
    Description: "A person in JSON format",
}

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

Optional/required flags

Flags can be specified as required or optional and are loaded and validated before the commands are executed.

var doSomethingCmd = cli.Cmd{
    Name:        "something",
    Description: "Performs some action",
    ReqFlags:    []cli.Flag{dbConnFlag, apiKeyFlag},
    OptFlags:    []cli.Flag{envNameFlag},
    Action: func(args map[string]string) {
        // dbConnFlag and apiKeyFlag are guaranteed to be set
        // envNameFlag is optional, if it was not provided it will use the default value
        
        // do something with the flags...
        fmt.Println("dbConn:", dbConnFlag.Value)
        fmt.Println("apiKey:", apiKeyFlag.Value)
        fmt.Println("env:", envNameFlag.Value)
    },
}

Flag interface

// Flag allows for custom flag types to be created.
// (Although the included flag types should be sufficient for most cases.)
// Command line flags are expected in one of the following formats:
//
//	--flag=value
//	--flag='value'
//	--flag="value"
//	--flag
//
// Or using an alias:
//
//	-f=value
//	-f='value'
//	-f="value"
//	-f
type Flag interface {
    GetName() string
    GetAlias() string
    GetDescription() string
    
    // Load a flag. The argFound bool indicates if the flag was found in the cli args
    // and argVal contains the value provided for the flag, if any.
    // Should return true if the flag was loaded (used for required/optional validation)
    // Returns an error if the flag was found but the value was invalid etc.
    // This method can be used to load the flag from any source, not just cli args. Eg: env vars, files etc.
    Load(argFound bool, argVal *string) (loaded bool, err error)
}

Example cli output

See _examples folder for full code examples

$ cli

An example CLI demonstrating different flag types

Usage:
    cli [command] [flags]

Commands:
    db    database    Do something with a database
          hello       Say hello to <name> a number of times
          person      Add a person to a database or something

Optional Flags:
    -h    --help    Print documentation for command

$ cli db

Do something with a database

Usage:
    cli db [flags]

Required Flags:
         --db-conn    Database connection string
                      > env var: DB_CONN

Optional Flags:
    -h    --help    Print documentation for command

2023/04/16 16:20:18 ERROR: cmd flag error: flag: 'db-conn' not provided

$ cli hello --help

Say hello to <name> a number of times

Usage:
    cli hello <name> [flags]

Optional Flags:
    -n    --count
    -h    --help     Print documentation for command

$ cli hello 'freddy the gopher' --count=3

Hello freddy the gopher 0
Hello freddy the gopher 1
Hello freddy the gopher 2

$ cli person

Add a person to a database or something

Usage:
    cli person [flags]

Required Flags:
         --person    A person in JSON format

Optional Flags:
    -h    --help    Print documentation for command

2023/04/16 16:20:45 ERROR: cmd flag error: flag: 'person' not provided

$ cli person --person='{"name":"fritz", "age":25}'

2023/04/16 16:20:48 Person name: fritz
2023/04/16 16:20:48 Person age: 25

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func LoadFlagFromArgs

func LoadFlagFromArgs(name, alias string, args []string) (found bool, value *string, err error)

LoadFlagFromArgs will load a flag from cli args. Returns true if the flag was found, false otherwise. If the flag was found, value will contain the value provided for the flag, if any. If the flag was found with a '=' and no value after the '=' an error will be returned.

Types

type App

type App struct {
	Name        string   // for documentation only (should match the name of the executable)
	Description string   // used for documentation
	SubCmds     []Cmd    // a list of available sub commands
	ReqFlags    []Flag   // required flags: if not provided, the cli will print an error, the help doc, and exit
	OptFlags    []Flag   // optional flags: if not provided, the default value will be used. Note that the help flag is automatically added to this list.
	Args        []string // positional args: used to populate the args map passed to the action function.
	Action      func(args map[string]string)
}

func (*App) Run

func (app *App) Run()

type BoolFlag added in v1.1.0

type BoolFlag struct {
	Name        string
	Alias       string
	Description string
	Value       bool
}

BoolFlag is a flag that if provided, the value will be true. If not provided, the value will be false.

func (*BoolFlag) GetAlias added in v1.1.0

func (flag *BoolFlag) GetAlias() string

func (*BoolFlag) GetDescription added in v1.1.0

func (flag *BoolFlag) GetDescription() string

func (*BoolFlag) GetName added in v1.1.0

func (flag *BoolFlag) GetName() string

func (*BoolFlag) Load added in v1.1.0

func (flag *BoolFlag) Load(argFound bool, argVal *string) (loaded bool, err error)

type Cmd

type Cmd struct {
	Name        string
	Alias       string   // can be used instead of Name (ideally 1 or 2 characters)
	Description string   // used for documentation
	SubCmds     []Cmd    // sub commands list
	ReqFlags    []Flag   // required flags: if not provided, the cli will print an error, the help doc, and exit
	OptFlags    []Flag   // optional flags: if not provided, the default value will be used. Note that the help flag is automatically added to this list.
	Args        []string // positional args: used to populate the args map passed to the action function.
	Action      func(args map[string]string)
	// contains filtered or unexported fields
}

Cmd represents a command in the cli. A command can have sub commands, flags, and positional arguments.

type Flag

type Flag interface {
	GetName() string
	GetAlias() string
	GetDescription() string

	// Load a flag. The argFound bool indicates if the flag was found in the cli args
	// and argVal contains the value provided for the flag, if any.
	// Should return true if the flag was loaded  (used for required/optional validation)
	// Returns an error if the flag was found but the value was invalid etc.
	// This method can be used to load the flag from any source, not just cli args. Eg: env vars, files etc.
	Load(argFound bool, argVal *string) (loaded bool, err error)
}

Flag allows for custom flag types to be created. (Although the included flag types should be sufficient for most cases.) Command line flags are expected in one of the following formats:

--flag=value
--flag='value'
--flag="value"
--flag

Or using an alias:

-f=value
-f='value'
-f="value"
-f

type IntFlag

type IntFlag struct {
	Name        string
	Alias       string
	Description string
	Value       int // can provide a default value here
}

IntFlag can be provided by cli args or env var. Values are parsed as int. CLI args take precedence.

func (*IntFlag) GetAlias

func (flag *IntFlag) GetAlias() string

func (*IntFlag) GetDescription

func (flag *IntFlag) GetDescription() string

func (*IntFlag) GetName

func (flag *IntFlag) GetName() string

func (*IntFlag) Load

func (flag *IntFlag) Load(argFound bool, argVal *string) (loaded bool, err error)

type JSONFlag

type JSONFlag[T any] struct {
	Name        string
	Alias       string
	EnvVar      string
	Description string
	Value       T // can provide a default value here
}

JSONFlag will parse a json string into Value, of type T. The value can be provided by cli args or env var. CLI args take precedence.

func (*JSONFlag[T]) GetAlias

func (flag *JSONFlag[T]) GetAlias() string

func (*JSONFlag[T]) GetDescription

func (flag *JSONFlag[T]) GetDescription() string

func (*JSONFlag[T]) GetName

func (flag *JSONFlag[T]) GetName() string

func (*JSONFlag[T]) Load

func (flag *JSONFlag[T]) Load(argFound bool, argVal *string) (loaded bool, err error)

type StringFlag

type StringFlag struct {
	Name           string
	Alias          string
	EnvVar         string
	Description    string
	AcceptedValues []string // if specified, only these values are accepted
	Value          string   // can provide a default value here
}

StringFlag is a flag that which can be provided by cli args or env var. CLI args take precedence. If AcceptedValues are specified, the value is validated against them.

func (*StringFlag) GetAlias

func (flag *StringFlag) GetAlias() string

func (*StringFlag) GetDescription

func (flag *StringFlag) GetDescription() string

func (*StringFlag) GetName

func (flag *StringFlag) GetName() string

func (*StringFlag) Load

func (flag *StringFlag) Load(argFound bool, argVal *string) (loaded bool, err error)

Directories

Path Synopsis
_example

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL