Skip to content

A very simple CMD line argument parser that allows for arguments to be specified from both the CLI and a TOML config file.

License

Notifications You must be signed in to change notification settings

barbell-math/smoothbrain-argparse

Repository files navigation

sbargp

import "github.com/barbell-math/smoothbrain-argparse"

A very simple CMD line argument parser that allows for arguments to be specified from both the CLI and a TOML config file.

Example (Simple)

package main

import (
	"flag"
	"fmt"
	"reflect"
)

type exampleConf struct {
	StoreName    string
	NumItems     int
	NumLocations int
	HasFreeFood  bool
	Department   struct {
		Name      string
		Specialty string
	}
	Vegies []string
	Fruits map[string]struct {
		Yummy bool
		Color string
	}
}

func main() {
	var c exampleConf
	err := Parse(
		&c,
		[]string{
			// Normally these would be os.Args[1:] but for the example we
			// provide a list of strings.
			"-StoreName", "kings",
			"-NumLocations", "3",
			"-conf", "./bs/example.toml",
		},
		ParserOpts[exampleConf]{
			ProgName:     "example",
			RequiredArgs: []string{"StoreName"},
			ArgDefsSetter: func(conf *exampleConf, fs *flag.FlagSet) error {
				// It is generally recommented (though not enforced) to name
				// CMD line arguments the same as the keys in the TOML file.
				fs.StringVar(&c.StoreName, "StoreName", "", "a string")
				fs.IntVar(&c.NumItems, "NumItems", 1, "a int")
				fs.IntVar(&c.NumItems, "NumLocations", 0, "a int")

				// Defaults for non-FlagSet arguments can be set here as well
				c.HasFreeFood = true // :)
				return nil
			},
		},
	)

	fmt.Println("Parsing error: ", err)

	fmt.Println("Parsed conf:")
	typ, val := reflect.TypeOf(c), reflect.ValueOf(c)
	for i := 0; i < typ.NumField(); i++ {
		fmt.Printf("  %-20s → %v\n", typ.Field(i).Name, val.Field(i).Interface())
	}

}

Output

Parsing error:  <nil>
Parsed conf:
  StoreName            → kings
  NumItems             → 3
  NumLocations         → 0
  HasFreeFood          → true
  Department           → {produce fruit and vegetables}
  Vegies               → [potato carrot chicken]
  Fruits               → map[apple:{true red} banana:{true yellow} orange:{true orange}]

Index

Variables

var (
    InvalidArgumentErr         = errors.New("Invalid argument")
    InvalidConfFileErr         = errors.New("Invalid conf file")
    MissingRequiredArgsErr     = errors.New("Missing required args")
    InvalidValuesInConfFileErr = errors.New("Invalid values in conf file")
)

var (
    EnvVarNotSetErr = errors.New(
        "The supplied environment variable was not set",
    )
)

var (
    MissingLeadingZerosErr = errors.New(
        "Leading zeros in date-time values cannot be left off",
    )
)

func DB

func DB(fs *flag.FlagSet, dc *DBConf, longArgStart string, _defaults DBConf)

Sets five flags that are intended to be used to access a database:

  • <longArgStart>.User
  • <longArgStart>.PswdEnvVar
  • <longArgStart>.Host
  • <longArgStart>.Port
  • <longArgStart>.Name

The longArgStart argument should be used to make sure the CMD line argument has the same name as the TOML key.

func Logging

func Logging(fs *flag.FlagSet, lc *LoggingConf, longArgStart string, _defaults LoggingConf)

Sets five flags:

  • <longArgStart>.SaveTo
  • l
  • <longArgStart>.Name
  • <longArgStart>.MaxNumLogs
  • <longArgStart>.MaxLogSizeBytes
  • <longArgStart>.Verbose
  • v

`<longArgDir>.SaveTo` and `l` will both set the directory to place any log files in. The flag parser will check that the dir exists. `<longArgStart>.Verbose` and `v` will be set by Verbosity.

The longArgStart argument should be used to make sure the CMD line argument has the same name as the TOML key.

func Parse

func Parse[T any](conf *T, cliArgs []string, opts ParserOpts[T]) error

Takes a sequence of CMD line arguments and parses them. The supplied `conf` value will be populated with any values.

A `conf` argument will be added that will accept a path to a TOML config file. This TOML config file will be treated as another source of arguments, and the `conf` value will be populated with the contents of that file. The burnt sushi TOML parser is used internally, refer to it's documentation for things like struct field tags.

The arguments that are present in the TOML config file will take precedence over all CMD line arguments.

func Verbosity[T constraints.Signed](fs *flag.FlagSet, val *T, longArgStart string, _default T)

Sets two flags:

  • <longArgStart>.Verbose
  • v

`<longArgStart>.Verbose` and `v` will both increment the same underlying value by one every time they are supplied. Both `v` and `<longArgStart>.Verbose` can be supplied multiple times.

