cflag

package
v0.6.15 Latest Latest
Warning

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

Go to latest
Published: Jan 4, 2024 License: MIT Imports: 24 Imported by: 4

README

cflag

cflag - Wraps and extends go flag.FlagSet to build simple command line applications

  • Supports auto-rendering of pretty help messages
  • Allows adding short options to flag options, and multiples
  • Allows binding named arguments
  • Allows setting arguments or options as required
  • Allows setting validators for arguments or options

中文说明

Install

go get github.com/gookit/goutil/cflag

Go docs

Usage

Examples, code please see _example/cmd.go

package main

import (
	"github.com/gookit/goutil/cflag"
	"github.com/gookit/goutil/cliutil"
)

var opts = struct {
    age  int
    name string
    str1 string
    lOpt string
    bol  bool
}{}

// go run ./_example/cmd.go
// go run ./cflag/_example/cmd.go -h
// go run ./cflag/_example/cmd.go --name inhere --lo val ab cd
func main() {
	c := cflag.New(func(c *cflag.CFlags) {
		c.Desc = "this is a demo command"
		c.Version = "0.5.1"
	})
	c.IntVar(&opts.age, "age", 0, "this is a int option;;a")
	c.StringVar(&opts.name, "name", "", "this is a string option and required;true")
	c.StringVar(&opts.str1, "str1", "def-val", "this is a string option with default value;;s")
	c.StringVar(&opts.lOpt, "long-opt", "", "this is a string option with shorts;;lo")

	c.AddArg("arg1", "this is arg1", true, nil)
	c.AddArg("arg2", "this is arg2", true, nil)

	c.Func = func(c *cflag.CFlags) error {
		cliutil.Magentaln("hello, this is command:", c.Name())
		cliutil.Infoln("option.age =", opts.age)
		cliutil.Infoln("option.name =", opts.name)
		cliutil.Infoln("option.str1 =", opts.str1)
		cliutil.Infoln("option.lOpt =", opts.lOpt)
		cliutil.Infoln("arg1 =", c.Arg("arg1").String())
		cliutil.Infoln("arg2 =", c.Arg("arg2").String())
		cliutil.Infoln("remain args =", c.RemainArgs())

		return nil
	}

	// c.MustParse(os.Args[1:])
	c.MustParse(nil)
}
Bind and get arguments

Bind arguments:

	c.AddArg("arg1", "this is arg1", true, nil)
	c.AddArg("arg2", "this is arg2", true, nil)

Get arguments by name:

	cliutil.Infoln("arg1 =", c.Arg("arg1").String())
	cliutil.Infoln("arg2 =", c.Arg("arg2").String())
Set required and short options

Options can be set as required, and short option names can be set.

TIPs: Implements required and shorts by extending usage with options parsed

Format:

  • format1: desc;required
  • format2: desc;required;shorts
  • required: a bool string. mark option is required
    • True: true,on,yes
    • False: false,off,no,''
  • shorts: shortcut names for option, allow multi values, split by comma ,

Examples:

    // set option 'name' is required
	c.StringVar(&opts.name, "name", "", "this is a string option and required;true")
    // set option 'str1' shorts: s
	c.StringVar(&opts.str1, "str1", "def-val", "this is a string option with default value;;s")
Show help
go run ./cflag/_example/cmd.go -h

Output:

cmd-help

Run command
go run ./cflag/_example/cmd.go --name inhere -a 12 --lo val ab cd
go run ./cflag/_example/cmd.go --name inhere -a 12 --lo val ab cd de fg

Output:

cmd-run

required Check
go run ./cflag/_example/cmd.go -a 22
go run ./cflag/_example/cmd.go --name inhere

Output:

cmd-required.png

Cli application

Use cflag to quickly build a multi-command application.

package main

import (
	"github.com/gookit/goutil/cflag"
	"github.com/gookit/goutil/dump"
)

var c1Opts = struct {
	age  int
	name string
}{}

var c2Opts = struct {
	str1 string
	lOpt string
	bol  bool
}{}

// go run ./_example/app.go
// go run ./cflag/_example/app.go -h
// go run ./cflag/_example/app.go demo -h
func main() {
	app := cflag.NewApp()
	app.Desc = "this is my cli application"
	app.Version = "1.0.2"

	// go run ./cflag/_example/app.go demo --name inhere --age 333 val0 val1
	c1 := cflag.NewCmd("demo", "this is a demo command")
	c1.OnAdd = func(c *cflag.Cmd) {
		c.IntVar(&c1Opts.age, "age", 0, "this is a int option;;a")
		c.StringVar(&c1Opts.name, "name", "", "this is a string option and required;true")

		c.AddArg("arg1", "this is arg1", true, nil)
		c.AddArg("arg2", "this is arg2", false, nil)
	}
	c1.Func = func(c *cflag.Cmd) error {
		dump.P(c1Opts, c.Args())
		return nil
	}

	// Multiple commands can be added
	app.Add(c1)

	app.Run()
}
Show commands
go run ./cflag/_example/app.go -h

app-help

Run command
go run ./cflag/_example/app.go demo --name inhere --age 333 val0 val1

app-run

Documentation

Overview

Package cflag Wraps and extends go `flag.FlagSet` to build simple command line applications

- Support auto render a pretty help panel

- Allow to add shortcuts for flag option

- Allow binding named arguments

- Allow set required for argument or option

- Allow set validator for argument or option

Example
package main

import (
	"github.com/gookit/goutil/cflag"
	"github.com/gookit/goutil/cliutil"
)

func main() {
	opts := struct {
		age  int
		name string
		str1 string
		bol  bool
	}{}

	c := cflag.New(func(c *cflag.CFlags) {
		c.Desc = "this is a demo command"
		c.Version = "0.5.1"
	})
	c.IntVar(&opts.age, "age", 0, "this is a int option;;a")
	c.StringVar(&opts.name, "name", "", "this is a string option and required;true")
	c.StringVar(&opts.str1, "str1", "def-val", "this is a string option with default value;;s")

	c.AddArg("arg1", "this is arg1", true, nil)
	c.AddArg("arg2", "this is arg2", true, nil)
	c.AddArg("arg3", "this is arg3 with default", false, "def-val")

	c.Func = func(c *cflag.CFlags) error {
		// do something ...

		cliutil.Infoln("hello, this is", c.Name())
		cliutil.Infoln("option.age =", opts.age)
		cliutil.Infoln("option.name =", opts.name)
		cliutil.Infoln("option.str1 =", opts.str1)
		cliutil.Infoln("arg1 =", c.Arg("arg1").String())
		cliutil.Infoln("arg2 =", c.Arg("arg2").String())
		cliutil.Infoln("arg3 =", c.Arg("arg3").String())

		return nil
	}

	// c.MustParse(os.Args[1:])
	c.MustParse(nil)
}
Output:

Index

Examples

Constants

View Source
const ParseStopMark = "--"

ParseStopMark string

View Source
const (
	// RegGoodName match a good option, argument name
	RegGoodName = `^[a-zA-Z][\w-]*$`
)

Variables

View Source
var Debug = envutil.GetBool("CFLAG_DEBUG")

Debug mode

Functions

func AddPrefix

func AddPrefix(name string) string

AddPrefix for render flag options help

func AddPrefixes

func AddPrefixes(name string, shorts []string) string

AddPrefixes for render flag options help, name will first add.

func AddPrefixes2 added in v0.5.6

func AddPrefixes2(name string, shorts []string, nameAtEnd bool) string

AddPrefixes2 for render flag options help, can custom name add position.

func FilterNames added in v0.5.7

func FilterNames(names []string) []string

FilterNames for option names, will clear there are: "-+= "

func IsFlagHelpErr added in v0.5.6

func IsFlagHelpErr(err error) bool

IsFlagHelpErr check

func IsGoodName added in v0.6.5

func IsGoodName(name string) bool

IsGoodName check

func IsZeroValue

func IsZeroValue(opt *flag.Flag, value string) (bool, bool)

IsZeroValue determines whether the string represents the zero value for a flag.

