flage

package module
v0.0.0-...-2a49c41 Latest Latest
Warning

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

Go to latest
Published: Jun 17, 2024 License: Apache-2.0 Imports: 17 Imported by: 0

README

flage

Go Reference

Extensions to go's built-in flag parsing. For when you want a little bit more, but not too much.

Install

Run:

go get github.com/jeffh/flage

Structs

This package can use a struct for easy parsing using go's flag package. Supported types are:

  • types supported by the flag package
  • any type that supports the flag.Value interface
  • any type that supports encoding.TextMarshal and encoding.TextUnmarshal interfaces

Example:

type Example struct {
    Bool bool
    Str  string
    U    uint
    U64  uint64
    I    int
    I64  int64
    F64  float64
    D    time.Duration
}
var opt Example
StructVar(&opt, nil) // this nil can be an optional flagset, otherwise, assumes flag.CommandLine
flag.Parse()
// opt will be populated

The argument names are the field names, lower-cased. You can add flage tags to customize them:

type Example struct {
    Bool bool `flage:"yes"`
}

The tag is comma separated with the following format:

{FlagName},{DefaultValue},{DocString}

FlagName = optional, use "-" to ignore it, leave blank to use lowercase field name behavior
DefaultValue = default value, parsed as if it was an argument flag. Causes panics on failure to parse
DocString = docstring for when -help is used. Commas are accepted.

Finally, you can use structs to create flagsets via FlagSetStruct.

Slices

This package provides types that allow them to be used multiple time to build a slice:

var args flage.StringSlice
flag.Var(&args, "arg", "additional arguments to pass. Can be used multiple times")
// ...
flag.Parse()

fmt.Printf("args are: %s", strings.Join(args, ", "))

// slices can be "reset" to clear them
flage.Reset(&args)

fmt.Printf("args are: %s", strings.Join(args, ", "))

// usage: myprogram -arg 1 -arg 2
// output:
// args are: 1, 2
// args are:

The following slices are supported:

  • StringSlice for slices of strings
  • FloatSlice for slices of float64
  • IntSlice for slices of int64
  • UintSlice for slices of uint64

These slices also support calling Reset on them to clear those slices, which can be useful if you're reusing them in flagsets.

Config Files

This feature is WIP and subject to change.

Sometimes using a bunch of flags is laborious and it would be nice to save to a file. flage provides some helpers to do this:

type Example struct {
    Config string

    Bool bool
    Str  string
    U    uint
    U64  uint64
    I    int
    I64  int64
    F64  float64
    D    time.Duration
}
var opt Example
StructVar(&opt, nil)
flag.Parse()

if opt.Config != "" {
    err := flage.ParseConfigFile(opt.Config)
    if err != nil {
        // ...
    }
}
// opt will be populated

The above code will allow -config <file> to point to a file that looks like:

# this is a comment and is ignored, # must be at the start of the line (ignoring only whitesepace)
-bool
-str "str"
-u 1 -u64 2

This is the same as passing in arguments to the command line argument (except for -config) with a couple of differences:

  • # are single lined comments
  • Newlines are converted to spaces
  • Some template variables and functions are available a la go's text/template syntax

This is templated the following template context is available:

  • {{.configDir}} points to the directory that holds the config file specified via -config <file>
  • {{env "MY_ENV_VAR"}} returns the value of reading the environment variable MY_ENV_VAR
  • {{envOr "MY_ENV_VAR" "DEFAULT"}} returns the value of reading the environment variable MY_ENV_VAR or returns "DEFAULT" if not present
  • {{envOrError "MY_ENV_VAR" "my error message"}} returns the value of reading the environment variable MY_ENV_VAR or returns an error with "my error message" included

More may be added. You can define your own set by using TemplateConfigRenderer, which the config functions wrap.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrNoMatchingFlagSet = errors.New("no matching commands")
	ErrUnknownCommand    = errors.New("unknown command")
)

Functions

func BoolVar

func BoolVar(fs *flag.FlagSet, p *bool, name string, value bool, usage string)

func CommandString

func CommandString(v any) []string

CommandString converts a struct into a series of command line args

func DurationVar

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

func FlagSetStruct

func FlagSetStruct(name string, errHandling flag.ErrorHandling, out any) *flag.FlagSet

FlagSetStruct makes a new flagset based on an output string to set to

func Float32Var

func Float32Var(fs *flag.FlagSet, p *float32, name string, value float32, usage string)

func Float64Var

func Float64Var(fs *flag.FlagSet, p *float64, name string, value float64, usage string)

func Int64Var

func Int64Var(fs *flag.FlagSet, p *int64, name string, value int64, usage string)

func IntVar

func IntVar(fs *flag.FlagSet, p *int, name string, value int, usage string)

func MakeUsageWithSubcommands

func MakeUsageWithSubcommands(info HelpInfo) func()

MakeUsageWithSubcommands creates a flag.Usage function that prints subcommands and arguments for them.

func ParseConfigFile

func ParseConfigFile(fileContents string) ([]string, error)