The longArgStart argument should be used to make sure the CMD line argument has the same name as the TOML key. If verosity is a top level key then set longArgStart to an empty string.

type AbsDir

Can be used to represent an absolute path to a dir in a config. When unmarshaling the path will be made absolute if it is not already.

type AbsDir string

func (*AbsDir) UnmarshalText

func (a *AbsDir) UnmarshalText(data []byte) error

Checks that the supplied data is a valid path to a dir and if so resolves the absolute path and sets the underlying value absolute to the path.

type AbsFile

Can be used to represent an absolute path to a file in a config. When unmarshaling the path will be made absolute if it is not already.

type AbsFile string

func (*AbsFile) UnmarshalText

func (a *AbsFile) UnmarshalText(data []byte) error

Checks that the supplied data is a valid path to a file and if so resolves the absolute path and sets the underlying value absolute to the path.

type DBConf

type DBConf struct {
    User       string
    PswdEnvVar EnvVar
    Host       string
    Port       uint16
    Name       string
}

type Dir

Can be used to represent a path to a dir in a config

type Dir string

func (*Dir) UnmarshalText

func (d *Dir) UnmarshalText(data []byte) error

Checks that the supplied data is a valid path to a dir and if so sets the underlying value to the path.

type EnvVar

Can be used to represent a path to an environment variable in a config. The value of the config entry will be set to the value of the environment variable, if it exists. If it does not exist an error is returned.

type EnvVar string

func (*EnvVar) UnmarshalText

func (e *EnvVar) UnmarshalText(data []byte) error

Checks that the supplied data is a valid path to a file and if so sets the underlying value to the path.

type File

Can be used to represent a path to a file in a config

type File string

func (*File) UnmarshalText

func (f *File) UnmarshalText(data []byte) error

Checks that the supplied data is a valid environment variable and if so sets the underlying value to the value of the environment variable.

The type of function that flag.Func accepts

type FlagSetFunc func(arg string) error

func Float

func Float[T constraints.Float](val *T, _default T) FlagSetFunc

Useful for parsing a specific kind of float from the CMD line since flag does not have a generic version yet. (It only provides float64)

func FromTextUnmarshaler[T any, I interface {
    *T
    encoding.TextUnmarshaler
}](val *T, _default T) FlagSetFunc

Useful when a type in the supplied config value is a custom type that implements the encoding.TextUnmarshaler interface which the TOML parser will use when parsing values.

This is provided as a way to make sure the CMD line args can be parsed in the same manner as the values in the TOML file.

func Int

func Int[T constraints.Signed](val *T, base int, _default T) FlagSetFunc

Useful for parsing a specific kind of int from the CMD line since flag does not have a generic version yet. (It only provides int)

func Time

func Time(val *time.Time, _default time.Time) FlagSetFunc

Useful for parsing a time value from the CMD line. The format will one of the [allowd date-time formats in TOML].

func Uint

func Uint[T constraints.Unsigned](val *T, _default T, base int) FlagSetFunc

Useful for parsing a specific kind of uint from the CMD line since flag does not have a generic version yet. (It only provides uint)

type LoggingConf struct {
    Verbosity       int
    SaveTo          Dir
    Name            string
    MaxNumLogs      int
    MaxLogSizeBytes int
}

type ParserOpts[T any] struct {
    // The program name that should be printed out on the help menu in the
    // following format: `Usage of <program name>`. If left empty
    // <program name> will be replaced with `this program`.
    ProgName string
    // All arguments provided in this list must be provided. Arguments can
    // be provided in either the CMD line, in a TOML conf file, or both. If
    // an argument is provided in either place it will be marked as present.
    RequiredArgs []string
    // The function that allows the user (you) to define the CMD line
    // arguments. The CMD line argument parameters can be named the same as
    // the keys in the TOML file. Naming the parameters the same as their
    // associated key in the TOML file is generally recommended, and may be
    // necessary to make it so arguments in the [RequiredArgs] list are seen
    // as present from both the CMD line and TOML conf file. Hierarchical
    // keys of the TOML file are separated by a '.'.
    //
    // This function can also be used to set default values. Assuming that
    // you don't have a FlagSet argument for a given value in conf, simply
    // set that value to the default value. If a FlagSet argument
    // corresponds to a value in conf then the default value will be
    // whatever is defined by the FlagSet method.
    ArgDefsSetter func(conf *T, fs *flag.FlagSet) error
}

Generated by gomarkdoc

Helpful Developer Cmds

To build the build system:

go build -o ./bs/bs ./bs

The build system can then be used as usual:

./bs/bs --help
./bs/bs buildbs # Builds the build system!

About

A very simple CMD line argument parser that allows for arguments to be specified from both the CLI and a TOML config file.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages