gli

package module
v1.5.7 Latest Latest
Warning

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

Go to latest
Published: Dec 25, 2022 License: BSD-2-Clause-Views Imports: 14 Imported by: 20

README

Go Report Card MIT License

features

  • struct base
  • tag (cli:"names, n" help:"help message" default:"parsable literal")
    • for sub commands (cli, help, usage)
    • for options (cli, help, default, env, required)
  • sub command as a member struct in a parent struct
    • sub sub ... command
  • extra sub command
  • user defined option types (example: gli.Range, gli.IntList, ...)
  • pointer type options
  • hook functions Init/Before/Run/After/Help as methods of commands

go get

go get github.com/shu-go/gli

example app:

go get github.com/shu-go/gli/example/todo

This introduces an executable binary todo.

Examples

Example1: Simple

type Global struct {
    Opt1 string
    Opt2 int
}

func main() {
    app := gli.New(&Global{})
    _, _, err := app.Run(os.Args)
    // :
}

func (g *Global) Run(args []string) {
}

// app --opt1 abc --opt2 123
// app --opt1=abc --opt2=123

Example2: Renaming

type Global struct {
    Opt1 string `cli:"s, str"`
    Opt2 int    `cli:"i, int, opt2"`
}

// :

// app --opt1 abc --opt2 123 <-- NG: opt1 is not defined (while opt2 is defined)
// app -s abc -i 123
// app --str abc --int 123

Example3: Sub command

type Global struct {
    Opt1 string `cli:"s, str"`
    Opt2 int    `cli:"i, int, opt2"`

    Sub1 mySub
}

type mySub struct {
    Opt3 string
    
    Sub2 mySubSub `cli:s, sub2`
}

func (sub *mySub) Run(g *Global, args []string) {
}

func (subsub *mySubSub) Run(g *Global, args []string, sub *mySub) {
}

// app --str abc --int 123 sub1 --opt3 def

Example4: Hook functions

Commnds (root and sub commands) may have some hook functions.

Define receivers for the target commands.

func (subsub *mySubSub) Run(g *Global, args []string, sub *mySub) {
}
  • Run
    • is called for the target command
  • Before
    • are called for root -> sub -> subsub(target, in this case)
    • With any error, Run is not called.
  • After
    • are called for subsub(target, in this case) -> sub -> root
  • Init
    • are called for root -> sub -> subsub(target, in this case)
    • These functions are for initialization of command struct.
  • Help
    • prints help message.
    • subsub(target, in this case) -> root
Run
  1. Init for all commands
  2. Before for all commands
    • and defer calling After
  3. Run
Help
  1. Init for all commands
  2. first defined Help, subsub -> root
Signature

Parameters are in arbitrary order, omittable.

  • []string
  • struct{...} or *struct{...} of command
// OK
func (subsub *mySubSub) Run(args []string, g *Global, sub *mySub) error {
}
// OK
func (subsub *mySubSub) Run(g *Global, args []string, sub *mySub) error {
}
// OK
func (subsub *mySubSub) Run(args []string, sub *mySub) error {
}
// OK
func (subsub *mySubSub) Run(sub *mySub) error {
}

Return value is nothing or an error.

func (subsub *mySubSub) Run() {
}
func (subsub *mySubSub) Run() error {
}

Example5: No Hook

Using gli to get values. No Run() implemented.

type Global struct {
    Opt1 string
    Opt2 int
    Sub1 *Sub1Cmd
}

type Sub1Cmd struct {
    Opt3 string
}

func main() {
    g := Global{}
    app := gli.New(&g)
    tgt, tgtargs, err := app.Run(os.Args, false) // no hook

    // traverse g
    println(g.Opt1) // abc
    println(g.Opt2) // 123
    if g.Sub1 != nil {
        println(g.Sub1.Opt3) // def
    }

    if sub1, ok := tgt.(*Sub1Cmd); ok {
        println(sub1.Opt3) // def
    }
    println(tgtargs) // g h i
}

func (g *Global) Run(args []string) {
    // not called
}

// app --opt1 abc --opt2 123 sub1 --opt3 def  g h i

Example6: Extra Command

type Global struct {}