from flag.isZeroValue() and more return the second arg for check is string.

func LimitInt added in v0.6.11

func LimitInt(min, max int) comdef.IntCheckFunc

LimitInt limit int value range

func ReplaceShorts added in v0.5.6

func ReplaceShorts(args []string, shortsMap map[string]string) []string

ReplaceShorts replace shorts to full option. will stop on ParseStopMark

For example:

eg: '-f' -> '--file'.
eg: '-n=tom' -> '--name=tom'.

func SetDebug

func SetDebug(open bool)

SetDebug mode

func SplitShortcut added in v0.5.6

func SplitShortcut(shortcut string) []string

SplitShortcut string to []string

func WithDesc

func WithDesc(desc string) func(c *CFlags)

WithDesc for command

func WithVersion

func WithVersion(version string) func(c *CFlags)

WithVersion for command

func WrapColorForCode added in v0.5.13

func WrapColorForCode(s string) string

WrapColorForCode convert "hello `keywords`" to "hello <mga>keywords</>"

Types

type App added in v0.5.12

type App struct {
	Name string
	Desc string
	// NameWidth max width for command name
	NameWidth  int
	HelpWriter io.Writer
	// Version for app
	Version string

	// AfterHelpBuild hook
	AfterHelpBuild func(buf *strutil.Buffer)
	// contains filtered or unexported fields
}

App struct

func NewApp added in v0.5.12

func NewApp(fns ...func(app *App)) *App

NewApp instance

Example
package main

import (
	"github.com/gookit/goutil/cflag"
	"github.com/gookit/goutil/dump"
)

func main() {
	app := cflag.NewApp()
	app.Desc = "this is my cli application"
	app.Version = "1.0.2"

	var c1Opts = struct {
		age  int
		name string
	}{}

	c1 := cflag.NewCmd("demo", "this is a demo command")
	c1.OnAdd = func(c *cflag.Cmd) {
		c.IntVar(&c1Opts.age, "age", 0, "this is a int option;;a")
		c.StringVar(&c1Opts.name, "name", "", "this is a string option and required;true")

		c.AddArg("arg1", "this is arg1", true, nil)
		c.AddArg("arg2", "this is arg2", false, nil)
	}

	c1.Func = func(c *cflag.Cmd) error {
		dump.P(c1Opts, c.Args())
		return nil
	}

	var c2Opts = struct {
		str1 string
		lOpt string
		bol  bool
	}{}

	c2 := cflag.NewCmd("other", "this is another demo command")
	{
		c2.StringVar(&c2Opts.str1, "str1", "def-val", "this is a string option with default value;;s")
		c2.StringVar(&c2Opts.lOpt, "long-opt", "", "this is a string option with shorts;;lo")

		c2.Func = func(c *cflag.Cmd) error {
			dump.P(c2Opts)
			return nil
		}
	}

	app.Add(c1, c2)
	app.Run()
}
Output:

func (*App) Add added in v0.5.12

func (a *App) Add(cmds ...*Cmd)

Add command(s) to app

func (*App) Run added in v0.5.12

func (a *App) Run()

Run app by os.Args

func (*App) RunWithArgs added in v0.5.12

func (a *App) RunWithArgs(args []string) error

RunWithArgs run app by input args

type Booleans added in v0.5.13

type Booleans []bool

Booleans The bool flag list, repeatable. eg: -v -v => []bool{true, true}

func (*Booleans) Bools added in v0.6.11

func (s *Booleans) Bools() []bool

Bools value

func (*Booleans) IsRepeatable added in v0.6.7

func (s *Booleans) IsRepeatable() bool

IsRepeatable on input

func (*Booleans) Set added in v0.5.13

func (s *Booleans) Set(value string) error

Set new value

func (*Booleans) String added in v0.5.13

func (s *Booleans) String() string

String input value to string

type CFlags

type CFlags struct {
	*flag.FlagSet

	// Desc command description
	Desc string
	// Version command version number
	Version string
	// Example command usage examples
	Example string
	// LongHelp custom help
	LongHelp string
	// Func handler for the command
	Func func(c *CFlags) error
	// contains filtered or unexported fields
}

CFlags wrap and extends the go flag.FlagSet

eg:

// Can be set required and shorts on desc:
// format1: desc;required
cmd.IntVar(&age, "age", 0, "your age;true")
// format2: desc;required;shorts
cmd.IntVar(&age, "age", 0, "your age;true;a")

func New

func New(fns ...func(c *CFlags)) *CFlags

New create new instance.

Usage:

cmd := cflag.New(func(c *cflag.CFlags) {
	c.Version = "0.1.2"
	c.Desc = "this is my cli tool"
})

// binding opts and args

cmd.Parse(nil)

func NewEmpty

func NewEmpty(fns ...func(c *CFlags)) *CFlags

NewEmpty instance.

func (*CFlags) AddArg

func (c *CFlags) AddArg(name, desc string, required bool, value any)

AddArg binding for command

func (*CFlags) AddShortcuts

func (c *CFlags) AddShortcuts(name string, shorts ...string)

AddShortcuts for option flag

func (*CFlags) AddValidator

func (c *CFlags) AddValidator(name string, fn OptCheckFn)

AddValidator for a flag option

func (*CFlags) Arg

func (c *CFlags) Arg(name string) *FlagArg

Arg get by bind name

func (*CFlags) BinFile

func (c *CFlags) BinFile() string

BinFile path for command

func (*CFlags) BindArg

func (c *CFlags) BindArg(arg *FlagArg)

BindArg for command

func (*CFlags) ConfigOpt

func (c *CFlags) ConfigOpt(name string, fn func(opt *FlagOpt))

ConfigOpt for a flag option

func (*CFlags) MustParse

func (c *CFlags) MustParse(args []string)

MustParse parse flags and run command, will auto handle error

func (*CFlags) MustRun added in v0.5.6

func (c *CFlags) MustRun(args []string)

MustRun parse flags and run command. alias of MustParse()

func (*CFlags) Name

func (c *CFlags) Name() string

Name for command

func (*CFlags) Parse

func (c *CFlags) Parse(args []string) error

Parse flags and run command func

If args is nil, will parse os.Args

func (*CFlags) QuickRun added in v0.5.6

func (c *CFlags) QuickRun()

QuickRun parse OS flags and run command, will auto handle error

func (*CFlags) RemainArgs

func (c *CFlags) RemainArgs() []string

RemainArgs get

func (*CFlags) ShowHelp

func (c *CFlags) ShowHelp()

ShowHelp for command

func (*CFlags) WithConfigFn

func (c *CFlags) WithConfigFn(fns ...func(c *CFlags)) *CFlags

WithConfigFn for command

type Cmd added in v0.5.12

type Cmd struct {
	*CFlags
	Name  string
	Func  func(c *Cmd) error
	OnAdd func(c *Cmd)
}

Cmd struct

func NewCmd added in v0.5.12

func NewCmd(name, desc string) *Cmd

NewCmd instance

func (*Cmd) Config added in v0.5.12

func (c *Cmd) Config(fn func(c *Cmd)) *Cmd

Config the cmd

type ConfString added in v0.6.5

type ConfString struct {
	maputil.SMap
	// contains filtered or unexported fields
}

ConfString The config-string flag, INI format, like nginx-config.

Example:

--config 'k0=val0;k1=val1' => string map {k0:val0, k1:val1}

func (*ConfString) Data added in v0.6.5

func (s *ConfString) Data() maputil.SMap

Data map get

func (*ConfString) Get added in v0.6.7

func (s *ConfString) Get() any

Get value

func (*ConfString) Set added in v0.6.5

func (s *ConfString) Set(value string) error

Set new value, will check value is right

func (*ConfString) SetData added in v0.6.5

func (s *ConfString) SetData(mp map[string]string)

SetData value

func (*ConfString) String added in v0.6.5

func (s *ConfString) String() string

String to string

type EnumString added in v0.5.13

type EnumString struct {
	// contains filtered or unexported fields
}

EnumString limit input value is in the enum list. implemented flag.Value interface

