flagtag

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

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

Go to latest
Published: Jul 14, 2014 License: MIT Imports: 8 Imported by: 1

README

flagtag GoDoc Build Status

... a Go command line flag support package

flagtag is a little package that focuses on providing very quick & easy support for connecting command line arguments to variables. The package provides a flag tag and a mechanism for automatically discovering tagged variables for which to set up flags.

By using this mechanism you have to do only very little programming. Variables with either user-provided or default values are readily available in the (tagged) variables after calling the flag package to parse command line arguments.

This flag configurator is based on Go's flag package and facilitates struct field tags. The function scans the provided variables for tags and automatically defines flags for tagged variables based on the content of the flag tag.

When to use this package?

I have created this package specifically for those occasions where you do not want to spend a lot of time defining and fine tuning flags and command line arguments. For example, when creating a rather basic command line tool. The package creates a direct mapping between flags and struct fields. Tags are simply declared using a 'flag'-tag. A single function call will make all arrangements for your tagged variables in the background.

The tag formats

The flag:

flag:"<flag-name>,<default-value>,<usage-description>"

The flag options:

flagopt:"<option>"

Available options:

  • skipFlagValue - Skip testing for flag.Value implementation and immediately continue with primitive types.

A basic example

A basic example follows. Below the example there will be a small description of what the tags accomplish.

package main

import (
        "fmt"
        "github.com/cobratbq/flagtag"
)

type Configuration struct {
        Greeting string `flag:"greet,Hello,The greeting."`
        Name     string `flag:"name,User,The user's name."`
        Times    int    `flag:"times,1,Number of repeats."`
}

func main() {
        var config Configuration
        flagtag.MustConfigureAndParse(&config)

        for i := 0; i < config.Times; i++ {
                fmt.Printf("%s %s!\n", config.Greeting, config.Name)
        }
}

This basic program defines a type that stores some configuration values. Apart from the default values you may wish to provide support for users to provide alternative configurations via command line arguments. Using this package you accomplish the same by defining an appropriate tag.

3 flags are being defined:

  • -greet with default value 'Hello',
  • -name with the default value 'User',
  • -times with the default amount of 1.

Go's flag package also provides a flag -help which prints help information. The last part of the tag defines a usage description that will be shown when help information is printed.

Features

  • Based on the default behavior of flag package.
  • Supports flag's primitive types,
  • and supports types derived from these primitive types.
  • Support for type time.Duration, as this is also supported by flag.
  • Support for pointers and interfaces to variables. (It does not appreciate nil though.)
  • Any types that implement the flag.Value interface.
  • Recursively configuring nested structs (unless they themselves are tagged).
  • Either returning an error or panicking, whatever suits your needs.
  • Do a one-pass configure & parse and be done with it, or configure multiple structs and/or define your own additional flags yourself. You can define your own flags interchangeably with using the flagtag package.
  • Default value for flag.Value implementors. If a default value is provided (i.e. non-zero length) then Set() will be called first with the default value. Then again if the flag was specified as a command line argument.
  • Flag options using the tag 'flagopt'.
    • 'skipFlagValue' can be provided to indicate that we should skip testing for the implementation of flag.Value. This can be used if the struct field accidentally implements flag.Value but you do not want to use it.
  • Support for custom argument slices. (Instead of default CommandLine options.)
  • Support for custom flag set(s).

Under consideration

  • More advanced syntax for 'flagopt' tag for other options.
    • Define syntax for use w/ and w/o value, such that the flagopt tag can be extended at a later time.
    • Separate multiple options with commas.
    • Support for more advanced values using double quotes or something ...

Compatibility notes

flagtag is fully compatible with Go's flag package. It simply uses the facilities offered by the flag package. It is also possible to use flagtag interchangeably with the flag package itself. As with the flag package, you have to be sure that flags have not been parsed yet, while still configuring the flags.

Support for default values for flag.Value interface types is not available in the flag package. The flag package does not provide a parameter for a default value. So, as an addition, flagtag simply calls Set(..) first with the default value if a default value is provided. Then, while parsing values if it turns out that this particular flag is specified, we again call Set(..) for the flag according to the specified program argument.

Documentation

Overview

Package flagtag provides support for creating command line flags by tagging appropriate struct fields with the 'flag' tag.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Configure

func Configure(config interface{}) error

