flago

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Jan 9, 2024 License: MIT Imports: 11 Imported by: 0

README ¶

test list Go Reference

Parse command line flags into a struct with tags

The library is a wrapper around the standard library's flag package providing a way to parse command line flags into a struct fields

The main features are:

  • Ignore unknown flags
  • Distinguish not passed flags from default values that is difficult with the standard flag package
  • More convenient way to define flags using struct tags
  • Using nested structs for similar flag groups

Example

Define your flags struct with tags:
import (
    flago "github.com/cardinalby/go-struct-flags"
)

type MyFlags struct {
    // Verbose can be filled both by "-v" and "-verbose" flags
    Verbose   int      `flags:"verbose,v" flagUsage:"verbose mode: 1,2,3"`
	
    // Login is optional, it will be set only if passed
    Login     *string  `flag:"login" flagUsage:"user login"`
	
    // FileNames will contain flag.Args() after Parse()
    FileNames []string `flagArgs:"true"`
}

// This is the way to set defaults:
myFlags := MyFlags{}
Create new FlagSet and register the struct:
flagSet := flago.NewFlagSet("myApp", flag.ExitOnError)
if err := flagSet.StructVar(&myFlags); err != nil {
    // error can happen if struct tags are invalid
    panic(err)
}
Parse command line flags:
// Use short form of "-v"
// Normally you would use os.Args[1:] instead of hardcoded values
if err := flagSet.Parse([]string{"-v", "2", "--login", "user1", "file1", "file2"}); err != nil {
    // Parse has default behavior
    panic(err)
}

// myFlags.Verbose == 2
// *myFlags.Login == "user1"
// myFlags.FileNames == []string{"file1", "file2"}
Check if flag is passed

Using pointer fields enables you to distinguish not passed flags from default values:

// Use long form of "--verbose" and don't pass "--login"
if err := flagSet.Parse([]string{"--verbose", "2"}); err != nil {
    // Parse has default behavior
    panic(err)
}

// myFlags.Verbose == 2
// myFlags.Login == nil
// len(myFlags.FileNames) == 0
Set defaults

Unlike std flag package the library doesn't provide a way to explicitly set "default" values.

You can do it in native way just assigning them to struct fields before parsing (both for pointer and non-pointer fields)

defaultLogin := "admin"
myFlags := MyFlags{
    Verbose: 1,
    Login: &defaultLogin,
}

// No flags are passed
if err := flagSet.Parse("file1", "file2"); err != nil {
    // Parse has default behavior
    panic(err)
}

// myFlags.Verbose == 1       <--- hasn't been changed
// *myFlags.Login == "admin"  <--- hasn't been changed
// myFlags.FileNames == []string{"file1", "file2"}
Using nested structs

You can create logically similar flag groups assigning them a prefix using nested structs:

type PersonFlags struct {
    Name  string `flag:"name" flagUsage:"person name"`
    Email string `flag:"email" flagUsage:"person email"`
}
type MyParentFlags struct {
    Sender   PersonFlags `flagPrefix:"sender-" flagUsagePrefix:"sender "`
    Receiver PersonFlags `flagPrefix:"receiver-" flagUsagePrefix:"receiver "`
}

flagSet := NewFlagSet("myApp", flag.ExitOnError)
myFlags := MyParentFlags{}
if err := flagSet.StructVar(&myFlags); err != nil {
    panic(err)
}

if err := flagSet.Parse([]string{
    "--sender-name", "John",
    "--sender-email", "j@email.com",
    "--receiver-name", "Dave",
    "--receiver-email", "d@email.com",
}); err != nil {
    panic(err)
}

// myFlags.Sender.Name == "John"
// myFlags.Sender.Email == "j@email.com"
// myFlags.Receiver.Name == "Dave"
// myFlags.Receiver.Email == "d@email.com"

See tests for more examples.

Configure Parse() behavior

Ignore unknown flags

SetIgnoreUnknown(true) method call will make Parse() ignore unknown flags instead of returning an error.

Allow parsing multiple aliases

SetAllowParsingMultipleAliases(true) method call will make Parse() not return an error if multiple aliases of the same field are passed. The last passed value will be used.

Supported struct tags

To parse flags and args to struct fields you should use StructVar() method.

The struct fields that don't have any "flag" tags will be ignored.

Define named flag(s) for a field

🔻 flag="name"

Defines flag name for a field. Unlike json package, if the name is not set, the field will be ignored.

  • Field should have type supported by flag package or be pointer to such type.
  • If the field is a pointer, it will be set only if the flag is passed to Parse().
  • If it's not a pointer and is the correspondent flag is not passed, its default value will remain.
🔻 flags="name1,name2"

Same as flag but defines multiple comma-separated flag names (aliases) for a field.

  • You should use either flag or flags tag for a field, not both.
  • By default, Parse() will return an error if multiple aliases of the same field are passed. You can change this behavior using SetAllowParsingMultipleAliases(true)
🔸 flagUsage="message"

Defines flag usage message for a field. Should be used only for fields with flag or flags tag.

Assign remaining args

🔻 flagArgs="true"

Field will be filled with flag.Args() (remaining command line args after named flags) after Parse().

  • Other "flag" tags should not be used for such fields.

Describe nested structs

The library parses fields in nested structs if explicitly instructed with flagPrefix tag on a field containing another struct.

🔻 flagPrefix="pref"

Instructs the library to parse fields in nested struct.

  • All resulting flag names (specified by flag and flags tags) in the nested struct will have the specified prefix.
  • With flagPrefix="" nested struct will still be parsed but without using prefix for its fields.
  • The prefix does not affect fields tagged with flagArgs.
🔸 flagUsagePrefix="usage_pref"

This tag is used only for nested struct fields with flagPrefix tag.

Instructs the library to use the specified prefix for flag usage messages of fields in nested struct.

Usage help message

If you use flago.NewFlagSet() constructor, resulting FlagSet will assign own default implementation of Usage that prints help message in the same manner as the standard flag package but grouping aliases assigned to a field using flags tag in one line.

If you use flago.Wrap() constructor, it doesn't override default Usage of the standard FlagSet. You can do it manually: flagSet.Usage = flago.DefaultUsage

Field types support

StructVar() method parses fields and their tags and calls the correspondent FlagSet.***Var() methods depending on the field type.

So fields should have types supported by flag package or be pointers to such types.

Fields implementing flag.Value and func(string) error fields are also supported (but can't be pointers).

Special case

If a field has encoding.TextUnmarshaler interface, it also should implement encoding.TextMarshaler.

The library will call FlagSet.TextVar() on such fields that requires a default "marshaler" value.

Global functions

The library provides global functions with the names matching flago.FlagSet method names for a default flago.CommandLine FlagSet instance in the same manner as the standard flag package does.

Documentation ¶

Index ¶

Constants ¶

This section is empty.

Variables ¶

View Source
var CommandLine = Wrap(flag.CommandLine)

CommandLine is a default FlagSet that is used by the package functions. It's a wrapper around flag.CommandLine to follow the same pattern as in the stdlib.

View Source
var Usage = func() {
	printUsageTitle(CommandLine.FlagSet, os.Args[0])
	PrintDefaults()
}

Functions ¶

func DefaultUsage ¶

func DefaultUsage(flagSet *flag.FlagSet)

DefaultUsage prints the default FlagSet usage to flagSet.Output grouping alternative flag names

func Parse ¶

func Parse() error

Parse parses the command-line flags using the default FlagSet

func PrintDefaults ¶

func PrintDefaults()

PrintDefaults prints the default FlagSet usage to stdout grouping alternative flag names

func PrintFlagSetDefaults ¶

func PrintFlagSetDefaults(flagSet *flag.FlagSet)

PrintFlagSetDefaults prints flag names and usage grouping alternative flag names

func SetAllowParsingMultipleAliases ¶

func SetAllowParsingMultipleAliases(allow bool)

SetAllowParsingMultipleAliases sets the behavior of Parse() when multiple tag names assigned to same field are passed. If `true`, it will be ignored and only the last value will be used. If `false`, Parse() will return an error. Default value is `false`.

func SetIgnoreUnknown ¶ added in v1.0.0

func SetIgnoreUnknown(ignore bool)

SetIgnoreUnknown sets the behavior of Parse() when unknown flags are passed. If `true`, they will be ignored. If `false`, Parse() will return an error. Default value is `false`.

func StripUnknownFlags ¶ added in v1.0.0

func StripUnknownFlags(flagSet *flag.FlagSet, args []string) []string

func StructVar ¶

func StructVar(p any) error

StructVar registers the given struct with the default FlagSet See FlagSet.StructVar

func StructVarWithPrefix ¶

func StructVarWithPrefix(p any, flagsPrefix string) error

StructVarWithPrefix registers the given struct with the default FlagSet using the given prefix for flag names. See FlagSet.StructVarWithPrefix

Types ¶

type FlagSet ¶

type FlagSet struct {
	*flag.FlagSet
	// contains filtered or unexported fields
}

FlagSet is a wrapper around *flag.FlagSet that allows to register structs parsing their fields as flags.

func NewFlagSet ¶

func NewFlagSet(name string, errorHandling flag.ErrorHandling) *FlagSet

NewFlagSet creates a new FlagSet wrapping new flag.FlagSet with the given name and error handling policy and assigns its Usage to the own implementation that groups alternative flag names

func Wrap ¶

func Wrap(stdFlagSet *flag.FlagSet) *FlagSet

Wrap creates a new FlagSet wrapping the given `stdFlagSet` and does not set stdFlagSet.Usage

func (*FlagSet) Parse ¶

func (fls *FlagSet) Parse(arguments []string) error

Parse parses the command-line flags calling Parse on the wrapped FlagSet and then sets values of the registered structs fields for flags that were actually parsed.

func (*FlagSet) PrintDefaults ¶

func (fls *FlagSet) PrintDefaults()

PrintDefaults prints the default FlagSet usage to wrapped FlagSet.Output grouping alternative flag names

func (*FlagSet) SetAllowParsingMultipleAliases ¶

func (fls *FlagSet) SetAllowParsingMultipleAliases(allow bool)

SetAllowParsingMultipleAliases sets the behavior of Parse() when multiple tag names assigned to same field are passed. If `true`, it will be ignored and only the last value will be used. If `false`, Parse() will return an error. Default value is `false`.

func (*FlagSet) SetIgnoreUnknown ¶ added in v1.0.0

func (fls *FlagSet) SetIgnoreUnknown(ignore bool)

SetIgnoreUnknown sets the behavior of Parse() when unknown flags are passed. If `true`, they will be ignored. If `false`, Parse() will return an error. Default value is `false`.

func (*FlagSet) StructVar ¶

func (fls *FlagSet) StructVar(p any) error

StructVar registers the fields of the given struct as a flags

func (*FlagSet) StructVarWithPrefix ¶

func (fls *FlagSet) StructVarWithPrefix(p any, flagsPrefix string) error

StructVarWithPrefix registers the fields of the given struct as a flags with names prefixed with `flagsPrefix`

Jump to

Keyboard shortcuts

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