Usage:

var enumStr = cflag.NewEnumString("php", "go", "java")
c.VarOpt(&enumStr, "lang", "", "input language name")

func NewEnumString added in v0.6.6

func NewEnumString(enum ...string) EnumString

NewEnumString instance

func (*EnumString) Enum added in v0.6.7

func (s *EnumString) Enum() []string

Enum to string

func (*EnumString) EnumString added in v0.6.7

func (s *EnumString) EnumString() string

EnumString to string

func (*EnumString) Get added in v0.6.7

func (s *EnumString) Get() any

Get value

func (*EnumString) Set added in v0.5.13

func (s *EnumString) Set(value string) error

Set new value, will check value is right

func (*EnumString) SetEnum added in v0.5.13

func (s *EnumString) SetEnum(enum []string)

SetEnum values

func (*EnumString) String added in v0.5.13

func (s *EnumString) String() string

String input value to string

func (*EnumString) WithEnum added in v0.6.6

func (s *EnumString) WithEnum(enum []string) *EnumString

WithEnum values

type FlagArg

type FlagArg struct {
	// Value for the flag argument
	*structs.Value

	// Name of the argument
	Name string
	// Desc arg description
	Desc string
	// Index of the argument
	Index int
	// Required argument
	Required bool
	// Validator for check value
	Validator func(val string) error
	// contains filtered or unexported fields
}

FlagArg struct

func NewArg

func NewArg(name, desc string, required bool) *FlagArg

NewArg create instance

func (*FlagArg) HelpDesc

func (a *FlagArg) HelpDesc() string

HelpDesc string build

type FlagOpt

type FlagOpt struct {
	// Shortcuts short names. eg: ["o", "a"]
	Shortcuts []string
	// Required option
	Required bool
	// Validator for check option value
	Validator OptCheckFn
}

FlagOpt struct

func (*FlagOpt) HelpName

func (o *FlagOpt) HelpName(name string) string

HelpName string

type IntVar added in v0.6.11

type IntVar struct {

	// check func
	CheckFn comdef.IntCheckFunc
	// contains filtered or unexported fields
}

IntVar int value can with a check func

Limit min and max value:

iv := cflag.IntValue{CheckFn: cflag.LimitInt(1, 10)}
fs.IntVar(&iv, "int", 1, "the int value")

func NewIntVar added in v0.6.11

func NewIntVar(checkFn comdef.IntCheckFunc) IntVar

NewIntVar create a new IntVar instance with check func

func (*IntVar) Get added in v0.6.11

func (o *IntVar) Get() any

Get value

func (*IntVar) Set added in v0.6.11

func (o *IntVar) Set(value string) error

Set new value

func (*IntVar) String added in v0.6.11

func (o *IntVar) String() string

String value get

type Ints added in v0.5.13

type Ints []int

Ints The int flag list, repeatable

implemented flag.Value interface

func (*Ints) Get added in v0.6.11

func (s *Ints) Get() any

Get value

func (*Ints) Ints added in v0.6.11

func (s *Ints) Ints() []int

Ints value

func (*Ints) IsRepeatable added in v0.6.7

func (s *Ints) IsRepeatable() bool

IsRepeatable on input

func (*Ints) Set added in v0.5.13

func (s *Ints) Set(value string) error

Set new value

func (*Ints) String added in v0.5.13

func (s *Ints) String() string

String to string

type IntsString added in v0.6.7

type IntsString struct {

	// value and size validate
	ValueFn func(val int) error
	SizeFn  func(ln int) error
	// contains filtered or unexported fields
}

IntsString The ints-string flag. eg: --get 1,2,3

Implemented the flag.Value interface

func (*IntsString) Get added in v0.6.7

func (o *IntsString) Get() any

Get value

func (*IntsString) Ints added in v0.6.7

func (o *IntsString) Ints() []int

Ints value

func (*IntsString) Set added in v0.6.7

func (o *IntsString) Set(value string) error

Set new value. eg: "12"

func (*IntsString) String added in v0.6.7

func (o *IntsString) String() string

