Golang实践录:命令行cobra库实例再三优化

本文是上一文章《Golang实践录:命令行cobra库实例优化》 的优化,主要的子命令的业务实现的整理。

起因

上一版本实现的方式,还是有点不满意,格式也不对齐,重要的是,似乎不是正规的方式。

思路

cobra官方支持多级子命令,经研究测试发现,在实现三级子命令时,稍有麻烦。故舍弃官方的做法。同时参考了部分示例代码,结合得到本文的案例。

实现

旧版本如下:

var theCmd = []conf.UserCmdFunc{
    conf.UserCmdFunc {
        Name: "foo",
        ShortHelp: "just a foo help info",
        Func: foo,
    },
    conf.UserCmdFunc {"watch", "watch config file", testWatch,},
}

func NewCmdTest() *cobra.Command{

    var cmd = &cobra.Command{
        Use:     name,
        Short:   shortDescription,
        Long:    longDescription,
        Example: example,
        RunE: func(cmd *cobra.Command, args []string) error {
			//klog.Println(common.DBName)
			if (len(args) == 0) {
				klog.Warning("no args found")
				common.PrintHelpInfo(theCmd)
				return nil
			}
            // !! 遍历并调用即可
			for _, item:=range theCmd {
				if (args[0] == item.Name) {
					item.Func(args)
					return nil
				}
			}
			klog.Printf("cmd '%v' not support", args[0])
			common.PrintHelpInfo(theCmd)
            return nil
        },
    }
    // note:使用子命令形式,下列可在help中展开
    // 命令参数,保存的值,参数名,默认参数,说明
    //cmd.Flags().StringVar(&mode, "db", "-", "set the database name")

    return cmd
}

新版本修改如下:

根据命令参数长度补齐:

// rpad adds padding to the right of a string.
func rpad(s string, padding int) string {
	template := fmt.Sprintf("%%-%ds", padding)
	return fmt.Sprintf(template, s)
}

func GetHelpInfo(theCmd []conf.UserCmdFunc) (ret string) {
	ret = fmt.Sprintf("Available Commands:\n");

	for _, item := range theCmd {
		nameLen := len(item.Name)
		if nameLen > cmdMaxLen {
			cmdMaxLen = nameLen
		}
	}
	
	for _, item := range theCmd {
		ret += fmt.Sprintf("  %v %v\n", rpad(item.Name, cmdMaxLen), item.ShortHelp)
	}
	
	return
}

子命令实现:


var mode int

func NewCmdTest() *cobra.Command{

    var cmd = &cobra.Command{
        Use:     name,
        Short:   shortDescription,
        Long:    longDescription + "\n" + common.GetHelpInfo(theCmd),
        Example: example,
        RunE: func(cmd *cobra.Command, args []string) error {
			// 1 没有参数
			if (len(args) == 0) {
				//klog.Warning("no args found")
				//common.PrintHelpInfo(theCmd)
				cmd.Help()
				return nil
			}

			// 2 遍历是否有合法的参数,如无则提示
			idx := -1
			for idx1, item := range theCmd {
				if (args[0] == item.Name) {
					idx = idx1 // why ???
					break
				}
			}
			if idx == -1 {
				klog.Printf("arg '%v' not support", args[0])
				cmd.Help()
				return nil
			}
			
			// 3 执行公共的初始化
			klog.Printf("bussiness init, mode: %v\n", mode) // just test

			// 4 执行命令
			theCmd[idx].Func(args)

			return nil
        },
    }
    // note:使用子命令形式,下列可在help中展开
    // 命令参数,保存的值,参数名,默认参数,说明
	cmd.Flags().IntVarP(&mode, "mode", "m", 0, "set the test mode")

    return cmd
}

修改1:将自定义的帮助信息纳入到Long字段,利用默认的cmd.Help()输出信息(要添加自定义的部分信息)。
修改2:先遍历自定义的命令列表,没有时提示帮助信息,有则执行。

测试

默认输出帮助信息:

$ ./cmdtool.exe
  cmd test tool.
  【中文样例】命令终端测试示例工具。

Usage:
  cmdtool.exe [command]

Examples:
  comming soon...


Available Commands:
  db          db command
  help        Help about any command
  misc        misc command
  test        test command

Flags:
  -c, --config string   config file (config.yaml)
  -h, --help            help for cmdtool.exe
  -o, --output string   specify the output file name
  -p, --print           verbose output
      --version         version for cmdtool.exe

Use "cmdtool.exe [command] --help" for more information about a command.

执行子命令,默认将合法的命令输出:

$ ./cmdtool.exe test
[2020-12-11 14:51:24.009 rootCmd.go:115] helloooooo 100s firstblood
test...

Available Commands:
  foo   just a foo help info
  watch watch config file

Usage:
  cmdtool.exe test [flags]

Examples:
  example comming up...


Flags:
  -h, --help       help for test
  -m, --mode int   set the test mode

Global Flags:
  -c, --config string   config file (config.yaml)
  -o, --output string   specify the output file name
  -p, --print           verbose output


$ ./cmdtool.exe test nocmd
[2020-12-11 14:53:13.301 rootCmd.go:115] helloooooo 100s firstblood
[2020-12-11 14:53:13.303 cmd.go:60] arg 'nocmd' not support
test...

Available Commands:
  foo   just a foo help info
  watch watch config file

Usage:
  cmdtool.exe test [flags]

Examples:
  example comming up...


Flags:
  -h, --help       help for test
  -m, --mode int   set the test mode

Global Flags:
  -c, --config string   config file (config.yaml)
  -o, --output string   specify the output file name
  -p, --print           verbose output

源码

源码在此

相关推荐
©️2020 CSDN 皮肤主题: 技术工厂 设计师:CSDN官方博客 返回首页