cli

package module
v2.0.3+incompatible Latest Latest
Warning

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

Go to latest
Published: Oct 29, 2019 License: Apache-2.0 Imports: 12 Imported by: 3

README

go-cli

GoDoc Build Status Coverage Status Go Report Card Release License

go-cli is a package to build a CLI application. Support command/sub-commands.

Some applications are built using go-cli including:

Table of Contents

Installation

go-cli is available using the standard go get command.

To install go-cli, simply run:

go get github.com/subchen/go-cli

Syntax for Command Line

// Long option
--flag    // boolean flags, or flags with no option default values
--flag x  // only on flags without a default value
--flag=x

// Short option
-x        // boolean flags
-x 123
-x=123
-x123     // value is 123

// value wrapped by quote
-x="123"
-x='123'

// unordered in flags and arguments
arg1 -x 123 arg2 --test arg3 arg4

// stops parsing after the terminator `--`
-x 123 -- arg1 --not-a-flag arg3 arg4

Getting Started

A simple CLI application:

package main

import (
    "fmt"
    "os"
    "github.com/subchen/go-cli"
)

func main() {
    app := cli.NewApp()
    app.Name = "hello"
    app.Version = "1.0.0"
    app.Usage = "a hello world application."
    app.Action = func(c *cli.Context) {
        fmt.Println("Hello World!")
    }
    app.Run(os.Args)
}

Build and run our new CLI application

$ go build
$ ./hello
Hello World!

go-cli also generates neat help text

$ ./hello --help
NAME:
    hello - a hello world application.

USAGE:
    hello [options] [arguments...]

VERSION:
    1.0.0

OPTIONS:
    --help     print this help
    --version  print version information
Arguments

You can lookup arguments by calling the Args function on cli.Context, e.g.:

app := cli.NewApp()

app.Action = func(c *cli.Context) {
    name := c.Args()[0]
    fmt.Printf("Hello %v\n", name)
}

app.Run(os.Args)
Flags

Setting and querying flags is simple.

app := cli.NewApp()

app.Flags = []*cli.Flag {
    {
        Name: "name",
        Usage: "a name of user",
    },
}

app.Action = func(c *cli.Context) {
    name := c.GetString("name")
    fmt.Printf("Hello %v\n", name)
}

app.Run(os.Args)
Bool flag

A bool flag can has a optional inline bool value.

&cli.Flag{
    Name: "verbose",
    Usage: "output verbose information",
    IsBool: true,
},

The parsed arguments likes:

// valid
--verbose
--verbose=true
--verbose=false

// invalid
--verbose false

bool flag accepts 1,t,true,yes,on as true, 0,f,false,no,off as false.

Value bind

You can bind a variable for a Flag.Value, which will be set after parsed.

var name string

app := cli.NewApp()

app.Flags = []*cli.Flag {
    {
        Name: "name",
        Usage: "a name of user",
        Value: &name,
    },
}

app.Action = func(c *cli.Context) {
    fmt.Printf("Hello %v\n", name)
}

app.Run(os.Args)

Flag.Value can accept a cli.Value interface or a pointer of base type.

  • base type:

    • *string
    • *bool
    • *int, *int8, *int16, *int32, *int64
    • *uint, *uint8, *uint16, *uint32, *uint64
    • *float32, *float64
    • *time.Time, *time.Duration, *time.Location
    • *net.IP, *net.IPMask, *net.IPNet
    • *url.URL
  • slice of base type:

    • *[]string
    • *[]int, *[]uint, *[]float64
    • *[]net.IP, *[]net.IPNet
    • *[]url.URL
  • cli.Value:

    type Value interface {
        String() string
        Set(string) error
    }
    

Note: If you set *bool as Flag.Value, the Flag.IsBool will be automatically true.

Short, Long, Alias Names

You can set multiply name in a flag, a short name, a long name, or multiple alias names.

&cli.Flag{
    Name: "o, output, output-dir",
    Usage: "A directory for output",
}

Then, results in help output like:

-o, --output, --output-dir value   A directory for output
Placeholder

Sometimes it's useful to specify a flag's value within the usage string itself.

For example this:

&cli.Flag{
    Name: "o, output",
    Usage: "A directory for output",
    Placeholder: "DIR",
}

Then, results in help output like:

-o DIR, --output DIR   A directory for output
Default Value
&cli.Flag{
    Name: "o, output",
    Usage: "A directory for output",
    DefValue: "/tmp/",
}

