GitHub - gookit/gcli: 🖥 Go CLI application, tool library, running CLI commands, support console color, user interaction, progress display, data formatting display, generate bash/zsh completion add more features. Go的命令行应用,工具库,运行CLI命令,支持命令行色彩,用户交互,进度显示,数据格式化显示,生成bash/zsh命令补全脚本 (original) (raw)

GCli

GitHub go.mod Go version Actions Status GitHub tag (latest SemVer) Codacy Badge Go Reference Go Report Card Coverage Status

A simple and easy-to-use command-line application and tool library written in Golang. Including running commands, color styles, data display, progress display, interactive methods, etc.

中文说明

中文说明请看 README.zh-CN

Screenshots

app-cmd-list

Features

Flag Options:

Flag Arguments:

GoDoc

Install

go get github.com/gookit/gcli/v3

Quick start

an example for quick start:

package main

import ( "github.com/gookit/gcli/v3" "github.com/gookit/gcli/v3/_examples/cmd" )

// for test run: go build ./_examples/cliapp.go && ./cliapp func main() { app := gcli.NewApp() app.Version = "1.0.3" app.Desc = "this is my cli application" // app.SetVerbose(gcli.VerbDebug)

app.Add(cmd.Example)
app.Add(&gcli.Command{
    Name: "demo",
    // allow color tag and {$cmd} will be replace to 'demo'
    Desc: "this is a description <info>message</> for {$cmd}", 
    Subs: []*gcli.Command {
        // ... allow add subcommands
    },
    Aliases: []string{"dm"},
    Func: func (cmd *gcli.Command, args []string) error {
        gcli.Print("hello, in the demo command\n")
        return nil
    },
})

// .... add more ...

app.Run(nil)

}

Binding flags

flags binding and manage by builtin gflag.go, allow binding flag options and arguments.

Bind options

gcli support multi method to binding flag options.

Use flag methods

Available methods:

BoolOpt(p *bool, name, shorts string, defValue bool, desc string) BoolVar(p *bool, meta FlagMeta) Float64Opt(p *float64, name, shorts string, defValue float64, desc string) Float64Var(p *float64, meta FlagMeta) Int64Opt(p *int64, name, shorts string, defValue int64, desc string) Int64Var(p *int64, meta FlagMeta) IntOpt(p *int, name, shorts string, defValue int, desc string) IntVar(p *int, meta FlagMeta) StrOpt(p *string, name, shorts, defValue, desc string) StrVar(p *string, meta FlagMeta) Uint64Opt(p *uint64, name, shorts string, defValue uint64, desc string) Uint64Var(p *uint64, meta FlagMeta) UintOpt(p *uint, name, shorts string, defValue uint, desc string) UintVar(p *uint, meta FlagMeta) Var(p flag.Value, meta FlagMeta) VarOpt(p flag.Value, name, shorts, desc string)

Usage examples:

var id int var b bool var opt, dir string var f1 float64 var names gcli.Strings

// bind options cmd.IntOpt(&id, "id", "", 2, "the id option") cmd.BoolOpt(&b, "bl", "b", false, "the bool option") // notice DIRECTORY will replace to option value type cmd.StrOpt(&dir, "dir", "d", "", "the DIRECTORY option") // setting option name and short-option name cmd.StrOpt(&opt, "opt", "o", "", "the option message") // setting a special option var, it must implement the flag.Value interface cmd.VarOpt(&names, "names", "n", "the option message")

Use struct tags

package main

import ( "github.com/gookit/gcli/v3" )

type userOpts struct { Int int flag:"name=int0;shorts=i;required=true;desc=int option message" Bol bool flag:"name=bol;shorts=b;desc=bool option message" Str1 string flag:"name=str1;shorts=o;required=true;desc=str1 message" // use ptr Str2 *string flag:"name=str2;required=true;desc=str2 message" // custom type and implement flag.Value Verb0 gcli.VerbLevel flag:"name=verb0;shorts=v0;desc=verb0 message" // use ptr Verb1 *gcli.VerbLevel flag:"name=verb1;desc=verb1 message" }

// run: go run ./_examples/issues/iss157.go func main() { astr := "xyz" verb := gcli.VerbWarn

cmd := gcli.NewCommand("test", "desc")
cmd.Config = func(c *gcli.Command) {
    c.MustFromStruct(&userOpts{
        Str2:  &astr,
        Verb1: &verb,
    })
}

// disable auto bind global options: verbose,version, progress...
gcli.GOpts().SetDisable()

// direct run
if err := cmd.Run(nil); err != nil {
    colorp.Errorln( err)
}

}

Bind arguments

About arguments:

Available methods:

Add(arg Argument) *Argument AddArg(name, desc string, requiredAndArrayed ...bool) *Argument AddArgByRule(name, rule string) *Argument AddArgument(arg *Argument) *Argument BindArg(arg Argument) *Argument

Usage examples:

