• Stars
    star
    13
  • Rank 1,512,713 (Top 30 %)
  • Language
    Go
  • License
    Apache License 2.0
  • Created over 7 years ago
  • Updated almost 4 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A full-featured and easy to use command-line package

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/v3

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/v3"
)

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/v3"
)

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

More Repositories

1

jetbrick-template-2x

Template Engine for Java
Java
371
star
2

frep

Generate file using template from environment, arguments, json/yaml/toml config files
Go
154
star
3

javadoc.chm

This software generates an Microsoft HTML Help(CHM) from generic javadoc style API documents
Java
143
star
4

angular-async-loader

Load modules and components asynchronously for angular 1.x application.
JavaScript
136
star
5

jetbrick-template-1x

Java template engine, quickly and easily.
Java
68
star
6

go-xmldom

XML DOM processing for Golang, supports xpath query
Go
44
star
7

go-trylock

TryLock support on read-write lock for Golang
Go
33
star
8

jetbrick-webmvc

jetbrick web mvc framework
Java
25
star
9

centos-7-kickstart

build a centos 7 iso/ovf/ova with kickstart
Shell
21
star
10

jetbrick-commons

jetbrick utility classes
Java
21
star
11

go-log

Simple and configurable Logging in Go, with level, formatters and writers
Go
14
star
12

jetbrick-template-2x-samples

Samples for jetbrick-template-2x
Java
11
star
13

jetbrick-template-1x-samples

The samples for jetbrick-template integrated with webmvc
Java
9
star
14

jetbrick-ioc

IoC framwork for jetbrick
Java
7
star
15

jetbrick-webmvc-samples

Samples for jetbrick-webmvc
Java
6
star
16

go-stack

Common utility functions for Golang
Go
6
star
17

go-tableify

Pretty console printing of tabular data
Go
5
star
18

go-curl

A Go HTTP client library for creating and sending API requests
Go
5
star
19

jetbrick-orm

Object-relational mapping framework
Java
4
star
20

jetbrick-all-1x

A full-stack framework written with java
Java
4
star
21

gls

A goroutine-local storage for golang
Go
3
star
22

subchen.github.io

WebSite for subchen.github.com
HTML
3
star
23

ovfenv-installer

Configure networking from vSphere ovfEnv properties
Go
3
star
24

homebrew-tap

Tools of macOS Homebrew Packages
Ruby
2
star
25

snack

Generic functional library for javascript/node.js
JavaScript
2
star
26

snack-string

Generic string functional library for javascript/node.js
JavaScript
2
star
27

dev-box

A development box deployer, Support macOS, CentOS and Ubuntu.
Shell
2
star
28

shaft

Java simple database operation framework
Java
2
star
29

snack-cli

command-line interfaces for node.js
JavaScript
2
star
30

bintray-cli

Command line for api.bintray.com
1
star
31

jetbrick-template-shiro

Shiro tag extension for jetbrick-template
Java
1
star
32

jetbrick-website-app

website for http://subchen.github.io/
Java
1
star
33

jetbrick-extension

jetbrick extension modules
Java
1
star
34

jetbrick-jdbclog

jdbc logger for jetbrick
Java
1
star
35

jetbrick-ioc-spring

Spring intergrate for Jetbrick IoC
Java
1
star