flage

package module
v0.0.0-...-a2bd8d1 Latest Latest
Warning

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

Go to latest
Published: Mar 27, 2024 License: Apache-2.0 Imports: 13 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

This section is empty.

Functions

func DefaultPreviewTemplateFuncs

func DefaultPreviewTemplateFuncs(keys *[][2]string) template.FuncMap

func DefaultTemplateFuncs

func DefaultTemplateFuncs() template.FuncMap

func ExtractEnvKeysFromConfigFile

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

ExtractEnvKeysFromConfigFile returns the environment keys that are read from a given config file.

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 ParseConfigFile

func ParseConfigFile(file string) error

ParseConfigFile reads a given filepath and applies command line parsing to it. This is a quick and easy way to provide file-based configuration, a la pip.

If you want to only read the file, use ReadConfig instead.

Comments are lines that start with a '#' (and not in the middle).

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

This is also templated, so the following variables are available:

- configDir: the directory of the config file

The following functions are available:

- env(key): returns the value of the environment variable - envOr(key, def): returns the value of the environment variable or the default value - envOrError(key, msg): returns the value of the environment variable or errors with msg

Example:

-load {{.configDir}}/file.txt -secret {{env "SECRET"}} -port {{envOr "PORT" "8080"}}

func ParseEnvFile

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

ParseEnvFile 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 PreviewConfig

func PreviewConfig(configPath string, data string) (string, error)

PreviewConfig returns the contents of data by passing that is ready to pass to flag.FlagSet.Parse(...)

func PreviewConfigFile

func PreviewConfigFile(file string) (string, error)

PreviewConfigFile returns the contents of file by passing that is ready to pass to flag.FlagSet.Parse(...)

func ReadConfig

func ReadConfig(configPath string, data string) ([]string, error)

ReadConfigFile returns args to parse from a given file path

Comments are lines that start with a '#' (and not in the middle).

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

This is also templated, so the following variables are available:

- configDir: the directory of the config file

The following functions are available:

- env(key): returns the value of the environment variable - envOr(key, def): returns the value of the environment variable or the default value - envOrError(key, msg): returns the value of the environment variable or errors with msg

Example:

-load {{.configDir}}/file.txt -secret {{env "SECRET"}} -port {{envOr "PORT" "8080"}}

func ReadConfigFile

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

ReadConfigFile returns args to parse from a given file. If you have already opened the file, use ReadConfig instead.

Comments are lines that start with a '#' (and not in the middle).

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

This is also templated, so the following variables are available:

- configDir: the directory of the config file

The following functions are available:

- env(key): returns the value of the environment variable - envOr(key, def): returns the value of the environment variable or the default value

Example:

-load {{.configDir}}/file.txt -secret {{env "SECRET"}} -port {{envOr "PORT" "8080"}}

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 SourceEnvFile

func SourceEnvFile(file string) error

SourceEnvFile parses a env file via ParseEnvFile and sets the process' environment variables

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. 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

If encoding.TextUnmarshler is used then a method on the struct must be used to provide defaults to encoding.TextUnmarshaler:

func (m *myOptions) MarshalFlagField(field string) encoding.TextMarshaler {
  if field == "myTextUnmarshalerField" {
    return big.NewInt(123)
  }
  return nil // panics will happen if we return nil
}

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()

Types

type FieldTextMarshaler

type FieldTextMarshaler interface {
	MarshalFlagField(field string) encoding.TextMarshaler
}

FieldTextMarshaler is the interface a struct needs to implement if it has fields of type encoding.TextUnmarshaler to return the appropriate default value.

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 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 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 TemplateConfigRenderer

type TemplateConfigRenderer struct {
	Data  map[string]string
	Funcs template.FuncMap
}

TemplateConfigRenderer manages rendering of config files that is used by other helper functions:

- ParseConfigFile - ReadConfigFile - ReadConfig - ExtractEnvKeysFromConfigFile - PreviewConfigFile - PreviewConfig

This allows you to set your own template variables and functions. Use DefaultTemplateFuncs to get default template functions used.

func (*TemplateConfigRenderer) Render

func (r *TemplateConfigRenderer) Render(data string, configPath string) (string, error)

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