• golang 几个好用的cli package


    cli 开发在golang 的软件开发中占用很大,同时开源的比较好用的cli也很多,以下是整理的几个cli

    github.com/spf13/cobra

    这个比较有名了, 好多框架都使用了这个
    以下是一个简单的使用

    • 代码
    package main
    import (
     "github.com/spf13/cobra"
    )
    func main() {
     cmd := newCommand()
     cmd.AddCommand(newNestedCommand())
     rootCmd := &cobra.Command{}
     rootCmd.AddCommand(cmd)
     if err := rootCmd.Execute(); err != nil {
      println(err.Error())
     }
    }
    func newCommand() *cobra.Command {
     cmd := &cobra.Command{
      Run: func(cmd *cobra.Command, args []string) {
       println(`Foo`)
      },
      Use: `foo`,
      Short: "Command foo",
      Long: "This is a command",
     }
     return cmd
    }
    func newNestedCommand() *cobra.Command {
     cmd := &cobra.Command{
      Run: func(cmd *cobra.Command, args []string) {
       println(`Bar`)
      },
      Use: `bar`,
      Short: "Command bar",
      Long: "This is a nested command",
     }
     return cmd
    }
     
     
    • 效果
    go run main.go
    Usage:
       [command]
    Available Commands:
      foo Command foo
      help Help about any command
    Flags:
      -h, --help help for this command
    Use " [command] --help" for more information about a command.
     

    github.com/urfave/cli

    这个也比较有名,好多框架也使用了这个

    • 代码
    package main
    import (
     "log"
     "os"
     "sort"
     "github.com/urfave/cli"
    )
    func main() {
     app := cli.NewApp()
     app.Flags = []cli.Flag{
      cli.StringFlag{
       Name: "lang, l",
       Value: "english",
       Usage: "Language for the greeting",
      },
      cli.StringFlag{
       Name: "config, c",
       Usage: "Load configuration from `FILE`",
      },
     }
     app.Commands = []cli.Command{
      {
       Name: "complete",
       Aliases: []string{"c"},
       Usage: "complete a task on the list",
       Action: func(c *cli.Context) error {
        log.Print("ddd")
        return nil
       },
      },
      {
       Name: "add",
       Aliases: []string{"a"},
       Usage: "add a task to the list",
       Action: func(c *cli.Context) error {
        return nil
       },
      },
     }
     sort.Sort(cli.FlagsByName(app.Flags))
     sort.Sort(cli.CommandsByName(app.Commands))
     err := app.Run(os.Args)
     if err != nil {
      log.Fatal(err)
     }
    }
    • 运行效果
    go run cmd/cli/main.go 
    NAME:
       main - A new cli application
    USAGE:
       main [global options] command [command options] [arguments...]
    VERSION:
       0.0.0
    COMMANDS:
       add, a add a task to the list
       complete, c complete a task on the list
       help, h Shows a list of commands or help for one command
    GLOBAL OPTIONS:
       --config FILE, -c FILE Load configuration from FILE
       --lang value, -l value Language for the greeting (default: "english")
       --help, -h show help
       --version, -v print the version 

    github.com/google/subcommands

    • 代码
    package main
    import (
       "context"
       "flag"
       "fmt"
       "os"
       "strings"
       "github.com/google/subcommands"
    )
    type printCmd struct {
       capitalize bool
    }
    func (*printCmd) Name() string { return "print" }
    func (*printCmd) Synopsis() string { return "Print args to stdout." }
    func (*printCmd) Usage() string {
       return `print [-capitalize] <some text>:
       Print args to stdout.
      `
    }
    func (p *printCmd) SetFlags(f *flag.FlagSet) {
       f.BoolVar(&p.capitalize, "capitalize", false, "capitalize output")
    }
    func (p *printCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
       for _, arg := range f.Args() {
          if p.capitalize {
             arg = strings.ToUpper(arg)
          }
          fmt.Printf("%s ", arg)
       }
       fmt.Println()
       return subcommands.ExitSuccess
    }
    func main() {
       subcommands.Register(subcommands.HelpCommand(), "")
       subcommands.Register(subcommands.FlagsCommand(), "")
       subcommands.Register(subcommands.CommandsCommand(), "")
       subcommands.Register(&printCmd{}, "")
       flag.Parse()
       ctx := context.Background()
       os.Exit(int(subcommands.Execute(ctx)))
    }
     
     
    • 效果
    go run cmd/subcommands/main.go       
    Usage: main <flags> <subcommand> <subcommand args>
    Subcommands:
            commands list all command names
            flags describe all known top-level flags
            help describe subcommands and their syntax
            print Print args to stdout.
    Use "main flags" for a list of top-level flags
    exit status 2

    github.com/mitchellh/cli

    这个是hashicorp 好多产品使用的一个cli

    • 代码
    package main
    import (
       "fmt"
       "log"
       "os"
       "github.com/mitchellh/cli"
    )
    func fooCommandFactory() (cli.Command, error) {
       return new(FooCommand), nil
    }
    func barCommandFactory() (cli.Command, error) {
       return new(BarCommand), nil
    }
    // FooCommand fooCommand
    type FooCommand struct{}
    // Help should return long-form help text that includes the command-line
    // usage, a brief few sentences explaining the function of the command,
    // and the complete list of flags the command accepts.
    func (f *FooCommand) Help() string {
       return "help foo"
    }
    // Run should run the actual command with the given CLI instance and
    // command-line arguments. It should return the exit status when it is
    // finished.
    //
    // There are a handful of special exit codes this can return documented
    // above that change behavior.
    func (f *FooCommand) Run(args []string) int {
       fmt.Println("Foo Command is running")
       return 1
    }
    // Synopsis should return a one-line, short synopsis of the command.
    // This should be less than 50 characters ideally.
    func (f *FooCommand) Synopsis() string {
       return "foo command Synopsis"
    }
    // BarCommand barCommand
    type BarCommand struct{}
    // Help should return long-form help text that includes the command-line
    // usage, a brief few sentences explaining the function of the command,
    // and the complete list of flags the command accepts.
    func (b *BarCommand) Help() string {
       return "help bar"
    }
    // Run should run the actual command with the given CLI instance and
    // command-line arguments. It should return the exit status when it is
    // finished.
    //
    // There are a handful of special exit codes this can return documented
    // above that change behavior.
    func (b *BarCommand) Run(args []string) int {
       fmt.Println("bar Command is running")
       return 1
    }
    // Synopsis should return a one-line, short synopsis of the command.
    // This should be less than 50 characters ideally.
    func (b *BarCommand) Synopsis() string {
       return "bar command Synopsis"
    }
    func main() {
       c := cli.NewCLI("app", "1.0.0")
       c.Args = os.Args[1:]
       c.Commands = map[string]cli.CommandFactory{
          "foo": fooCommandFactory,
          "bar": barCommandFactory,
       }
       exitStatus, err := c.Run()
       if err != nil {
          log.Println(err)
       }
       os.Exit(exitStatus)
    } 
    • 运行效果
    go run cmd/hashicorp-cli/main.go       
    Usage: app [--version] [--help] <command> [<args>]
    Available commands are:
        bar bar command Synopsis
        foo foo command Synopsis

    github.com/alecthomas/kingpin

    这个cli pacakge 也是大家用的比较多的一个

    • 代码
    package main
    import (
       "fmt"
       "os"
       "gopkg.in/alecthomas/kingpin.v2"
    )
    func listHosts() []string {
       // Provide a dynamic list of hosts from a hosts file or otherwise
       // for bash completion. In this example we simply return static slice.
       // You could use this functionality to reach into a hosts file to provide
       // completion for a list of known hosts.
       return []string{"sshhost.example", "webhost.example", "ftphost.example"}
    }
    type NetcatCommand struct {
       hostName string
       port int
       format string
    }
    func (n *NetcatCommand) run(c *kingpin.ParseContext) error {
       fmt.Printf("Would have run netcat to hostname %v, port %d, and output format %v
    ", n.hostName, n.port, n.format)
       return nil
    }
    func configureNetcatCommand(app *kingpin.Application) {
       c := &NetcatCommand{}
       nc := app.Command("nc", "Connect to a Host").Action(c.run)
       nc.Flag("nop-flag", "Example of a flag with no options").Bool()
       // You can provide hint options using a function to generate them
       nc.Flag("host", "Provide a hostname to nc").
          Required().
          HintAction(listHosts).
          StringVar(&c.hostName)
       // You can provide hint options statically
       nc.Flag("port", "Provide a port to connect to").
          Required().
          HintOptions("80", "443", "8080").
          IntVar(&c.port)
       // Enum/EnumVar options will be turned into completion options automatically
       nc.Flag("format", "Define the output format").
          Default("raw").
          EnumVar(&c.format, "raw", "json")
       // You can combine HintOptions with HintAction too
       nc.Flag("host-with-multi", "Define a hostname").
          HintAction(listHosts).
          HintOptions("myhost.com").
          String()
       // And combine with themselves
       nc.Flag("host-with-multi-options", "Define a hostname").
          HintOptions("myhost.com").
          HintOptions("myhost2.com").
          String()
       // If you specify HintOptions/HintActions for Enum/EnumVar, the options
       // provided for Enum/EnumVar will be overridden.
       nc.Flag("format-with-override-1", "Define a format").
          HintAction(listHosts).
          Enum("option1", "option2")
       nc.Flag("format-with-override-2", "Define a format").
          HintOptions("myhost.com", "myhost2.com").
          Enum("option1", "option2")
    }
    func addSubCommand(app *kingpin.Application, name string, description string) {
       c := app.Command(name, description).Action(func(c *kingpin.ParseContext) error {
          fmt.Printf("Would have run command %s.
    ", name)
          return nil
       })
       c.Flag("nop-flag", "Example of a flag with no options").Bool()
    }
    func main() {
       app := kingpin.New("completion", "My application with bash completion.")
       app.Flag("flag-1", "").String()
       app.Flag("flag-2", "").HintOptions("opt1", "opt2").String()
       configureNetcatCommand(app)
       // Add some additional top level commands
       addSubCommand(app, "ls", "Additional top level command to show command completion")
       addSubCommand(app, "ping", "Additional top level command to show command completion")
       addSubCommand(app, "nmap", "Additional top level command to show command completion")
       kingpin.MustParse(app.Parse(os.Args[1:]))
    }
    • 运行效果
    go run cmd/kingpin/main.go 
    usage: completion [<flags>] <command> [<args> ...]
    My application with bash completion.
    Flags:
      --help Show context-sensitive help (also try --help-long and --help-man).
      --flag-1=FLAG-1  
      --flag-2=FLAG-2  
    Commands:
      help [<command>...]
        Show help.
      nc --host=HOST --port=PORT [<flags>]
        Connect to a Host
      ls [<flags>]
        Additional top level command to show command completion
      ping [<flags>]
        Additional top level command to show command completion
      nmap [<flags>]
        Additional top level command to show command completion

    说明

    以上是几个整理的cli,后期会继续完善

    参考资料

    https://github.com/google/subcommands
    https://github.com/urfave/cli
    https://github.com/mitchellh/cli
    https://github.com/alecthomas/kingpin
    http://github.com/spf13/cobra
    https://github.com/rongfengliang/cliapp

  • 相关阅读:
    10. 分离链接散列表
    9. avltree
    8.二叉查找树
    socket listen参数中的backlog 的意义!
    TCP 三次握手和四次挥手中的ACK 为什么总是SYN + 1 或者 FIN +1 而不是+ 其他数值?
    eclipse 快捷键
    内部类
    rabbitmq AmqpClient 使用Topic 交换机同一个channel 同时多个队列 ,多个交换机,C++代码示例
    rabbitMQ 问题
    rabbitmq AmqpClient 使用Topic 交换机投递与接收消息,C++代码示例
  • 原文地址:https://www.cnblogs.com/rongfengliang/p/11685336.html
Copyright © 2020-2023  润新知