myflags

package module
v0.3.3 Latest Latest
Warning

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

Go to latest
Published: Sep 27, 2023 License: MIT Imports: 10 Imported by: 1

README

Go package PkgGoDev

myflags

myflags is a Golang module to make command line flag easier, it creates command line flags based on fields in a struct, so user doesn't need to manually create the flags one by one. it also supports more types than flag module, and easily extensible for new types, user could even add support for existing type without using alias type.

myflags also support multiple and hierarchical actions, each action could have a set of its own parameters and sub-actions, for example a file compression tool cptool could have "compress" and "extract" action, and each has different parameters, and "compress" could have sub-actions like "zipfoler" and "zipfile", each then again has different parameters.

Input wise, parameters of an action has prefix "-", while action doesn't have any prefix.

for example, compress a folder could be command line input like cptool compress -profile <profile_name> zipfolder -foldername <foldername>.

Struct Field Tags

Following struct field tags are supported:

  • skipflag: skip the field for flagging
  • alias: use the specified alias as the name of the parameter
  • usage: the usage string of the parameter
  • action: this field is an action

Quick Start

Using myflags is straight forward:

  1. define all flags in a struct, each action is a field whose type is another struct.
  2. create a Filler with the struct, call Fill method with the struct variable with default value.
  3. call flag.Parse()

Following is an example: https://github.com/hujun-open/myflags/blob/2fd27463cabdc368b87aecc7addbb42f5535abc6/example/main.go#L1-L45 the created flags:

.\cptool.exe -?
a zip command
  - configfile: working profile
        default:default.conf
  = compress: to compress things
    - loop: number of compress iterations
        default:0x20
    - profile:
    - s:
        default:false
    = dryrun: dry run, doesn't actually create any file
    = zipfolder: zip a folder
      - folder: specify folder name
    = zipfile: zip a file
      - f: specify file name
        default:defaultzip.file
  = extract: to unzip things
    - inputfile: input zip file
  = help: help

some parsing results:

.\cptool.exe -configfile cp.conf compress -profile my.profile -s zipfilder -folder ./bigfolder/
parsed actions [Compress]
{ConfigFile:cp.conf Compress:{Loop:32 Profile:my.profile Skip:true NoFlag: DryRun:{} ZipFolder:{FolderName:} ZipFile:{FileName:defaultzip.file}} Extract:{InputFile:} Help:{}}

.\cptool.exe -configfile cp.conf compress -loop 100 dryrun
parsed actions [Compress DryRun]
{ConfigFile:cp.conf Compress:{Loop:100 Profile: Skip:false NoFlag: DryRun:{} ZipFolder:{FolderName:} ZipFile:{FileName:defaultzip.file}} Extract:{InputFile:} Help:{}}

Supported Types

Base:

  • all int/uint types: support base tag for the base
  • float32/float64
  • string
  • bool
  • time.Duration
  • time.Time: supports layout tag for time layout string
  • All types implement both of following interface:
    • encoding.TextUnmarshaler
    • encoding.TextUnmarshaler
  • All type register via myflags.Register function

Note: flag is only created for exported struct field.

In addition to base types, following types are also supported:

  • pointer to the base type
  • slice/array of base type
  • slice/array of pointer to the base type

for slice/array, use "," as separator.

myflags also supports following type of struct:

  • nested struct, like:
type Outer struct {
    Nested struct {
        Name string
    }
}
  • embeded struct, like:
type SubS struct {
    SubName string
}
type Outer struct {
    SubS
}

Flag Naming

By default, the name of created flag is the lowercase of struct field name, in case the field is part of sub-struct, and parent struct is NOT an action, then the name of created flag is "<parent_field_name>-<field_name>";

Optionally a renaming function could be supplied when creating the Filler, myflags uses the renaming function returned string as the flag name.

Extension

New type could be supported via myflags.Register, which takes a variable implements myflags.RegisteredConverters interface. the myflags.Register must be called before myflags.Fill, typically it should be called in init().

Check time.go, inttype.go for examples.

Bool

myflags use standard Golang module flag, which doesn't support "-flag x" format for bool. using "-flag x" for bool could cause silent failure that input parameters after bool don't get parsed.

Documentation

Index

Constants

View Source
const (
	//SkipTag is the struct field tag used to skip flag generation
	SkipTag = "skipflag"
	//AliasTag is the struct field tag used to specify the parameter name iso field name
	AliasTag = "alias"
	//UsageTag is the struct field tag used to specify the usage of the field
	UsageTag = "usage"
	//ActTag is the struct field tag used to specify the field is an action
	ActTag = "action"
)
View Source
const (
	//default flag.ErrorHandling
	DefaultErrHandle = flag.ExitOnError
)

Variables

View Source
var DefaultTimeLayout = "2006-01-02 15:04:05"

DefaultTimeLayout is the default layout string to parse time, following golang time.Parse() format, can be overridden per field by field tag "layout". Default value is "2006-01-02 15:04:05", which is the same as time.DateTime in Go 1.20

View Source
var ErrInvalidAction = errors.New("unknown action")

Functions

func DefaultRenamer

func DefaultRenamer(parent, name string, isAct bool) string

DefaultRenamer is the default renaming function, it is parent + "-" + name when isAct is true; otherwise return lower case of name

func PrettyStruct added in v0.1.1

func PrettyStruct(in any, prefix string) string

PrettyStruct returns a pretty formatted string representation of in

func Register

func Register[T any](c RegisteredConverters)

Register a new type with corresponding converters

Types

type Filler

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

Filler auto-generates one or multiple flag.FlagSet based on an input struct

func NewFiller

func NewFiller(fsname, usage string, options ...FillerOption) *Filler

NewFiller creates a new Filler, fsname is the name for flagset, usage is the overall usage introduction. optionally, a list of FillerOptions could be specified.

func (*Filler) Fill

func (filler *Filler) Fill(in any) error

Fill filler with struct in

func (*Filler) GetActUsage added in v0.2.0

func (filler *Filler) GetActUsage(actname string) string

GetActUsage returns filler's child action usage specified by actname, actname should be the field name before renaming; return "" if not found

func (*Filler) GetFlagset added in v0.3.1

func (filler *Filler) GetFlagset() *flag.FlagSet

GetFlagset returns the flagset used by the filler

func (*Filler) Parse added in v0.2.0

func (filler *Filler) Parse() ([]string, error)

like, PrseArgs, use os.Args as input

func (*Filler) ParseArgs added in v0.2.0

func (filler *Filler) ParseArgs(args []string) ([]string, error)

ParseArgs parse the args, return parsed actions as a slice of string, each is a parsed action name

func (*Filler) Usage added in v0.2.0

func (filler *Filler) Usage()

Usage print the string returned by UsageStr

func (*Filler) UsageStr added in v0.2.0

func (filler *Filler) UsageStr(prefix string) string

UsageStr return a usage string for the filler and its descendant fillers (a.k.a actions)

type FillerOption

type FillerOption func(filler *Filler)

FillerOption is an option when creating new Filler

func WithFlagErrHandling added in v0.2.0

func WithFlagErrHandling(h flag.ErrorHandling) FillerOption

WithFlagErrHandling returns a FillerOption thats specifies the flag.ErrorHandling

func WithRenamer

func WithRenamer(r RenameFunc) FillerOption

WithRenamer returns a FillerOption that specifies the rename function

type FromStrFunc

type FromStrFunc func(s string, tags reflect.StructTag) (any, error)

FromStrFunc is a function convert string s into a specific type T, the tag is the struct field tag, as addtional input. see time.go for implementation examples

type RegisteredConverters

type RegisteredConverters interface {
	ToStr(any, reflect.StructTag) string
	FromStr(string, reflect.StructTag) (any, error)
}

type RenameFunc

type RenameFunc func(parent, name string, isAct bool) string

RenameFunc is the function to rename the flag for a struct field, name is the field name, while parent is the parent struct field name, isAct is true when parent is an action

type ToStrFunc

type ToStrFunc func(in any, tags reflect.StructTag) string

ToStrFunc is a function convert in to string, the tag is the struct field tag, as addtional input. see time.go for implementation examples

Jump to

Keyboard shortcuts

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