CLI - A package for building command line app with go
hl => help, "veron" => "version").dft:"$HOME/dev").git commit command.(See example 21 and 22)See godoc
// main.go
// This is a HelloWorld-like example
package main
import (
"os"
"github.com/mkideal/cli"
)
type argT struct {
Name string `cli:"name" usage:"tell me your name"`
}
func main() {
os.Exit(cli.Run(new(argT), func(ctx *cli.Context) error {
argv := ctx.Argv().(*argT)
ctx.String("Hello, %s!\n", argv.Name)
return nil
}))
}$ go build -o hello
$ ./hello --name Clipher
Hello, Clipher!// main.go
// This example show basic usage of flag
package main
import (
"os"
"github.com/mkideal/cli"
)
type argT struct {
cli.Helper
Port int `cli:"p,port" usage:"short and long format flags both are supported"`
X bool `cli:"x" usage:"boolean type"`
Y bool `cli:"y" usage:"boolean type, too"`
}
func main() {
os.Exit(cli.Run(new(argT), func(ctx *cli.Context) error {
argv := ctx.Argv().(*argT)
ctx.String("port=%d, x=%v, y=%v\n", argv.Port, argv.X, argv.Y)
return nil
}))
}$ go build -o app
$ ./app -h
Options:
-h, --help display help information
-p, --port short and long format flags both are supported
-x boolean type
-y boolean type, too
$ ./app -p=8080 -x
port=8080, x=true, y=false
$ ./app -p 8080 -x=true
port=8080, x=true, y=false
$ ./app -p8080 -y true
port=8080, x=false, y=true
$ ./app --port=8080 -xy
port=8080, x=true, y=true
$ ./app --port 8080 -yx
port=8080, x=true, y=true// main.go
// This example show how to use required flag
package main
import (
"os"
"github.com/mkideal/cli"
)
type argT struct {
cli.Helper
Id uint8 `cli:"*id" usage:"this is a required flag, note the *"`
}
func main() {
os.Exit(cli.Run(new(argT), func(ctx *cli.Context) error {
argv := ctx.Argv().(*argT)
ctx.String("%d\n", argv.Id)
return nil
}))
}$ go build -o app
$ ./app
ERR! required argument --id missing
$ ./app --id=2
2…$ go build -o app
$ ./app -h
Options:
-h, --help display help information
--basic[=2] basic usage of default
--env[=$HOME] env variable as default
--expr[=$BASE_PORT+1000] expression as default
--devdir[=$HOME/dev] directory of developer
$ ./app
2, /Users/wang, 1000, /Users/wang/dev
$ BASE_PORT=8000 ./app --basic=3
3, /Users/wang, 9000, /Users/wang/dev// main.go
// This example show how to use slice as a flag
package main
import (
"os"
"github.com/mkideal/cli"
)
type argT struct {
// []bool, []int, []float32, ... supported too.
Friends []string `cli:"F" usage:"my friends"`
}
func main() {
os.Exit(cli.Run(new(argT), func(ctx *cli.Context) error {
ctx.JSONln(ctx.Argv())
return nil
}))
}$ go build -o app
$ ./app
{"Friends":null}
$ ./app -FAlice -FBob -F Charlie
{"Friends":["Alice","Bob","Charlie"]}// main.go
// This example show how to use map as a flag
package main
import (
"os"
"github.com/mkideal/cli"
)
type argT struct {
Macros map[string]int `cli:"D" usage:"define macros"`
}
func main() {
os.Exit(cli.Run(new(argT), func(ctx *cli.Context) error {
ctx.JSONln(ctx.Argv())
return nil
}))
}$ go build -o app
$ ./app
{"Macros":null}
$ ./app -Dx=not-a-number
ERR! `not-a-number` couldn't converted to an int value
$ ./app -Dx=1 -D y=2
{"Macros":{"x":1,"y":2}}// main.go
// This example show usage of force flag
// Force flag has prefix !, and must be a boolean.
// Will prevent validating flags if some force flag assigned true
package main
import (
"os"
"github.com/mkideal/cli"
)
type argT struct {
Version bool `cli:"!v" usage:"force flag, note the !"`
Required int `cli:"*r" usage:"required flag"`
}
func main() {
os.Exit(cli.Run(new(argT), func(ctx *cli.Context) error {
argv := ctx.Argv().(*argT)
if argv.Version {
ctx.String("v0.0.1\n")
}
return nil
}))
}$ go build -o app
$ ./app
ERR! required argument -r missing
# -v is a force flag, and assigned true, so `ERR` disappear.
$ ./app -v
v0.0.1……// main.go
// This example demonstrates cli.AutoHelper
package main
import (
"os"
"github.com/mkideal/cli"
)
type argT struct {
Help bool `cli:"h,help" usage:"show help"`
}
// AutoHelp implements cli.AutoHelper interface
// NOTE: cli.Helper is a predefined type which implements cli.AutoHelper
func (argv *argT) AutoHelp() bool {
return argv.Help
}
func main() {
os.Exit(cli.Run(new(argT), func(ctx *cli.Context) error {
return nil
}))
}$ go build -o app
$ ./app -h
Options:
-h, --help show helpTry comment AutoHelp method and rerun it.
…$ go build -o app
$ ./app --age=-1
ERR! age -1 out of range
$ ./app --age=1000
ERR! age 1000 out of range
$ ./app -g balabala
ERR! invalid gender balabala
$ ./app --age 88 --gender female
{"Help":false,"Age":88,"Gender":"female"}// main.go
// This example introduce prompt and pw tag
package main
import (
"os"
"github.com/mkideal/cli"
)
type argT struct {
cli.Helper
Username string `cli:"u,username" usage:"github account" prompt:"type github account"`
Password string `pw:"p,password" usage:"password of github account" prompt:"type the password"`
}
func main() {
os.Exit(cli.Run(new(argT), func(ctx *cli.Context) error {
argv := ctx.Argv().(*argT)
ctx.String("username=%s, password=%s\n", argv.Username, argv.Password)
return nil
}))
}$ go build -o app
$ ./app
type github account: hahaha # visible
type the password: # invisible because of `pw` tag
username=hahaha, password=123456// main.go
// This example show how to use decoder
package main
import (
"os"
"strings"
"github.com/mkideal/cli"
)
type exampleDecoder struct {
list []string
}
// Decode implements cli.Decoder interface
func (d *exampleDecoder) Decode(s string) error {
d.list = strings.Split(s, ",")
return nil
}
type argT struct {
Example exampleDecoder `cli:"d" usage:"example decoder"`
}
func main() {
os.Exit(cli.Run(new(argT), func(ctx *cli.Context) error {
argv := ctx.Argv().(*argT)
ctx.JSONln(argv.Example.list)
return nil
}))
}$ go build -o app
$ ./app -d a,b,c
["a","b","c"]// main.go
// This example show how to use builtin Decoder: PidFile
package main
import (
"os"
"github.com/mkideal/cli"
clix "github.com/mkideal/cli/ext"
)
type argT struct {
cli.Helper
PidFile clix.PidFile `cli:"pid" usage:"pid file" dft:"013-pidfile.pid"`
}
func main() {
os.Exit(cli.Run(new(argT), func(ctx *cli.Context) error {
argv := ctx.Argv().(*argT)
if err := argv.PidFile.New(); err != nil {
return err
}
defer argv.PidFile.Remove()
return nil
}))
}// main.go
// This example show how to use builtin Decoder: Time and Duration
package main
import (
"os"
"github.com/mkideal/cli"
clix "github.com/mkideal/cli/ext"
)
type argT struct {
Time clix.Time `cli:"t" usage:"time"`
Duration clix.Duration `cli:"d" usage:"duration"`
}
func main() {
os.Exit(cli.Run(new(argT), func(ctx *cli.Context) error {
argv := ctx.Argv().(*argT)
ctx.String("time=%v, duration=%v\n", argv.Time, argv.Duration)
return nil
}))
}$ go build -o app
$ ./app -t '2016-1-2 3:5' -d=10ms
time=2016-01-02 03:05:00 +0800 CST, duration=10ms// main.go
// This example show how to use builtin Decoder: File
package main
import (
"os"
"github.com/mkideal/cli"
clix "github.com/mkideal/cli/ext"
)
type argT struct {
Content clix.File `cli:"f,file" usage:"read content from file or stdin"`
}
func main() {
os.Exit(cli.Run(new(argT), func(ctx *cli.Context) error {
argv := ctx.Argv().(*argT)
ctx.String(argv.Content.String())
return nil
}))
}$ go build -o app
# read from stdin
$ echo hello | ./app -f
hello
# read from file
$ echo hello > test.txt && ./app -f test.txt
hello
$ rm test.txt…$ go build -o app
$ ./app
{
"A": "",
"B": 0,
"C": false
}
$ ./app -c '{"A": "hello", "b": 22, "C": true}'
{
"A": "hello",
"B": 22,
"C": true
}// main.go
// This example show how to use builtin parser: jsonfile
// It's similar to json, but read string from file.
package main
import (
"os"
"github.com/mkideal/cli"
)
type config struct {
A string
B int
C bool
}
typNo open issues yet, or sync has not completed.