cmd.AddArg("arg0", "the first argument, is required", true) cmd.AddArg("arg1", "the second argument, is required", true) cmd.AddArg("arg2", "the optional argument, is optional") cmd.AddArg("arrArg", "the array argument, is array", false, true)

can also use Arg()/BindArg() add a gcli.Argument object:

cmd.Arg("arg0", gcli.Argument{ Name: "ag0", Desc: "the first argument, is required", Require: true, }) cmd.BindArg("arg2", gcli.Argument{ Name: "ag0", Desc: "the third argument, is is optional", }) cmd.BindArg("arrArg", gcli.Argument{ Name: "arrArg", Desc: "the third argument, is is array", Arrayed: true, })

use AddArgByRule:

cmd.AddArgByRule("arg2", "add an arg by string rule;required;23")

New application

app := gcli.NewApp() app.Version = "1.0.3" app.Desc = "this is my cli application" // app.SetVerbose(gcli.VerbDebug)

Add commands

app.Add(cmd.Example) app.Add(&gcli.Command{ Name: "demo", // allow color tag and {$cmd} will be replace to 'demo' Desc: "this is a description message</> for {$cmd}", Subs: []*gcli.Command { // level1: sub commands... { Name: "remote", Desc: "remote command for git", Aliases: []string{"rmt"}, Func: func(c *gcli.Command, args []string) error { dump.Println(c.Path()) return nil }, Subs: []*gcli.Command{ // level2: sub commands... // {} } }, // ... allow add subcommands }, Aliases: []string{"dm"}, Func: func (cmd *gcli.Command, args []string) error { gcli.Print("hello, in the demo command\n") return nil }, })

Run application

Build the example application as demo

$ go build ./_examples/cliapp

Display version

$ ./cliapp --version

or use -V

$ ./cliapp -V

app-version

Display app help

by ./cliapp or ./cliapp -h or ./cliapp --help

Examples:

./cliapp ./cliapp -h # can also ./cliapp --help # can also

cmd-list

Run command

Format:

./cliapp COMMAND [--OPTION VALUE -S VALUE ...] [ARGUMENT0 ARGUMENT1 ...] ./cliapp COMMAND [--OPTION VALUE -S VALUE ...] SUBCOMMAND [--OPTION ...] [ARGUMENT0 ARGUMENT1 ...]

Run example:

$ ./cliapp example -c some.txt -d ./dir --id 34 -n tom -n john val0 val1 val2 arrVal0 arrVal1 arrVal2

You can see:

run-example

Display command help

by ./cliapp example -h or ./cliapp example --help

cmd-help

Error command tips

command tips

Generate Auto Completion Scripts

import "github.com/gookit/gcli/v3/builtin"

// ...
// add gen command(gen successful you can remove it)
app.Add(builtin.GenAutoComplete())

Build and run command(This command can be deleted after success.):

$ go build ./_examples/cliapp.go && ./cliapp genac -h // display help $ go build ./_examples/cliapp.go && ./cliapp genac // run gen command

will see:

INFO: 
  {shell:zsh binName:cliapp output:auto-completion.zsh}

Now, will write content to file auto-completion.zsh
Continue? [yes|no](default yes): y

OK, auto-complete file generate successful

After running, it will generate an auto-completion.{zsh|bash} file in the current directory, and the shell environment name is automatically obtained. Of course, you can specify it manually at runtime

Generated shell script file ref:

Preview:

auto-complete-tips

Write a command

command allow setting fields:

Quick create

var MyCmd = &gcli.Command{ Name: "demo", // allow color tag and {$cmd} will be replace to 'demo' Desc: "this is a description message</> for command {$cmd}", Aliases: []string{"dm"}, Func: func (cmd *gcli.Command, args []string) error { gcli.Print("hello, in the demo command\n") return nil }, // allow add multi level subcommands Subs: []*gcli.Command{}, }

Write go file

the source file at: example.go

package main

import ( "fmt"

"github.com/gookit/color"
"github.com/gookit/gcli/v3"
"github.com/gookit/goutil/dump"

)

// options for the command var exampleOpts = struct { id int c string dir string opt string names gcli.Strings }{}

// ExampleCommand command definition var ExampleCommand = &gcli.Command{ Name: "example", Desc: "this is a description message", Aliases: []string{"exp", "ex"}, // 命令别名 // {$binName} {$cmd} is help vars. '{$cmd}' will replace to 'example' Examples: {$binName} {$cmd} --id 12 -c val ag0 ag1 <cyan>{$fullCmd} --names tom --names john -n c</> test use special option, Config: func(c *gcli.Command) { // binding options // ... c.IntOpt(&exampleOpts.id, "id", "", 2, "the id option") c.StrOpt(&exampleOpts.c, "config", "c", "value", "the config option") // notice DIRECTORY will replace to option value type c.StrOpt(&exampleOpts.dir, "dir", "d", "", "the DIRECTORY option") // 支持设置选项短名称 c.StrOpt(&exampleOpts.opt, "opt", "o", "", "the option message") // 支持绑定自定义变量, 但必须实现 flag.Value 接口 c.VarOpt(&exampleOpts.names, "names", "n", "the option message")

  // binding arguments
    c.AddArg("arg0", "the first argument, is required", true)
    // ...
},
Func:  exampleExecute,

}

// 命令执行主逻辑代码 // example run: // go run ./_examples/cliapp.go ex -c some.txt -d ./dir --id 34 -n tom -n john val0 val1 val2 arrVal0 arrVal1 arrVal2 func exampleExecute(c *gcli.Command, args []string) error { color.Infoln("hello, in example command")

if exampleOpts.showErr {
    return c.NewErrf("OO, An error has occurred!!")
}

magentaln := color.Magenta.Println

color.Cyanln("All Aptions:")
// fmt.Printf("%+v\n", exampleOpts)
dump.V(exampleOpts)

color.Cyanln("Remain Args:")
// fmt.Printf("%v\n", args)
dump.P(args)

magentaln("Get arg by name:")
arr := c.Arg("arg0")
fmt.Printf("named arg '%s', value: %#v\n", arr.Name, arr.Value)

magentaln("All named args:")
for _, arg := range c.Args() {
    fmt.Printf("- named arg '%s': %+v\n", arg.Name, arg.Value)
}

return nil

}