func main() {
    ex := extra{
        Name string `cli:"n"`
    }{}

    app := gli.New(&Global{})
    app.AddExtraCommand(&ex, "extra", "help message")
}

// app extra -n abc

Example7: User defined option types

type MyOption struct {
    Data int
}

func (o *MyOption) Parse(s string) error {
    o.Data = len(s)
}

//

type Global struct {
    My MyOption
}

Example8: more tags

type Global struct {
    Opt1 string `cli:"opt1=PLACE_HOLDER" default:"default value" env:"ENV_OPT1" help:"help message"`
    Opt2 int    `cli:"opt2" required:"true"`
    Sub MySub   `cli:"sub" help:"help message" usage:"multi line usages\nseparated by \\n"`
}

Options:

  • cli
    • renaming
    • cli:"name1, name2, ..., nameZ=PLACE_HOLDER"
  • default
    • in string literal
    • bool, float, int and uint are converted by strconv.ParseXXX
    • other types are required implement func Parse (see Example7)
    • use Init hook function for dynamic default values
  • env
    • environment variable name
  • required
    • bool (true/false)
      • true if the option is given in the command line
    • checked just before Before or Run hook function is executed
    • this check is not affected by Init, Before, After hook function nor default tag
  • help

Sub commands:

  • cli
  • help
  • usage
    • multi line usage description separated by \n.

Option value overwriting:

  1. default tag
  2. env tag
  3. Init hook function

Example9: alternative help and usage of commands

type Global struct {
    Sub1 SubCommand1 `cli:"s1"  help:"a command"  usage:"s1 [anything]"`
    Sub2 SubCommand2 `cli:"s2"` // no help and usage
}

type SubCommand2 struct {
    help struct{} `help:"another command" usage:"s2 [something]"`

    // Underscore is also OK.
    //_ struct{} `help:"another command" usage:"s2 [something]"` 
}

Both Sub1 and Sub2 are handled as have same tags.


Copyright 2018 Shuhei Kubota

Documentation

Overview

Package gli is a CLI parsing and mapping library.

type globalCmd struct {
    Name string
    Age  int
}
func (g *globalCmd) Run() error {
    // :
}
app := gli.NewWith(&globalCmd{})
err := app.Run(os.Args)

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrNotDefined means "an option or a subcommand is not defined in the passed struct".
	ErrNotDefined = errors.New("not defined")
	// ErrNotRunnable means "Run method is not defined for the passed struct".
	ErrNotRunnable = fmt.Errorf("command not runnable")
	// ErrOptCanNotBeSet is a reflect related error.
	ErrOptCanNotBeSet = fmt.Errorf("option can not be set")
)

Functions

func Usage

func Usage(usage string) extraCmdInit

Usage is an optional argument to AddExtracommand.

Types

type App

type App struct {

	// Name is the app name. default: the name of the executable file
	Name string
	// Desc is a description of the app
	// {{Name}} - {{Desc}}
	Desc string
	// Usage is a long(multiline) usage text
	Usage string
	// Version numbers
	Version string

	// Copyright the app author has
	Copyright string

	// CliTag is a tag key. default: `cli`
	CliTag string
	// HelpTag is a tag key. default: `help`
	HelpTag string
	// UsageTag is a tag key. default: `usage`
	UsageTag string
	// DefaultTag is a tag key. default: `default`
	DefaultTag string
	// DefDescTag is a tag key. default: `defdesc`
	DefDescTag string
	// EnvTag is a tag key. default: `env`
	EnvTag string
	// RequiredTag is a tag key. default: `required`
	RequiredTag string

	// MyCommandABC => false(default): "mycommandabc" , true: "my-command-abc"
	HyphenedCommandName bool
	// MyOptionABC => false(default): "myoptionabc" , true: "my-option-abc"
	HyphenedOptionName bool
	// OptionsGrouped(default: true) allows -abc may be treated as -a -b -c.
	OptionsGrouped bool
	DoubleHyphen   bool

	// SuppressErrorOutput is an option to suppresses on cli parsing error.
	SuppressErrorOutput bool
	Stdout, Stderr      *os.File

	// true(default): bool options have --no-xxx options.
	// AutoNoBoolOptions also appends --no-xxx descriptions in help doc if .
	//
	// Options:
	//   opt1, o1  A bool option
	//   opt2, o2  A bool option (default: true)
	//     --no-opt2
	//   opt1, o1  A bool option
	AutoNoBoolOptions bool
	// contains filtered or unexported fields
}

App contains parsing and parsed data.

func New

func New() App

New makes main gli instance to parse and invoke hooks.

App bridges between application logic code and CLI definition (your struct).

Next, call Bind() to set the CLI up.

func NewWith

func NewWith(ptrSt interface{}) App

NewWith is New().Bind(ptrSt)

func (*App) AddExtraCommand

func (g *App) AddExtraCommand(ptrSt interface{}, names, help string, inits ...extraCmdInit)

AddExtraCommand adds a sub command.

func (*App) Bind

func (g *App) Bind(ptrSt interface{}) error

Bind updates option/command names with ptrSt. Extra commands are cleared.

func (App) Help

func (g App) Help(w io.Writer)

Help displays help messages.

func (*App) Parse

func (g *App) Parse(args []string) (tgt interface{}, tgtargs []string, err error)

Parse parses args and returns results. tgt (interface{}) : a resultant struct tgtargs ([]string) : args of last subcommand err : parsing error

func (*App) Run

func (g *App) Run(args []string) error

Run parses args and calls Run method of a subcommand.

type Date

type Date time.Time

Date is a parsable type of date.

DEPLICATED: use time.Time instead. CAUTION: time.Time is Local timezone, gli.Date is UTC.

see https://golang.org/pkg/time/#ParseDuration

func (*Date) Parse

func (d *Date) Parse(str string) error

Parse parses string str and stores it as gli.Date (time.Time)

examples: "2019-12-31", "2019/12/31"

func (Date) Time

func (d Date) Time() time.Time

Time returns gli.Date as time.Time

type Duration

type Duration time.Duration

Duration is a parsable type of time duration.

DEPLICATED: use time.Duration instead.

see https://golang.org/pkg/time/#ParseDuration

func (Duration) Duration

func (d Duration) Duration() time.Duration

Duration returns gli.Duration as time.Time

func (*Duration) Parse

func (d *Duration) Parse(str string) error

Parse parses string str and stores it as gli.Duration (time.Time)

examples: "10m" ten minutes, "1s" one second

type IntList

type IntList []int

IntList is a parsable type of [1, 2, 3]

func (IntList) Contains

func (l IntList) Contains(i int) bool

Contains tests string s is in the gli.IntList

func (*IntList) Parse

func (l *IntList) Parse(str string, nondefFirst bool) error

Parse parses string str and stores it as gli.IntList ([]int)

examples: "1,2,3"

type Map

type Map map[string]string

Map is a parsable type of key:value pair.

func (*Map) Parse

func (m *Map) Parse(str string, nondefFirst bool) error

Parse parses string str and stores it as gli.Map (map[string]string)

examples: "key1:value1,key2:value2"

type MultipleOptionParser

type MultipleOptionParser interface {
	// Parse parses string str and converts it to the receiver's type.
	// Bool nondefFirst is true if you shuld re-initialize.
	Parse(str string, nondefFirst bool) error
}

MultipleOptionParser sets a converted value to itself. This is for options where the value is passed multiple times, such as in a list.

type OptionParser

type OptionParser interface {
	// Parse parses string str and converts it to the receiver's type.
	Parse(str string) error
}

OptionParser sets a converted value to itself.

type Range

type Range struct {
	Min, Max string
}

Range is a parsable type of min:max.

func (*Range) Parse

func (r *Range) Parse(str string) error

Parse parses string str and stores it as gli.Range (Min, Max string)

examples: "A:Z", "1:100", ":0"

type StrList

type StrList []string

StrList is a parsable type of ["s", "t", "r"]

func (StrList) Contains

func (l StrList) Contains(s string) bool

Contains tests string s is in the gli.StrList

func (*StrList) Parse

func (l *StrList) Parse(str string, nondefFirst bool) error

Parse parses string str and stores it as gli.StrList ([]string)

examples: "a,b,c"

Directories

Path Synopsis
example

Jump to

Keyboard shortcuts

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