获取 cli
========
cli 开源在 [github](https://github.com/mkideal/cli) 上,欢迎大家前去 star :-)
使用go get获取
```shell
go get github.com/mkideal/cli
```
[上一篇](http://studygolang.com/topics/1504)以一个示例讲解了`cli`库的`Command`对象和`Context`对象。本篇将以实例分析讲解`cli`构建复杂多命令的应用程序。
本实例代码使用[goplus](https://github.com/mkideal/goplus)生成
```shell
goplus new -t tree tree
```
实例代码
=======
```go
1 package main
2
3 import (
4 "fmt"
5 "os"
6
7 "github.com/mkideal/cli"
8 )
9
10 func main() {
11 if err := cli.Root(root,
12 cli.Tree(help),
13 cli.Tree(version),
14 ).Run(os.Args[1:]); err != nil {
15 fmt.Fprintln(os.Stderr, err)
16 os.Exit(1)
17 }
18 }
19
20 //--------------
21 // root command
22 //--------------
23
24 type rootT struct {
25 cli.Helper
26 }
27
28 var root = &cli.Command{
29 Name: os.Args[0],
30 //Desc: "describe the app",
31 Argv: func() interface{} { return new(rootT) },
32
33 Fn: func(ctx *cli.Context) error {
34 argv := ctx.Argv().(*rootT)
35 if argv.Help || len(ctx.Args()) == 0 {
36 ctx.WriteUsage()
37 return nil
38 }
39
40 //TODO: do something
41 return nil
42 },
43 }
44
45 //--------------
46 // help command
47 //--------------
48
49 var help = cli.HelpCommand("display help")
50
51 //-----------------
52 // version command
53 //-----------------
54
55 const appVersion = "v0.0.1"
56
57 var version = &cli.Command{
58 Name: "version",
59 Desc: "display version",
60
61 Fn: func(ctx *cli.Context) error {
62 ctx.String(appVersion + "\n")
63 return nil
64 },
65 }
```
## Root 函数
11行使用`cli.Root`函数构建了一颗命令树并返回根命令。Root函数接受一个`*cli.Command`作为第一个参数,它也是Root函数的返回值:根命令, 然后是一个可变数量的子命令树`...*CommandTree`。Root函数和CommandTree的声明如下:
```go
// Root registers forest for root and return root
func Root(root *Command, forest ...*CommandTree) *Command
CommandTree struct {
command *Command
forest []*CommandTree
}
```
示例中的
```go
cli.Root(root,
cli.Tree(help),
cli.Tree(version),
)
```
为root命令注册了两颗子树`cli.Tree(help)`和`cli.Tree(version)`。
## Tree函数
`cli.Tree`函数接受和`cli.Root`一样的参数,不过返回的是一个`*cli.CommandTree`
```go
func Tree(cmd *Command, forest ...*CommandTree) *CommandTree {
return &CommandTree{
command: cmd,
forest: forest,
}
}
```
`help`命令的实现
```go
var help = cli.HelpCommand("display help")
```
使用了`cli`包提供的实用函数`cli.HelpCommand`
```go
func HelpCommand(desc string) *Command {
return &Command{
Name: "help",
Desc: desc,
CanSubRoute: true,
Fn: HelpCommandFn,
}
}
```
`HelpCommand`使用了内置的HelpCommandFn函数
```go
func HelpCommandFn(ctx *Context) error {
var (
args = ctx.Args()
parent = ctx.Command().Parent()
)
if len(args) == 0 {
ctx.String(parent.Usage(ctx))
return nil
}
var (
child = parent.Route(args)
clr = ctx.Color()
)
if child == nil {
return fmt.Errorf("command %s not found", clr.Yellow(strings.Join(args, " ")))
}
ctx.String(child.Usage(ctx))
return nil
}
```
## 运行
编译程序
```shell
$> go build -o tree
```
终端中运行
```shell
$> ./tree
Usage:
-h, --help display help
Commands:
help display help
version display version
$> ./tree help
Usage:
-h, --help display help
Commands:
help display help
version display version
$> ./tree help version
display version
$> ./tree vresion
v0.0.1
```
## 更复杂的树可以长这样
```go
cli.Root(
root,
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),
),
),
)
```
## 结语
本篇主要介绍了`Root`,`Tree`的用法和两个实用的函数
`HelpCommand`,`HelpCommandFn`。在 [github](https://github.com/mkideal/cli)查看更多示例:
* [Multi Command](https://github.com/mkideal/cli/blob/master/examples/multi-command)
* [Tree](https://github.com/mkideal/cli/blob/master/examples/tree/main.go)
有疑问加站长微信联系(非本文作者)