You also can set a default value got from the Environment

&cli.Flag{
    Name: "o, output",
    Usage: "A directory for output",
    EnvVar: "APP_OUTPUT_DIR",
}

The EnvVar may also be given as a comma-delimited "cascade", where the first environment variable that resolves is used as the default.

EnvVar: "APP_OUTPUT,APP_OUTPUT_DIR",
NoOptDefVal

If a flag has a NoOptDefVal and the flag is set on the command line without an option the flag will be set to the NoOptDefVal.

For example given:

&cli.Flag{
    Name: "flagname",
    DefValue: "123",
    NoOptDefVal: "456",
    Value: &val
}

Would result in something like

Parsed Arguments Resulting Value
--flagname=000 val=000
--flagname val=456
[nothing] val=123
Hidden flags

It is possible to mark a flag as hidden, meaning it will still function as normal, however will not show up in usage/help text.

&cli.Flag{
    Name: "secretFlag",
    Hidden: true,
}
Commands

Commands can be defined for a more git-like command line app.

package main

import (
    "fmt"
    "os"
    "strings"
    "github.com/subchen/go-cli"
)

func main() {
    app := cli.NewApp()
    app.Name = "git"
    app.Commands = []*cli.Command{
        {
            Name:   "add",
            Usage:  "Add file contents to the index",
            Action: func(c *cli.Context) {
                fmt.Println("added files: ", strings.Join(c.Args(), ", "))
            },
        },
        {
            // alias name
            Name:   "commit, co",
            Usage:  "Record changes to the repository",
            Flags:  []*cli.Flag {
                {
                    Name: "m, message",
                    Usage: "commit message",
                },
            },
            Hidden: false,
            Action: func(c *cli.Context) {
                fmt.Println("commit message: ", c.GetString("m"))
            },
        },
    }

    app.SeeAlso = `https://github.com/subchen/go-cli
https://github.com/subchen/go-cli/wiki`

    app.Run(os.Args)
}

Also, you can use sub-commands in a command.

Generate Help

The default help flag (--help) is defined in cli.App and cli.Command.

Customize help

All of the help text generation may be customized. A help template is exposed as variable cli.HelpTemplate, that can be override.

// Append copyright
cli.HelpTemplate = cli.HelpTemplate + "@2017 Your company, Inc.\n\n"

Or, you can rewrite a help using customized func.

app := cli.NewApp()

app.ShowHelp = func(c *cli.HelpContext) {
    fmt.Println("this is my help generated.")
}

app.Run(os.Args)

Generate Version

The default version flag (--version) is defined in cli.App.

app := cli.NewApp()
app.Name = "hello"
app.Version = "1.0.0"
app.BuildInfo = &cli.BuildInfo{
    GitBranch:   "master",
    GitCommit:   "320279c1a9a6537cdfd1e526063f6a748bb1fec3",
    GitRevCount: "1234",
    Timestamp:   "Sat May 13 19:53:08 UTC 2017",
}
app.Run(os.Args)

Then, ./hello --version results like:

Name:       hello
Version:    1.0.0
Patches:    1234
Git branch: master
Git commit: 320279c1a9a6537cdfd1e526063f6a748bb1fec3
Built:      Sat May 13 19:53:08 UTC 2017
Go version: go1.8.1
OS/Arch:    darwin/amd64
Customize version

You can rewrite version output using customized func.

app := cli.NewApp()

app.ShowVersion = func(app *App) {
    fmt.Println("Version: ", app.Version)
}

app.Run(os.Args)

Error Handler

OnCommandNotFound

go-cli provides OnCommandNotFound func to handle an error if command/sub-command is not found.

app := cli.NewApp()
app.Flags = ...
app.Commands = ...

app.OnCommandNotFound = func(c *cli.Context, command string) {
    c.ShowError(fmt.Errorf("Command not found: %s", command))
}

app.Run(os.Args)
OnActionPanic

go-cli provides OnActionPanic func to handle an error if panic in action.

app := cli.NewApp()
app.Flags = ...
app.Commands = ...

app.OnActionPanic = func(c *cli.Context, err error) {
    os.Stderr.WriteString(fmt.Sprintf("fatal: %v\n", err))
}

app.Run(os.Args)

Notes: go-cli will only output error message without golang error stacks if app.OnActionPanic is nil.