Configure will configure the flag parameters according to the tags of the provided data type. It is allowed to call this method multiple times with different data types. (As long as flag's Parse() method has not been called yet.) Fields without a 'flag' tag or with an empty 'flag' tag will be ignored.

The 'flag' tag consists of 3 parts, similar to the *Var-functions of the flag package. Parts are separated by a comma. The parts are:

  • 1st: flag name
  • 2nd: default value
  • 3rd: usage description

Example:

`flag:"verbose,false,Enable verbose output."`.

This will create a flag 'verbose', which defaults to 'false' and shows usage information "Enable verbose output.".

If an error occurs, this error will be returned and the configuration of other struct fields will be aborted.

func ConfigureAndParse

func ConfigureAndParse(config interface{}) error

ConfigureAndParse will first attempt to configure the flags according to the provided config type. If any error occurs, this error will be returned and the command line arguments will not be parsed. If no error occurs, the command line arguments will be parsed and the config type will contain the result. Using this function may remove the need to even import the flag package at all.

func ConfigureAndParseArgs

func ConfigureAndParseArgs(config interface{}, args []string) error

ConfigureAndParseArgs is like ConfigureAndParse with the addition that it is possible to provide the arguments slice that should be parsed.

func ConfigureFlagset

func ConfigureFlagset(config interface{}, flagset *flag.FlagSet) error

ConfigureFlagset is like Configure but with the added ability to provide a flag set.

func ConfigureFlagsetAndParse

func ConfigureFlagsetAndParse(config interface{}, flagset *flag.FlagSet) error

ConfigureFlagsetAndParse is like ConfigureAndParse with the addition that it is possible to provide the flagset for the configuration.

func ConfigureFlagsetAndParseArgs

func ConfigureFlagsetAndParseArgs(config interface{}, flagset *flag.FlagSet, args []string) error

ConfigureFlagsetAndParseArgs is like ConfigureAndParse with the addition that it is possible to provide both the flagset for configuration and the arguments slice that should be parsed.

func MustConfigure

func MustConfigure(config interface{})

MustConfigure is like Configure, the only difference is that it will panic in case of an error.

func MustConfigureAndParse

func MustConfigureAndParse(config interface{})

MustConfigureAndParse is like ConfigureAndParse, the only difference is that it will panic in case of an error.

Example (Greeter)
// Prepare configuration
var config struct {
	Greeting string `flag:"greet,Hello,The greeting."`
	Name     string `flag:"name,User,The user's name."`
	Times    int    `flag:"times,1,Number of repeats."`
}
MustConfigureAndParse(&config)

// Start greeting
for i := 0; i < config.Times; i++ {
	fmt.Printf("%s %s!\n", config.Greeting, config.Name)
}
Output:

Example (Sleep)
// Prepare configuration
var config struct {
	Sleep   time.Duration `flag:"s,1s,The amount of time to sleep."`
	Verbose bool          `flag:"v,false,Verbose output."`
}
MustConfigureAndParse(&config)

// Start sleeping.
if config.Verbose {
	log.Println("Sleeping for " + config.Sleep.String())
}
time.Sleep(config.Sleep)
if config.Verbose {
	log.Println("Done.")
}
Output:

func MustConfigureAndParseArgs

func MustConfigureAndParseArgs(config interface{}, args []string)

MustConfigureAndParseArgs is like MustConfigureAndParse with the addition that it is possible to provide an arguments slice to be parsed, instead of the default command line arguments slice.

func MustConfigureFlagset

func MustConfigureFlagset(config interface{}, flagset *flag.FlagSet)

MustConfigureFlagset is like Configure, the only difference being that it is possible to provide a custom flagset.

func MustConfigureFlagsetAndParse

func MustConfigureFlagsetAndParse(config interface{}, flagset *flag.FlagSet)

MustConfigureFlagsetAndParse is like MustConfigureAndParse with the addition that it is possible to provide a custom flagset.

func MustConfigureFlagsetAndParseArgs

func MustConfigureFlagsetAndParseArgs(config interface{}, flagset *flag.FlagSet, args []string)

MustConfigureFlagsetAndParseArgs is like MustConfigureAndParse with the addition that it is possible to provide both a custom flagset and the argument slice to be parsed.

Types

type ErrInvalidDefault

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

ErrInvalidDefault is an error type for the case of invalid defaults.

func (*ErrInvalidDefault) Error

func (e *ErrInvalidDefault) Error() string

Error returns the error explaining the bad default value.

Jump to

Keyboard shortcuts

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