- Lightweight and easy to use.
- Defines flag by tag, e.g. flag name(short or/and long), description, default value, password, prompt and so on.
- Type safety.
- Output looks very nice.
- Supports custom Validator.
- Supports slice and map as a flag.
- Supports any type as a flag field which implements cli.Decoder interface.
- Supports any type as a flag field which use FlagParser.
- Suggestions for command.(e.g.
hl
=>help
, "veron" => "version"). - Supports default value for flag, even expression about env variable(e.g.
dft:"$HOME/dev"
). - Supports editor like
git commit
command.(See example 21 and 22)
package main
import (
"github.com/mkideal/cli"
)
type argT struct {
cli.Helper
Name string `cli:"name" usage:"your name" dft:"world"`
Age uint8 `cli:"a,age" usage:"your age" dft:"100"`
}
func main() {
cli.Run(&argT{}, func(ctx *cli.Context) error {
argv := ctx.Argv().(*argT)
ctx.String("Hello, %s! Your age is %d?\n", argv.Name, argv.Age)
return nil
})
}
Type these in terminal
$> go build -o hello
$> ./hello
Hello, world! Your age is 100?
$> ./hello --name=clipher -a 9
Hello, clipher! Your age is 9?
$> ./hello -h
Try
$> ./hello -a 256
See godoc
See _examples, example_*test.go files or site below:
- Example 1: Hello world
- Example 2: How to use flag
- Example 3: How to use required flag
- Example 4: How to use default flag
- Example 5: How to use slice
- Example 6: How to use map
- Example 7: Usage of force flag
- Example 8: Usage of child command
- Example 9: Auto help
- Example 10: Usage of Validator
- Example 11: Prompt and Password
- Example 12: How to use Decoder
- Example 13: Builtin Decoder: PidFile
- Example 14: Builtin Decoder: Time and Duration
- Example 15: Builtin Decoder: File
- Example 16: Parser
- Example 17: Builtin Parser: JSONFileParser
- Example 18: How to use custom parser
- Example 19: How to use Hooks
- Example 20: How to use Daemon
- Example 21: How to use Editor
- Example 22: Custom Editor
- onepw - A lightweight tool for managing passwords
- rqlite CLI - A command line tool for connecting to a rqlited node
Supported tags in argument object of cli:
- cli - supports short format and long format, e,g,
-p
,--port
- pw - similar to
cli
, but used to input password - usage - description of flag
- dft - default value, supports constant value, env variable, and even expression
- name - placeholder for flag
- prompt - prompt string
- parser - builtin parsers:
json
,jsonfile
, supports custom parsers.
- All basic types: int,uint,...,flaot32,float64,string,bool
- Slice of basic type: []int, []uint, []string,...
- Map of basic type: map[uint]int, map[string]string,...
- Any type which implments
cli.Decoder
- Any type which use correct parser(
json
,jsonfile
, or your registered parser)
// AutoHelper represents interface for showing help information automaticly
AutoHelper interface {
AutoHelp() bool
}
If your argT
implments AutoHelper, it will show help if argT.AutoHelp return true.
For example:
package main
import "github.com/mkideal/cli"
type argT struct {
Help bool `cli:"h,help" usage:"show help"`
}
func (argv *argT) AutoHelp() bool {
return argv.Help
}
func main() {
cli.Run(&argT{}, func(ctx *cli.Context) error {
return nil
})
}
Build and run:
go build -o app
./app -h
This will print help information.
For convenience, builtin type cli.Helper
implements cli.AutoHelper.
So, you just need to inherit it!
type argT struct {
cli.Helper
}
// Validator validates flag before running command
type Validator interface {
Validate(*Context) error
}
Determin whether the flag is set
- OnRootPrepareError - Function of root command which should be invoked if occur error while prepare period
- OnBefore - Function which should be invoked before
Fn
- OnRootBefore - Function of root command which should be invoked before
Fn
- OnRootAfter - Function of root command which should be invoked after
Fn
- OnAfter - Function which should be invoked after
Fn
Invoked sequence: OnRootPrepareError => OnBefore => OnRootBefore => Fn => OnRootAfter => OnAfter
Don't invoke any hook function if NoHook
property of command is true, e.g.
var helpCmd = &cli.Command{
Name: "help",
Desc: "balabala...",
NoHook: true,
Fn: func(ctx *cli.Context) error { ... },
}
// Tree creates a CommandTree
func Tree(cmd *Command, forest ...*CommandTree) *CommandTree
// Root registers forest for root and return root
func Root(root *Command, forest ...*CommandTree) *Command
func log(ctx *cli.Context) error {
ctx.String("path: `%s`\n", ctx.Path())
return nil
}
var (
cmd1 = &cli.Command{Name: "cmd1", Fn: log}
cmd11 = &cli.Command{Name: "cmd11", Fn: log}
cmd12 = &cli.Command{Name: "cmd12", Fn: log}
cmd2 = &cli.Command{Name: "cmd2", Fn: log}
cmd21 = &cli.Command{Name: "cmd21", Fn: log}
cmd22 = &cli.Command{Name: "cmd22", Fn: log}
cmd221 = &cli.Command{Name: "cmd221", Fn: log}
cmd222 = &cli.Command{Name: "cmd222", Fn: log}
cmd223 = &cli.Command{Name: "cmd223", Fn: log}
)
root := cli.Root(
&cli.Command{Name: "tree"},
cli.Tree(cmd1,
cli.Tree(cmd11),
cli.Tree(cmd12),
),
cli.Tree(cmd2,
cli.Tree(cmd21),
cli.Tree(cmd22,
cli.Tree(cmd221),
cli.Tree(cmd222),
cli.Tree(cmd223),
),
),
)
Context implements ServeHTTP method.
func (ctx *Context) ServeHTTP(w http.ResponseWriter, r *http.Request)
Command
has two http properties: HTTPMethods
and HTTPRouters
.
HTTPRouters []string
HTTPMethods []string
Each command have one default router: slashes-separated router path of command. e.g.
$app sub1 sub11
has default router /sub1/sub11
. The HTTPRouters
property will add some new extra routers, it would'nt replace the default router. The HTTPMethods
is a string array. It will handle any method if HTTPMethods
is empty.
var help = &cli.Command{
Name: "help",
Desc: "display help",
CanSubRoute: true,
HTTPRouters: []string{"/v1/help", "/v2/help"},
HTTPMethods: []string{"GET", "POST"},
Fn: cli.HelpCommandFn,
}
NOTE: Must call root command's RegisterHTTP method if you want to use custom HTTPRouters
...
if err := ctx.Command().Root().RegisterHTTP(ctx); err != nil {
return err
}
return http.ListenAndServe(addr, ctx.Command().Root())
...