ParseConfigFile reads a config file and converts it to command line arguments. This is a quick and easy way to provide file-based configuration, a la pip.

Comments are lines that start with a '#' (and not in the middle). If env is given to nil, it defaults to EnvSystem(nil).

The configuration file format assumes:

- any line that starts with a '#' is a comment and ignored (ignoring leading whitespace) - all lines are replaced with spaces - then input is passed to shlex.Split to split by shell parsing rules

Example:

-load ./file.txt -secret $SECRET

func ParseEnvironFile

func ParseEnvironFile(data []byte) ([][2]string, error)

ParseEnvironFile reads bytes like an enviroment file.

File format:

  • "#" are to-end-of-line comments and must be at the start of the line
  • each line is in KEY=VALUE format
  • any line without an equal sign is ignored

func PrintCommands

func PrintCommands(w io.Writer, defs []FlagSetDefinition)

PrintCommands prints flagset definitions

func PrintFlagSets

func PrintFlagSets(w io.Writer, fss []*flag.FlagSet)

PrintFlagSets prints flagset usages with a newline separate in between

func ReadConfigFile

func ReadConfigFile(file string) ([]string, error)

ReadConfigFile reads a given filepath and converts it to command line arguments. This is a quick and easy way to provide file-based configuration, a la pip.

If you have the contents of the file already, use ParseConfigFile instead.

Comments are lines that start with a '#' (and not in the middle). If env is given to nil, it defaults to EnvSystem(nil).

The configuration file format assumes:

- any line that starts with a '#' is a comment and ignored (ignoring leading whitespace) - all lines are replaced with spaces - then input is passed to shlex.Split to split by shell parsing rules

Example:

-load ./file.txt -secret $SECRET

func ReadEnvironFile

func ReadEnvironFile(file string) ([][2]string, error)

ReadEnvironFile reads a file like an enviroment file.

File format:

  • "#" are to-end-of-line comments
  • each line is in KEY=VALUE format
  • any line without an equal sign is ignored

func Reset

func Reset(f flag.Value)

Reset zeros out the flag.Value given.

If the flag.Value has a Reset() method, that is called instead. Otherwise, defaults to calling value.Set("").

Implementers of Reset() should take case to not mutate the original value, in case it's used in other parts of the code base (post flag parsing).

Example:

var args flage.StringSlice
flag.Var(&args, "arg", "additional arguments to pass. Can be used multiple times")
// ...
flag.Parse()
fmt.Printf("args are: %s", strings.Join(args, ", "))
flage.Reset(&args)
fmt.Printf("args are: %s", strings.Join(args, ", ")) // will be empty

func StringVar

func StringVar(fs *flag.FlagSet, p *string, name string, value string, usage string)

func StructVar

func StructVar(v any, fs *flag.FlagSet)

StructVar performs like flag.Var(...) but using a struct. Can optionally be annotated using tags. If fs is nil, then the global functions in the flag package are used instead.

Tags use the "flag" key with the following values: "<flagName>,<defaultValue>,<description>" If <flagName> is empty, then the lowercase of the fieldname is used. Can be set to "-" to ignore. Can be set to "*" to recursively parse the struct as top-level flags. If <defaultValue> is empty, then the zero value is used. If <description> is empty, then the empty string is used.

As per flag package, the following types are supported:

  • string
  • float64
  • uint / uint64
  • int / int64
  • bool
  • flag.Value
  • encoding.TextUnmarshaler | encoding.TextMarshaler

Also additional types are supported:

  • float32

Future support for built-in types may be added in the future.

Example:

type Flag struct {
  Install bool `flag:"install,,enables installation"`
  ConfigFile string `flag:"config,,optional config file to load"`
}

var f Flag
StructVar(&f, nil)
flag.Parse()

func TextVar

func TextVar(fs *flag.FlagSet, p encoding.TextUnmarshaler, name string, value string, usage string)

func Uint64Var

func Uint64Var(fs *flag.FlagSet, p *uint64, name string, value uint64, usage string)

func UintVar

func UintVar(fs *flag.FlagSet, p *uint, name string, value uint, usage string)

func Var

func Var(fs *flag.FlagSet, p flag.Value, name string, value string, usage string)

Types

type CommandIterator

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

func (*CommandIterator) Err

func (it *CommandIterator) Err() error

func (*CommandIterator) FlagDef

func (it *CommandIterator) FlagDef() *FlagSetDefinition

func (*CommandIterator) FlagPtr

func (it *CommandIterator) FlagPtr() any

func (*CommandIterator) Next

func (it *CommandIterator) Next() bool

type Env

type Env struct {
	Parent *Env
	Dict   Lookuper
}

func EnvFile

func EnvFile(parent *Env, filepath string) (*Env, error)

func EnvSystem

func EnvSystem(parent *Env) *Env

func NewEnv

func NewEnv(parent *Env, dict Lookuper) *Env

func (*Env) Get

func (e *Env) Get(key string) string

func (*Env) GetOr

func (e *Env) GetOr(key, defvalue string) string