String input value to string

type KVString added in v0.6.6

type KVString struct {
	maputil.SMap
	Sep string
}

KVString The kv-string flag, allow input multi.

Implemented the flag.Value interface.

Usage:

	type myOpts struct {
		vars cflag.KVString
	}
 var mo &myOpts{ vars: cflag.NewKVString() }

Example:

--var name=inhere => string map {name:inhere}
--var name=inhere --var age=234 => string map {name:inhere, age:234}

func NewKVString added in v0.6.6

func NewKVString() KVString

NewKVString instance

func (*KVString) Data added in v0.6.6

func (s *KVString) Data() maputil.SMap

Data map get

func (*KVString) Get added in v0.6.7

func (s *KVString) Get() any

Get value

func (*KVString) Init added in v0.6.8

func (s *KVString) Init() *KVString

Init settings

func (*KVString) IsRepeatable added in v0.6.7

func (s *KVString) IsRepeatable() bool

IsRepeatable on input

func (*KVString) Set added in v0.6.6

func (s *KVString) Set(value string) error

Set new value, will check value is right

type OptCheckFn

type OptCheckFn func(val any) error

OptCheckFn define

type RepeatableFlag added in v0.6.7

type RepeatableFlag interface {
	flag.Value
	// IsRepeatable mark option flag can be set multi times
	IsRepeatable() bool
}

RepeatableFlag interface.

type SafeFuncVar added in v0.6.13

type SafeFuncVar func(string)

SafeFuncVar safe func Value

func (SafeFuncVar) Set added in v0.6.13

func (f SafeFuncVar) Set(s string) error

Set value

func (SafeFuncVar) String added in v0.6.13

func (f SafeFuncVar) String() string

String get

type StrVar added in v0.6.11

type StrVar struct {

	// check func
	CheckFn comdef.StrCheckFunc
	// contains filtered or unexported fields
}

StrVar string value can with a check func

Usage:

sv := cflag.StrVar{}
fs.Var(&sv, "str", "the string value")

func NewStrVar added in v0.6.11

func NewStrVar(checkFn comdef.StrCheckFunc) StrVar

NewStrVar create a new StrVar with check func

func (*StrVar) Get added in v0.6.11

func (o *StrVar) Get() any

Get value string

func (*StrVar) Set added in v0.6.11

func (o *StrVar) Set(value string) error

Set new value

func (*StrVar) String added in v0.6.11

func (o *StrVar) String() string

String value get

type String added in v0.5.13

type String string

String a special string

Usage:

// case 1:
var names gcli.String
c.VarOpt(&names, "names", "", "multi name by comma split")

--names "tom,john,joy"
names.Split(",") -> []string{"tom","john","joy"}

// case 2:
var ids gcli.String
c.VarOpt(&ids, "ids", "", "multi id by comma split")

--names "23,34,56"
names.Ints(",") -> []int{23,34,56}

func (*String) Get added in v0.6.7

func (s *String) Get() any

Get value

func (*String) Ints added in v0.5.13

func (s *String) Ints(sep string) []int

Ints value to []int

func (*String) Set added in v0.5.13

func (s *String) Set(val string) error

Set value

func (*String) Split added in v0.5.13

func (s *String) Split(sep string) []string

Split value to []string

func (*String) String added in v0.5.13

func (s *String) String() string

String input value to string

func (*String) Strings added in v0.6.5

func (s *String) Strings() []string

Strings split value to []string by sep ','

type Strings added in v0.5.13

type Strings []string

Strings The string flag list, repeatable. eg: --names tom --names john

func (*Strings) Get added in v0.6.11

func (s *Strings) Get() any

Get value

func (*Strings) IsRepeatable added in v0.6.7

func (s *Strings) IsRepeatable() bool

IsRepeatable on input

func (*Strings) Set added in v0.5.13

func (s *Strings) Set(value string) error

Set new value

func (*Strings) String added in v0.5.13

func (s *Strings) String() string

String input value to string

func (*Strings) Strings added in v0.6.11

func (s *Strings) Strings() []string

Strings value

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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