Contributing

  • Fork it
  • Create your feature branch (git checkout -b my-new-feature)
  • Commit your changes (git commit -am 'Add some feature')
  • Push to the branch (git push origin my-new-feature)
  • Create new Pull Request

License

Apache 2.0 license. See LICENSE

Documentation

Index

Constants

This section is empty.

Variables

View Source
var HelpTemplate = `` /* 800-byte string literal not displayed */

HelpTemplate is the text template for the Default help topic. go-cli uses text/template to render templates. You can render custom help text by setting this variable.

Functions

This section is empty.

Types

type App

type App struct {
	// The name of the program. Defaults to path.Base(os.Args[0])
	Name string
	// The version of the program
	Version string
	// Short description of the program.
	Usage string
	// Text to override the USAGE section of help
	UsageText string
	// Long description of the program
	Description string
	// Authors of the program
	Authors string
	// Examples of the program
	Examples string
	// SeeAlso of the program
	SeeAlso string

	// build information, show in --version
	BuildInfo *BuildInfo

	// List of flags to parse
	Flags []*Flag
	// List of commands to execute
	Commands []*Command

	// Hidden --help and --version from usage
	HiddenHelp    bool
	HiddenVersion bool

	// Display full help
	ShowHelp func(*HelpContext)
	// Display full version
	ShowVersion func(*App)

	// The action to execute when no subcommands are specified
	Action func(*Context)

	// Execute this function if the proper command cannot be found
	OnCommandNotFound func(*Context, string)

	// Handler if panic in app.Action() and command.Action()
	OnActionPanic func(*Context, error)
}

App is the main structure of a cli application

func NewApp

func NewApp() *App

NewApp creates a new cli Application

func (*App) Run

func (a *App) Run(arguments []string)

Run is the entry point to the cli app, parse argument and call Execute() or command.Execute()

type BuildInfo

type BuildInfo struct {
	Timestamp   string
	GitBranch   string
	GitCommit   string
	GitRevCount string
}

BuildInfo stores app build info

func ParseBuildInfo

func ParseBuildInfo(info string) *BuildInfo

ParseBuildInfo parse a buildinfo string info struct

type Command

type Command struct {
	// The name of the program. Defaults to path.Base(os.Args[0])
	Name string
	// Short description of the program.
	Usage string
	// Text to override the USAGE section of help
	UsageText string
	// Long description of the program
	Description string
	// Examples of the program
	Examples string
	// SeeAlso of the program
	SeeAlso string

	// List of flags to parse
	Flags []*Flag
	// List of commands to execute
	Commands []*Command

	// hidden --help from usage
	HiddenHelp bool

	// Treat all flags as normal arguments if true
	SkipFlagParsing bool

	// Boolean to hide this command from help
	Hidden bool

	// Display full help
	ShowHelp func(*HelpContext)

	// The action to execute when no subcommands are specified
	Action func(*Context)

	// Execute this function if the proper command cannot be found
	OnCommandNotFound func(*Context, string)
}

Command is a subcommand for a cli.App

func (*Command) Names

func (c *Command) Names() []string

Names returns the names including short names and aliases

func (*Command) Run

func (c *Command) Run(ctx *Context)

Run is the entry point to the command, parse argument and call Execute() or subcommand.Execute()

type Context

type Context struct {
	// contains filtered or unexported fields
}

Context is a type that is passed through to each Handler action in a cli application. Context can be used to retrieve context-specific Args and parsed command-line options.

func (*Context) Arg added in v1.4.6

func (c *Context) Arg(n int) string

Arg returns the i'th non-flag argument

func (*Context) Args

func (c *Context) Args() []string

Args returns the non-flag arguments.

func (*Context) GetBool

func (c *Context) GetBool(name string) bool

GetBool returns flag value as bool

func (*Context) GetFloat32

func (c *Context) GetFloat32(name string) float32

GetFloat32 returns flag value as float32

func (*Context) GetFloat64

func (c *Context) GetFloat64(name string) float64

GetFloat64 returns flag value as float64

func (*Context) GetInt

func (c *Context) GetInt(name string) int

GetInt returns flag value as int

func (*Context) GetInt16

func (c *Context) GetInt16(name string) int16

GetInt16 returns flag value as int16

func (*Context) GetInt32

func (c *Context) GetInt32(name string) int32

GetInt32 returns flag value as int32

func (*Context) GetInt64

func (c *Context) GetInt64(name string) int64

GetInt64 returns flag value as int64

func (*Context) GetInt8

func (c *Context) GetInt8(name string) int8

GetInt8 returns flag value as int8

func (*Context) GetString

func (c *Context) GetString(name string) string

GetString returns flag value as string

func (*Context) GetStringSlice

func (c *Context) GetStringSlice(name string) []string

GetStringSlice returns flag value as string slice

func (*Context) GetUint

func (c *Context) GetUint(name string) uint

GetUint returns flag value as uint

func (*Context) GetUint16

func (c *Context) GetUint16(name string) uint16

GetUint16 returns flag value as uint16

func (*Context) GetUint32

func (c *Context) GetUint32(name string) uint32

GetUint32 returns flag value as uint32

func (*Context) GetUint64

func (c *Context) GetUint64(name string) uint64

GetUint64 returns flag value as uint64

func (*Context) GetUint8

func (c *Context) GetUint8(name string) uint8

GetUint8 returns flag value as uint8

func (*Context) Global

func (c *Context) Global() *Context

Global returns top context if exists

func (*Context) IsSet

func (c *Context) IsSet(name string) bool

IsSet returns flag is visited in cli args

func (*Context) NArg

func (c *Context) NArg() int

NArg returns number of non-flag arguments

func (*Context) Name

func (c *Context) Name() string

Name returns app/command full name

func (*Context) Parent

func (c *Context) Parent() *Context

Parent returns parent context if exists

func (*Context) ShowError

func (c *Context) ShowError(err error)

ShowError shows error and exit(1)

func (*Context) ShowHelp

func (c *Context) ShowHelp()

ShowHelp shows help and

func (*Context) ShowHelpAndExit added in v1.4.6

func (c *Context) ShowHelpAndExit(code int)

ShowHelpAndExit shows help and exit

type Flag

type Flag struct {
	Name        string // name as it appears on command line
	Usage       string // help message
	Placeholder string // placeholder in usage
	Hidden      bool   // allow flags to be hidden from help/usage text

	IsBool        bool   // if the flag is bool value
	DefValue      string // default value (as text); for usage message
	NoOptDefValue string // default value (as text); if the flag is on the command line without any options
	EnvVar        string // default value load from environ

	Value interface{} // returns final value
	// contains filtered or unexported fields
}

Flag represents the state of a flag

func (*Flag) GetValue

func (f *Flag) GetValue() string

GetValue returns the string value of flag

func (*Flag) Names

func (f *Flag) Names() []string

Names returns the names including short names and aliases

func (*Flag) SetValue

func (f *Flag) SetValue(value string) error

SetValue sets the value of the named flag

type HelpContext

type HelpContext struct {
	Name        string
	Version     string
	Usage       string
	UsageText   string
	Description string
	Authors     string
	Examples    string
	SeeAlso     string
	Flags       []*Flag
	Commands    []*Command
}

HelpContext is a struct for output help

func (*HelpContext) AuthorLines

func (c *HelpContext) AuthorLines() []string

AuthorLines splits line for authors

func (*HelpContext) ExampleLines

func (c *HelpContext) ExampleLines() []string

ExampleLines splits line for examples

func (*HelpContext) Level

func (c *HelpContext) Level() int

Level return command/subcommand's level

func (*HelpContext) SeeAlsoLines

func (c *HelpContext) SeeAlsoLines() []string

SeeAlsoLines splits line for see also

func (*HelpContext) UsageTextLines

func (c *HelpContext) UsageTextLines() []string

UsageTextLines splits line for usage

func (*HelpContext) VisibleCommands

func (c *HelpContext) VisibleCommands() []*Command

VisibleCommands returns commands which are visible

func (*HelpContext) VisibleCommandsUsageLines

func (c *HelpContext) VisibleCommandsUsageLines() []string

VisibleCommandsUsageLines splits line for commands

func (*HelpContext) VisibleFlags

func (c *HelpContext) VisibleFlags() []*Flag

VisibleFlags returns flags which are visible

func (*HelpContext) VisibleFlagsUsageLines

func (c *HelpContext) VisibleFlagsUsageLines() []string

VisibleFlagsUsageLines splits line for flags

type Value

type Value interface {
	String() string
	Set(string) error
}

Value is the interface to the dynamic value stored in a flag. (The default value is represented as a string.)

Jump to

Keyboard shortcuts

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