go build ./_examples/cliapp.go && ./cliapp example -h

cmd-help

Progress display

Package progress provide terminal progress bar display.

Such as: Txt, Bar, Loading, RoundTrip, DynamicText ...

Demo: ./cliapp prog bar

prog-bar

Demo: ./cliapp prog txt

prog-bar

prog-demo

[===     ] -> [    === ] -> [ ===    ]

prog-demo

Examples:

package main

import ( "time"

"github.com/gookit/gcli/v3/progress"

)

func main() { speed := 100 maxSteps := 110 p := progress.Bar(maxSteps) p.Start()

for i := 0; i < maxSteps; i++ {
    time.Sleep(time.Duration(speed) * time.Millisecond)
    p.Advance()
}

p.Finish()

}

more demos please see progress_demo.go

run demos:

go run ./_examples/cliapp.go prog txt go run ./_examples/cliapp.go prog bar go run ./_examples/cliapp.go prog roundTrip

prog-other

Interactive methods

console interactive methods

Examples:

package main

import ( "fmt"

"github.com/gookit/gcli/v3/interact"

)

func main() { username, _ := interact.ReadLine("Your name?") password := interact.ReadPassword("Your password?")

ok := interact.Confirm("ensure continue?")
if !ok {
    // do something...
}

fmt.Printf("username: %s, password: %s\n", username, password)

}

Read Input

read user input message

ans, _ := interact.ReadLine("Your name? ")

if ans != "" { color.Println("Your input: ", ans) } else { color.Cyan.Println("No input!") }

interact-read

Select/Choice

ans := interact.SelectOne( "Your city name(use array)?", []string{"chengdu", "beijing", "shanghai"}, "", ) color.Comment.Println("your select is: ", ans)

interact-select

Multi Select/Checkbox

ans := interact.MultiSelect( "Your city name(use array)?", []string{"chengdu", "beijing", "shanghai"}, nil, ) color.Comment.Println("your select is: ", ans)

interact-select

Confirm Message

if interact.Confirm("Ensure continue") { fmt.Println(emoji.Render(":smile: Confirmed")) } else { color.Warn.Println("Unconfirmed") }

interact-confirm

Read Password

pwd := interact.ReadPassword()

color.Comment.Println("your input password is: ", pwd)

interact-passwd

CLI Color

Terminal color use gookit/color Support windows cmd.exe powerShell

colored-demo

Color usage

package main

import ( "github.com/gookit/color" )

func main() { // simple usage color.Cyan.Printf("Simple to use %s\n", "color")

// internal theme/style:
color.Info.Tips("message")
color.Info.Prompt("message")
color.Warn.Println("message")
color.Error.Println("message")

// custom color
color.New(color.FgWhite, color.BgBlack).Println("custom color style")

// can also:
color.Style{color.FgCyan, color.OpBold}.Println("custom color style")

// use defined color tag
color.Print("use color tag: <suc>he</><comment>llo</>, <cyan>wel</><red>come</>\n")

// use custom color tag
color.Print("custom color tag: <fg=yellow;bg=black;op=underscore;>hello, welcome</>\n")

// set a style tag
color.Tag("info").Println("info style text")

// prompt message
color.Info.Prompt("prompt style message")
color.Warn.Prompt("prompt style message")

// tips message
color.Info.Tips("tips style message")
color.Warn.Tips("tips style message")

}

For more information on the use of color libraries, please visit gookit/color

Gookit packages

See also

License

MIT