flags

package module
v0.9.4 Latest Latest
Warning

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

Go to latest
Published: Dec 27, 2023 License: Apache-2.0 Imports: 9 Imported by: 1

README

flags GoDoc

Flags provides an elegant structured mechanism for declaring flags in Go programs. It is a simplified version of the github.com/pborman/options package. By default it wraps the standard flag package but can easily be adjusted to wrap any similar flag package.

Below is a simple program that uses this package:

package main

import (
	"fmt"
	"time"

	"github.com/pborman/flags"
)

type options struct {
	Name    string        `flag:"--name=NAME      name of the widget"`
	Count   int           `flag:"--count=COUNT    number of widgets"`
	Verbose bool          `flag:"-v               be verbose"`
	N       int           `flag:"-n=NUMBER        set n to NUMBER"`
	Timeout time.Duration `flag:"--timeout        duration of run"`
	Lazy    string
}
var opts = options {
	Name: "gopher",
}

func main() {
	args, err := flags.RegisterAndParse(&opts)
	if err != nil {
		fmt.Fprintln(err)
		os.Exit(1)
	}

	if opts.Verbose {
		fmt.Printf("Command line parameters: %q\n", args)
	}
	fmt.Printf("Name: %s\n", opts.Name)
}

The fields in the structure must be compatible with one of the following types:

  • bool
  • int
  • int64
  • float64
  • string
  • uint
  • uint64
  • []string
  • Value (interface { String() string; Set(string) error })
  • time.Duration

The following type is compatible with a string:

type Name string

The following are various ways to use the above declaration.

// Register opts, parse the command line, and set args to the
// remaining command line parameters
args := flags.RegisterAndParse(&opts)

// Validate opts.
err := flag.Validate(&opts)
if err != nil { ... }

// Register opts as command line options.
flags.Register(&opts)

// Register options to a new flag set.
set := flags.NewFlagSet("")
flags.RegisterSet(&options, set)

// Register a new instance of opts
vopts, set := flags.RegisterNew(&opts)
newOpts := vopts.(*options)

Documentation

Overview

Package flags is a simplified version github.com/pborman/options that works with the standard flag package and possibly other flag packages.

Package flags provides a structured interface for flag parsing. It is particularly helpful for parsing an option set more than once and possibly concurrently. This package was designed to make option specification simpler and more concise. It is a wrapper around the the standard flag pacakge.

Option Decorations

Options are declared in a structure that contains all information needed for the options. Each exported field of the structure represents an option. The fields tag is used to provide additional details. The tag contains up to four pieces of information:

Long name of the option (e.g. --name)
Short name of the option (e.g., -n)
Parameter name (e.g. NAME)
Description (e.g., "Sets the name to NAME")

The syntax of a tag is:

[[-]-option[=PARAM]] [--] description

The option must come first in the tag. It is prefixed by "-" or "--". The parameter name is specified by appending =PARAM to one of the declared options (e.g., --option=VALUE). The description is everything following the option declaration(s). The options and description message are delimited by one or more white space characters. An empty option (- or --) terminates option declarations, everything following is the description. This enables the description to start with a -, e.g. "-v -- -v means verbose".

Example Tags

The following are example tags

"--name=NAME sets the name to NAME"
"-n=NAME     sets the name to NAME"
"--name      sets the name"

A tag of just "-" causes the field to be ignored an not used as an option. An empty tag or missing tag causes the tag to be auto-generated.

Name string -> "--name unspecified"
N int       -> "-n unspecified"

Types

The fields of the structure must be compatible with one of the folllowing types:

bool
int
int64
float64
string
uint
uint64
[]string
Value
time.Duration

Example Structure

The following structure declares 7 options and sets the default value of Count to be 42.

type theOptions struct {
    Name    string        `flag:"--name=NAME   name of the widget"`
    Count   int           `flag:"--count=COUNT number of widgets"`
    Verbose bool          `flag:"-v            be verbose"`
    N       int           `flag:"-n=NUMBER     set n to NUMBER"`
    Timeout time.Duration `flag:"--timeout     duration of run"`
    List    []string      `flag:"--list=ITEM   add ITEM to the list"`
    Lazy    string        // defaults to --lazy=VALUE
}
var myOptions = theOptions {
    Count: 42,
}

Usage

The following are various ways to use the above declaration.

// Register myOptions, parse the command line, and set args to the
// remaining command line parameters
args, err := flags.RegisterAndParse(&myOptions)

// Validate myOptions.
err := flags.Validate(&myOptions)
if err != nil { ... }

// Register myOptions as command line flags.
flags.Register(&myOptions)

// Register myOptions as a new flag Set.
set := flag.NewFlagSet("", flag.ExitOnError)
flags.RegisterSet(&myOptions, set)

// Register a new instance of myOptions
vopts, set := flags.RegisterNew(&myOptions)
opts := vopts.(*theOptions)

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Dup

func Dup(i any) any

Dup returns a shallow duplicate of i or panics. Dup panics if i is not a pointer to struct or has an invalid flag tag. Dup does not copy non-exported fields or fields whose flag tag is "-".

Dup is normally used to create a unique instance of the set of options so i can be used multiple times.

func Help

func Help(w io.Writer, cmd, parameters string, i any)

Help writes help information for the flag set specified by i where i is a pointer to a structure as described above. As an example:

opts := &struct {
	Alpha   string   `flag:"--alpha=LEVEL set the alpha level"`
	Beta    int      `flag:"--beta=N      set beta to N"`
	Float   float64  `flag:"-f=RATE       set frame rate to RATE"`
	Fancy   bool     `flag:"--the_real_fancy_and_long_option yes or no"`
	Verbose bool     `flag:"-v            be verbose"`
	List    []string `flag:"--list=ITEM   add ITEM to list"`
}{}
Help(os.Stderr, "xyzzy", "...", opts)

Will write the following to standard error:

Usage: xyzzy [--alpha=LEVEL] [--beta=N] [ -f=RATE] [--the_real_fancy_and_long_option] [ -v] [--list=ITEM] ...
--alpha=LEVEL  set the alpha level
--beta=N       set beta to N
 -f=RATE       set frame rate to RATE
--list=ITEM    add ITEM to list
--the_real_fancy_and_long_option
               yes or no
 -v            be verbose

If cmd is the empty string the initial line will not be printed.

func Lookup

func Lookup(i any, option string) any

Lookup returns the value of the field in i for the specified option or nil. Lookup can be used if the structure declaring the options is not available. Lookup returns nil if i is invalid or does not have an option named option.

Example

Fetch the verbose flag from an anonymous structure:

i, set := flags.RegisterNew(&struct {
	Verbose bool `flag:"--verbose -v be verbose"`
})
set.Parse(args)
v := flags.Lookup(i, "verbose").(bool)

func Parse

func Parse() ([]string, error)

Parse calls flag.Parse and returns flag.Args().

func Register

func Register(i any)

Register registers the fields in i with the standard command-line option set. It panics for the same reasons that RegisterSet panics.

func RegisterAndParse

func RegisterAndParse(i any) ([]string, error)

RegisterAndParse and calls Register(i), flag.Parse(), and returns flag.Args().

func RegisterSet

func RegisterSet(name string, i any, set FlagSet) error

RegisterSet registers the fields in i, to the flag.FlagSet set. RegisterSet returns an error if i is not a pointer to struct, has an invalid flag tag, or contains a field of an unsupported option type. RegisterSet ignores non-exported fields or fields whose flag tag is "-".

If a Flags field is encountered, name is the name used to identify the set when parsing options.

See the package documentation for a description of the structure to pass to RegisterSet.

func SubRegisterAndParse

func SubRegisterAndParse(i any, args []string) ([]string, error)

SubRegisterAndParse is similar to RegisterAndParse except it is provided the arguments as args and on error the error is returned rather than written to standard error and the exiting the program. This is done by creating a new flag set, registering i with that set, and then calling Parse on the set with args.

SubRegisterAndParse is useful when you want to parse arguments other than os.Args (which is what RegisterAndParse does).

The first element of args is equivalent to a command name and is not parsed.

EXAMPLE:

func nameCommand(args []string) error {
	opts := &struct {
		Name string `flag:"--name NAME the name to use"`
	}{
		Name: "none",
	}
	// If args does not include the subcommand name then prepend it
	args = append([]string{"name"}, args...)

	args, err := flags.SubRegisterAndParse(opts, args)
	if err != nil {
		return err
	}
	fmt.Printf("The name is %s\n", opts.Name)
	fmt.Printf("The parameters are: %q\n", args)
}

func UsageLine added in v0.9.0

func UsageLine(cmd, parameters string, i any) string

UsageLine returns the usage line for the flag set specified by i. A usage line looks like:

cmd [--first=VALUE] ... [--last] parameters

cmd and parameters can be empty strings.

func Validate

func Validate(i any)

Validate validates i as a set of options or returns an error.

Use Validate to assure that a later call to one of the Register functions will not panic. Validate is typically called by an init function on structures that will be registered later.

Types

type FlagSet

type FlagSet interface {
	Parse([]string) error
	Args() []string
	NArg() int
	SetOutput(io.Writer)
	DurationVar(p *time.Duration, name string, value time.Duration, usage string)
	StringVar(p *string, name string, value string, usage string)
	IntVar(p *int, name string, value int, usage string)
	Int64Var(p *int64, name string, value int64, usage string)
	UintVar(p *uint, name string, value uint, usage string)
	Uint64Var(p *uint64, name string, value uint64, usage string)
	Float64Var(p *float64, name string, value float64, usage string)
	BoolVar(p *bool, name string, value bool, usage string)
}

A FlagSet implements a set of flags. flag.FlagSet from the standard flag package implements FlagSet. The FlagSet must also have the method:

Var(v valueType, name, usage string)

Where valueType implements the Value interface (which flag.Value does). We cannot put Var in the interface due to the Value type.

var (
	NewFlagSet          = func(name string) FlagSet { return flag.NewFlagSet(name, flag.ContinueOnError) }
	CommandLine FlagSet = flag.CommandLine
)

NewFlagSet and CommandLine can be replaced to use a different flag package. They default to the standard flag package.

func RegisterNew

func RegisterNew(name string, i any) (any, FlagSet)

RegisterNew creates a new flag.FlagSet, duplicates i, calls RegisterSet, and then returns them. RegisterNew should be used when the options in i might be parsed multiple times requiring a new instance of i each time.

type Value

type Value interface {
	String() string
	Set(string) error
}

Value is the interface to the dynamic value stored in a flag. (The default value is represented as a string.) Value is a copy of flag.Value

Jump to

Keyboard shortcuts

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