func (*Env) GetOrError

func (e *Env) GetOrError(key, errorMsg string) (string, error)

func (*Env) Keys

func (e *Env) Keys() []string

func (*Env) Lookup

func (e *Env) Lookup(key string) (string, bool)

func (*Env) Map

func (e *Env) Map() map[string][]string

func (*Env) Slice

func (e *Env) Slice() [][2]string

type EnvMap

type EnvMap map[string][]string

Represents a map of environment variables. Environment variables are appended when they are set. Supports multiple assignments as a flag argument using the format KEY=VALUE.

func (EnvMap) Keys

func (e EnvMap) Keys() []string

func (EnvMap) Lookup

func (e EnvMap) Lookup(_ context.Context, key string) ([]string, bool)

func (*EnvMap) Reset

func (e *EnvMap) Reset()

func (*EnvMap) Set

func (e *EnvMap) Set(value string) error

func (*EnvMap) String

func (e *EnvMap) String() string

type EnvUsage

type EnvUsage struct {
	Key      string
	Default  []string
	Required bool
}

type FlagSetDefinition

type FlagSetDefinition struct {
	Name   string
	Desc   string
	OutVar any
}

type FlagSetsAndDefs

type FlagSetsAndDefs struct {
	Defs []FlagSetDefinition
	Sets []*flag.FlagSet
}

func NewFlagSets

func NewFlagSets(defs []FlagSetDefinition, handling flag.ErrorHandling) *FlagSetsAndDefs

func NewFlagSetsAndDefsFromStruct

func NewFlagSetsAndDefsFromStruct(v any, handling flag.ErrorHandling) *FlagSetsAndDefs

func (*FlagSetsAndDefs) DefinitionFromFlagset

func (fss *FlagSetsAndDefs) DefinitionFromFlagset(fs *flag.FlagSet) (*FlagSetDefinition, bool)

DefinitionFromFlagset returns the FlagSetDefinition for a given flagset

func (*FlagSetsAndDefs) OutVarFromFlagset

func (fss *FlagSetsAndDefs) OutVarFromFlagset(fs *flag.FlagSet) any

func (*FlagSetsAndDefs) Parse

func (fss *FlagSetsAndDefs) Parse(args []string) *CommandIterator

type FloatSlice

type FloatSlice []float64

FloatSlice is a slice where mutliple of the flag appends to the slice Use ResetValues() to clear the slice (for multi-stage flag parsing)

func (*FloatSlice) Reset

func (i *FloatSlice) Reset()

func (*FloatSlice) Set

func (i *FloatSlice) Set(value string) error

Set appends an int64 or returns error if it is an invalid float64. Use Reset() to reset the string slice to an empty slice.

func (*FloatSlice) String

func (i *FloatSlice) String() string

String returns a string with ", " joined between each element

type HelpInfo

type HelpInfo struct {
	Commands []FlagSetDefinition
	Flagsets []*flag.FlagSet

	Progname             string // optional, defaults to os.Args[0]
	About                string
	CommandPrefix        string
	SkipPrintingCommands bool // don't print commands
}

type Int64Slice

type Int64Slice []int64

Int64Slice is a slice where mutliple of the flag appends to the slice Use ResetValues() to clear the slice (for multi-stage flag parsing)

func (*Int64Slice) Reset

func (i *Int64Slice) Reset()

Reset creates a new slice to use

func (*Int64Slice) Set

func (i *Int64Slice) Set(value string) error

Set appends an int64 or returns error if it is an invalid int. Use Reset() to reset the string slice to an empty slice.

func (*Int64Slice) String

func (i *Int64Slice) String() string

String returns a string with ", " joined between each element

type Lookuper

type Lookuper interface {
	Lookup(ctx context.Context, key string) ([]string, bool)
	Keys() []string
}

a dictionary key-value lookup interface

type StringSlice

type StringSlice []string

StringSlice is a slice where mutliple of the flag appends to the slice Use ResetValues() to clear the slice (for multi-stage flag parsing)

func (*StringSlice) Reset

func (i *StringSlice) Reset()

Reset creates a new slice to use

func (*StringSlice) Set

func (i *StringSlice) Set(value string) error

Set appends to the string slice. Use Reset() to reset the string slice to an empty slice.

func (*StringSlice) String

func (i *StringSlice) String() string

String returns a string with ", " joined between each element

type Uint64Slice

type Uint64Slice []uint64

Uint64Slice is a slice where mutliple of the flag appends to the slice Use ResetValues() to clear the slice (for multi-stage flag parsing)

func (*Uint64Slice) Reset

func (i *Uint64Slice) Reset()

Reset creates a new slice to use

func (*Uint64Slice) Set

func (i *Uint64Slice) Set(value string) error

Set appends an int64 or returns error if it is an invalid uint. Use Reset() to reset the string slice to an empty slice.

func (*Uint64Slice) String

func (i *Uint64Slice) String() string

String returns a string with ", " joined between each element

Jump to

Keyboard shortcuts

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