cli

package
v0.1.10 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 9, 2025 License: MIT Imports: 5 Imported by: 2

README

cli —— 轻量级命令行工具集合(基于标准库 flag)

cli 包是对 Go 标准库 flag 的薄封装,提供更友好的子命令组织、嵌套解析与帮助信息输出。适合快速构建多层级命令行工具,同时保持零第三方依赖、可读性强的代码风格。


安装

go get github.com/Rehtt/Kit/cli

在代码中:

import "github.com/Rehtt/Kit/cli"

快速上手

package main

import (
    "flag"
    "fmt"
    "os"

    kitcli "github.com/Rehtt/Kit/cli"
)

func main() {
    // 根命令
    root := kitcli.NewCLI("app", "示例应用", flag.ContinueOnError)
    var verbose bool
    root.BoolVar(&verbose, "v", false, "开启详细输出")

    // 子命令:hello
    hello := kitcli.NewCLI("hello", "打印问候语", flag.ContinueOnError)
    name := hello.String("name", "world", "名字")
    hello.CommandFunc = func(args []string)error {
        if verbose {
            fmt.Println("verbose on")
        }
        fmt.Printf("Hello, %s\n", *name)
        return nil
    }

    // 二级子命令:user add
    user := kitcli.NewCLI("user", "用户操作", flag.ContinueOnError)
    add := kitcli.NewCLI("add", "添加用户", flag.ContinueOnError)
    uname := add.String("name", "", "用户名")
    add.CommandFunc = func(args []string)error {
        fmt.Println("add", *uname)
    }
    _ = user.AddCommand(add)

    // 绑定子命令到根命令
    _ = root.AddCommand(hello, user)

    // 解析命令
    if err := root.Parse(os.Args[1:]); err != nil {
        // 根据 errorHandling 决定行为;这里选择自行处理
        os.Exit(2)
    }
    return nil
}

运行体验(示例):

$ app -h
Usage of app:
  -v    开启详细输出

Subcommands:
  hello  打印问候语
  user   用户操作

$ app hello -h
Usage of hello:
  -name string
        名字 (default "world")

$ app hello -v -name Alice
verbose on
Hello, Alice

$ app user add -name Bob
add Bob

核心概念与 API

  • CLI 结构体:表示一个命令。字段含义:

    • Use: 命令名(如 hellouser
    • Instruction: 简要说明(用于帮助信息)
    • CommandFunc: 命令执行函数,签名为 func(args []string)
    • FlagSet: 该命令的 *flag.FlagSet,用于定义与解析参数
    • SubCommands: 子命令映射(map[string]*CLI
  • 构造函数

    • NewCLI(use, instruction string, errorHandling flag.ErrorHandling) *CLI
      • errorHandling 透传给 flag.NewFlagSet,常用值:
        • flag.ContinueOnError: 出错返回错误,便于外层处理
        • flag.ExitOnError: 出错直接退出程序
  • 方法

    • AddCommand(cli ...*CLI) error: 挂载一个或多个子命令,命名重复会报错
    • Help(): 打印当前命令的帮助与子命令列表
    • Parse(arguments []string) error: 解析参数;若存在子命令并检测到首个非 flag 参数为子命令名,则递归解析对应子命令

行为细节:

  • Parse 内部会将 c.FlagSet.Usage 指向 c.Help,因此 -h/--help 会打印包含子命令的帮助信息。
  • 当存在子命令且第一个位置参数匹配子命令时,会递归进入子命令解析。
  • 未匹配到子命令、或未设置 Func 时会打印帮助信息并返回 nil
  • Help 使用 FlagSet.Output()io.Writer 输出;可通过 FlagSet.SetOutput(w) 重定向到自定义 writer。

默认实例与包装 API

本包提供一个默认的全局实例 cli.CommandLine 及其包装函数,便于快速开发简单工具:

package main

import (
    "flag"
    "fmt"
    "os"

    cli "github.com/Rehtt/Kit/cli"
)

func main() {
    // 根级 flag(对所有命令生效)
    verbose := cli.Bool("v", false, "开启详细输出")

    // 定义一个子命令并绑定其专属 flag
    hello := cli.NewCLI("hello", "打印问候语", flag.ContinueOnError)
    name := hello.String("name", "world", "名字")
    hello.CommandFunc = func(args []string)return {
        if *verbose { fmt.Println("verbose on") }
        fmt.Printf("Hello, %s\n", *name)
        return nil
    }
    _ = cli.AddCommand(hello)

    if err := cli.Parse(); err != nil { os.Exit(2) }
}

包装函数速览(均作用于 cli.CommandLine):

  • Parse() errorParsed() boolArgs() []stringNArg() int
  • 标准类型:BoolVar/BoolStringVar/StringIntVar/IntInt64Var/Int64UintVar/UintUint64Var/Uint64Float64Var/Float64DurationVar/Duration
  • 自定义类型:TextVar(p encoding.TextUnmarshaler, name string, value encoding.TextMarshaler, usage string)Var(p flag.Value, name, usage string)
  • 自定义解析回调:Func(name, usage string, fn func(string) error)BoolFunc(name, usage string, fn func(string) error)
  • 访问与遍历:VisitAll(fn)Visit(fn)Lookup(name)Set(name, value)

注意:根级定义的 flag(通过包装函数定义)适用于所有命令;子命令私有的 flag 应在对应的 *CLI 上定义。


使用建议(Best Practices)

  • 选择合适的 error handling
    • 推荐根命令使用 flag.ContinueOnError,让错误以返回值形式暴露,便于统一处理与测试。
  • 按层定义各自的 Flag
    • 每个命令有独立的 FlagSet,避免不同层级的 flag 混淆。
  • 稳定输出
    • 如需稳定的子命令显示顺序,可在调用 AddCommand 前对切片排序,或在 Help 中对 SubCommands 的键排序后输出。

常见问题(FAQ)

  • 如何实现命令别名?
    • 目前 SubCommands 使用 map,键即命令名。可手动插入多个键映射到同一 *CLI 以实现别名。
  • 如何让父命令的 flag 影响子命令?
    • 在父命令的变量中保存状态(如 verbose),子命令执行时按需读取(示例见上)。
  • 未知子命令是否会返回错误?
    • 当前实现会打印帮助并返回 nil。如需报错,可在外层检查 c.Arg(0) 或自行扩展 Parse 行为。

代码改进建议(基于当前实现)

  • 帮助输出顺序SubCommands 为 map,Help 中遍历无序。建议在输出前对键排序,或改为切片存储以保证稳定顺序。
  • 错误传递能力CommandFunc 无返回值,无法向外传递错误。可新增 FuncE func(args []string) error 或在 Parse 中统一调用错误处理回调。
  • 未知子命令的返回值:当前返回 nil,调用方难以区分“正常展示帮助”与“输入错误”。建议在未知子命令时返回可识别的错误值。

许可协议

本包遵循仓库根目录的许可协议,详见 LICENSE

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AddCommand

func AddCommand(cli ...*CLI) error

func Args

func Args() []string

Args 返回非 flag 参数(使用默认 CommandLine 实例)

func Bool

func Bool(name string, value bool, usage string) *bool

Bool 定义并返回一个 bool 类型 flag 指针(使用默认 CommandLine 实例)

func BoolFunc

func BoolFunc(name, usage string, fn func(string) error)

BoolFunc 定义一个自定义处理函数的 bool flag(使用默认 CommandLine 实例)

func BoolVar

func BoolVar(p *bool, name string, value bool, usage string)

BoolVar 定义一个 bool 类型 flag(使用默认 CommandLine 实例)

func Duration

func Duration(name string, value time.Duration, usage string) *time.Duration

Duration 定义并返回一个 time.Duration 类型 flag 指针(使用默认 CommandLine 实例)

func DurationVar

func DurationVar(p *time.Duration, name string, value time.Duration, usage string)

DurationVar 定义一个 time.Duration 类型 flag(使用默认 CommandLine 实例)

func Float64

func Float64(name string, value float64, usage string) *float64

Float64 定义并返回一个 float64 类型 flag 指针(使用默认 CommandLine 实例)

func Float64Var

func Float64Var(p *float64, name string, value float64, usage string)

Float64Var 定义一个 float64 类型 flag(使用默认 CommandLine 实例)

func Func

func Func(name, usage string, fn func(string) error)

Func 定义一个自定义处理函数的 flag(使用默认 CommandLine 实例)

func Int

func Int(name string, value int, usage string) *int

Int 定义并返回一个 int 类型 flag 指针(使用默认 CommandLine 实例)

func Int64

func Int64(name string, value int64, usage string) *int64

Int64 定义并返回一个 int64 类型 flag 指针(使用默认 CommandLine 实例)

func Int64Var

func Int64Var(p *int64, name string, value int64, usage string)

Int64Var 定义一个 int64 类型 flag(使用默认 CommandLine 实例)

func IntVar

func IntVar(p *int, name string, value int, usage string)

IntVar 定义一个 int 类型 flag(使用默认 CommandLine 实例)

func Lookup

func Lookup(name string) *flag.Flag

Lookup 返回指定名称的 flag 指针,若不存在则返回 nil

func NArg

func NArg() int

NArg 返回非 flag 参数的数量(使用默认 CommandLine 实例)

func Parse

func Parse() error

Parse 解析命令行参数(使用默认 CommandLine 实例)

func Parsed

func Parsed() bool

Parsed 判断命令行参数是否已被解析

func Run

func Run() error

Run 执行命令行参数(使用默认 CommandLine 实例)

func Set

func Set(name, value string) error

Set 设置指定名称 flag 的值

func String

func String(name string, value string, usage string) *string

String 定义并返回一个 string 类型 flag 指针(使用默认 CommandLine 实例)

func StringVar

func StringVar(p *string, name string, value string, usage string)

StringVar 定义一个 string 类型 flag(使用默认 CommandLine 实例)

func TextVar

func TextVar(p encoding.TextUnmarshaler, name string, value encoding.TextMarshaler, usage string)

TextVar 定义一个实现 encoding.TextUnmarshaler 的 flag(使用默认 CommandLine 实例)

func Uint

func Uint(name string, value uint, usage string) *uint

Uint 定义并返回一个 uint 类型 flag 指针(使用默认 CommandLine 实例)

func Uint64

func Uint64(name string, value uint64, usage string) *uint64

Uint64 定义并返回一个 uint64 类型 flag 指针(使用默认 CommandLine 实例)

func Uint64Var

func Uint64Var(p *uint64, name string, value uint64, usage string)

Uint64Var 定义一个 uint64 类型 flag(使用默认 CommandLine 实例)

func UintVar

func UintVar(p *uint, name string, value uint, usage string)

UintVar 定义一个 uint 类型 flag(使用默认 CommandLine 实例)

func Var

func Var(p flag.Value, name string, usage string)

Var 定义一个自定义 flag.Value 的 flag(使用默认 CommandLine 实例)

func Visit

func Visit(fn func(*flag.Flag))

Visit 按字典序遍历已设置的 flag,调用 fn

func VisitAll

func VisitAll(fn func(*flag.Flag))

VisitAll 按字典序遍历所有 flag,调用 fn(包括未设置的 flag)

Types

type CLI

type CLI struct {
	Use         string
	Instruction string
	CommandFunc CommandFunc
	*flag.FlagSet
	SubCommands map[string]*CLI
}
var CommandLine *CLI

func NewCLI

func NewCLI(use, instruction string, errorHandling flag.ErrorHandling) *CLI

func (*CLI) AddCommand

func (c *CLI) AddCommand(cli ...*CLI) error

func (*CLI) Help

func (c *CLI) Help()

func (*CLI) Parse

func (c *CLI) Parse(arguments []string) error

func (*CLI) Run

func (c *CLI) Run(arguments []string) error

Parse 别名

type CommandFunc

type CommandFunc func(args []string) error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL