commandline

package module
v0.0.5 Latest Latest
Warning

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

Go to latest
Published: Dec 4, 2020 License: MIT Imports: 5 Imported by: 0

README

commandline

A command oriented command line parser.

Description

Central Parser type registers Commands with Handlers. Command can have optional or required Param definitions which can write directly to Go values and be analyzed in a Handler.

Commands can have Commands of their own allowing for a Command hierarchy.

Params can be Prefixed (specified by name) or Raw (specified by index and addressable by name).

Example with panic functions:

// New parser.
cl := New()
// To store value parsed for foo's bar param.
var barVal string
// Add a special unnamed command to root to hold 'global' params.
// Directly register a 'verbose' param on it. 
cl.MustAddCommand("", "", nil).MustAddParam("verbose", "v", "Verbose output.", false, nil)
// Add a 'foo' command and directly register a 'bar' prefixed param on it.
cl.MustAddCommand("foo", "Do the foo.", nil).MustAddParam("bar", "r", "Enable bar.", true, &barVal)
// Add a 'baz' command and directly register a 'bat' raw param on it.
cl.MustAddCommand("baz", "Do the baz.", nil).MustAddRawParam("bat", "Enable bat.", false, nil)
// Parse global verbose flag, execute 'foo' command and pass it '--bar' param 
// with value 'bar' that is written to &barVal, execute baz command and read 
// 'bat' as its' bat param value.
cl.Parse([]string{"--verbose", "foo", "--bar", "bar", "baz", "bat"})
fmt.Println(cl.Print())
// Output:
// --verbose       -v      Verbose output.

// foo     Do the foo.
//         --bar   -r      (string)        Enable bar.

// baz     Do the baz.
//         [bat]           Enable bat.

Example with error functions:


// Some variables that will receive values.
var (
	verbose     bool
	projectname string
	projectdir  string
)

// cmdGlobal gets invoked for "Global params" unnamed function.
func cmdGlobal(params Context) error {
	verbose = params.Parsed("verbose")
	return nil
}

// cmdCreate gets invoked for "Create project" command.
func cmdCreate(params Context) error {
	CreateProject(projectname, projectdir)
	return nil
}

// Create new parser. 
parser := New()

// Parser allows for a single unnamed command in root command definitions to
// allow the command line not to start with a command but parameters instead.
// If it is registered it must be the root command of all commands.
//
// Register a special "global flags" handler command that is automatically
// invoken if any of it's flags is specified by command line arguments and
// skipped if no "global flags" is given in arguments and the command line
// starts with a command.
cmd, err := parser.AddCommand("", "Global params", cmdGlobal)

// Register an optional "verbose" param on "global flags" command.
// It will not write to any Go value as pointer to one is nil.
cmd.AddParam("verbose", "v", "Be more verbose.", false, nil)

// Register a sub command for the "global flags" command so it can be invoken
// via arguments regardless if "global flags" executed.
cmd, err := cmd.AddCommand("create" "Create a project", cmdCreate)

// Add a prefixed parameter to "Create project" command that is required and
// converts an argument following the param to registered Go value projectname.
cmd.AddParam("name", "n", "Project name", true, &projectname)

// Add an optional raw param that isn't prefixed but is instead treated as a
// param value itself.
cmd.AddRawParam("directory", "Specify project directory", false, &projectdir)

// Parse command line.
if err := parser.Parse(os.Args[1:]); err != nil {
	log.Fatal(err)
}

Valid command line for this example would be: -v create --name myproject /home/me/myproject

Status

Working as intended. No API changes except additions planned.

What's left:

  • Reflect incomming, will replace JSON with a light string converter.
  • Maybe abstract value parsing with codecs.
  • Maybe support complex structures as parameters.
  • Maybe add a reflector from Go composites to preconstructed Parser.
  • Maybe go:generate command handlers from a Parser instance.

License

MIT

See included LICENSE file.

Documentation

Overview

Package commandline implements a command line parser.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrNoArgs is returned by Parse if no arguments were specified on
	// command line and there are defined Commands or Params.
	ErrNoArgs = errors.New("commandline: no arguments")
	// ErrInvalidName is returned by Add* methods when an invalid Command or
	// Param long or short name is specified.
	ErrInvalidName = errors.New("commandline: invalid name")
	// ErrInvalidValue is returned by Add* methods or during parsing if an
	// invalid parameter is given for a Param value, i.e. not a valid pointer
	// to a Go value.
	ErrInvalidValue = errors.New("commandline: invalid value")
)

Functions

This section is empty.

Types

type Command

type Command struct {
	Params   // Params are this Command's Params.
	Commands // Commands are this Command's Commands.
	// contains filtered or unexported fields
}

Command is a command definition. A Command can contain sub-Commands and propagate Parser args further down the Commands chain. It can have zero or more defined Param instances in its' Params.

func (*Command) Print added in v0.0.4

func (c *Command) Print() string

Print prints Commands contained in this Command.

type CommandFunc

type CommandFunc = func(Context) error

CommandFunc is a prototype of a function that handles the event of a Command being parsed from command line arguments.

Parser parses Command's Params and pauses parsing when it finds next Command in arguments or it exhausts arguments, invokes parsed Command's CommandFunc carrying parsed Params then either continues parsing if the handler returns nil or stops and returns the error that the handler returned back to the Parse method whose caller is responsible for interpreting that error.

If the invoked Command has any raw Params registered, parsing will not continue after CommandFunc invocation.

type Commands

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

Commands holds a set of Commands with a unique name.

func (*Commands) AddCommand

func (c *Commands) AddCommand(name, help string, f CommandFunc) (*Command, error)

AddCommand registers a new Command under specified name and help text that invokes f when parsed from arguments if it is not nil. Name is the only required parameter.

If Commands is the root set in a Parser it can register a single Command with an empty name to be an unnamed container in a global params pattern.

If a registration error occurs it is returned with a nil *Command.

func (*Commands) GetCommand

func (c *Commands) GetCommand(name string) (cmd *Command, ok bool)

GetCommand returns a *Command by name if found and truth if found.

func (*Commands) MustAddCommand added in v0.0.2

func (c *Commands) MustAddCommand(name, help string, f CommandFunc) *Command

MustAddCommand is like AddCommand except the function panics on error. Returns added *Command.

func (*Commands) MustGetCommand added in v0.0.2

func (c *Commands) MustGetCommand(name string) *Command

MustGetCommand is like GetCommand but panics if Command is not found.

type Context added in v0.0.3

type Context interface {
	// Parsed will return if the param under specified long name was parsed.
	Parsed(string) bool
	// RawValue will return the parsed string value of param as specified on
	// command line, if parsed.
	RawValue(string) string
	// RawArgs will return a slice of raw values if this CommandFunc has no
	// defined params and custom handles params.
	RawArgs() []string
	// Command returns the parent Command of these Params.
	Command() *Command
}

Context is a CommandFunc context.

It provides access to params associated with the Command and the definition and post-parse state of the Command itself.

type Param

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

Param defines a Command parameter contained in a Params.

func (*Param) Value

func (p *Param) Value() interface{}

Value returns the Param value.

type Params

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

A Params defines a set of Command Params unique by long name.

func (*Params) AddParam

func (p *Params) AddParam(long, short, help string, required bool, value interface{}) error

AddParam registers a new Param in these Params.

Long param name is required, short is optional and can be empty, as is help.

If required is specified value must be a pointer to a supported Go value which will be updated to a value parsed from an argument following param. If a required Param or its' value is not found in command line args an error is returned.

If Param is not marked as required, specifying a value parameter is optional but dictates that: If nil, a value for the Param will not be parsed from args. If valid, the parser will parse the argument following the Param into it.

If an error occurs Param is not registered.

func (*Params) AddRawParam

func (p *Params) AddRawParam(name, help string, required bool, value interface{}) error

AddRawParam registers a raw Param under specified name which must be unique in long Params names. Raw params can only be defined after prefixed params or only raw params. Calls to AddParam after AddRawParam will error.

Parsed arguments are applied to raw Params in order as they are defined. If value is a pointer to a valid Go value argument will be converted to that Go value. Specifying a value is optional and if nil, parsed argument will not be parsed into the value.

A single non-required raw Param is allowed and it must be the last one.

If an error occurs it is returned and the Param is not registered.

func (*Params) Command added in v0.0.4

func (p *Params) Command() *Command

Command returns the parent Command of these Params.

func (*Params) MustAddParam added in v0.0.2

func (p *Params) MustAddParam(long, short, help string, required bool, value interface{}) *Command

MustAddParam is like AddParam except the function panics on error. Returns a Command that the param was added to.

func (*Params) MustAddRawParam added in v0.0.2

func (p *Params) MustAddRawParam(name, help string, required bool, value interface{}) *Command

MustAddRawParam is like AddRawParam except the function panics on error. Returns a Command that the param was added to.

func (*Params) ParamCount added in v0.0.2

func (p *Params) ParamCount() int

ParamCount returns number of defined params.

func (*Params) Parsed

func (p *Params) Parsed(name string) bool

Parsed returns if the param under specified name was parsed. If the Param under specified name is not registered, returns false.

func (*Params) RawArgs

func (p *Params) RawArgs() []string

RawArgs returns arguments of raw Params in order as passed on command line. It will be an empty slice if no arguments were passed to the param or the param is not raw type.

func (*Params) RawValue added in v0.0.2

func (p *Params) RawValue(name string) string

RawValue returns raw string value passed to a param, which could be empty.

It will return a non-empty value if param under specified name was registered, accepts an optional or required argument and was parsed from command line arguments.

type Parser

type Parser struct {

	// Commands is the root command set.
	//
	// Root Commands as an exception allows a single Command
	// with an empty name that serves as "global flag" container.
	Commands
	// contains filtered or unexported fields
}

Parser is a command line parser. Its' Parse method is to be invoked with a slice of command line arguments passed to program. For example:

err := Parser.Parse(os.Args[1:])

It is command oriented, meaning that one or more Command instances can be defined in Parser's Commands which when parsed from command line arguments invoke CommandFuncs registered for those Command instances. Command can have its' own Commands so a Command hierarchy can be defined.

Root Commands, as an exception, allow for one Command with an empty name to be defined. This is to allow that program args need not start with a Command and to allow Params to be passed first which can act as "global". e.g. "--verbose list users"

Command can have one or more Param instances defined in its' Params which can have names, help text, be required or optional and have an optional pointer to a Go value which is written from a value following Param in command line arguments.

If a pointer to a Go value is registered with a Param, the Param will require an argument following it that the parser will try to convert to the Go value registered with Param. Otherwise the Param will act as a simple flag which can be checked if parsed in the handler by checking the result of handler's Params.Parsed("long param name").

Parser supports prefixed and raw params which can be combined on a Command with a caveat that the Command that has one or more raw params registered cannot have sub-Commands because of ambiguities in parsing command names and raw parameters as well as the fact that one last raw param can be optional.

Prefixed params are explicitly addressed on a command line and can have short and long forms. They can be marked optional or required and be registered in any order, but before any raw params.

Short Param names have the "-" prefix, can be one character long and can be combined together following the short form prefix if none of the combined Params require a Param Value. They are optional per Param.

Long Param names have the "--" prefix and cannot be combined.

Raw params are not addressed but are instead matched against registered raw Params in order of registration as they appear on command line, respectively.

Prefixed and raw params can both be registered for a Command but raw params must be registered last and specified after prefixed Params on the command line. e.g. "rmdir -v /home/me/stuff" where "rmdir" is a command, "-v" is a prefixed param and "/home/me/stuff" is a raw parameter.

If Params are defined as optional they do not cause a parse error if not parsed from program args and return a parse error if defined as required and not parsed from command line.

Command can have a CommandFunc registered optionaly so that a Command can serve solely as sub-Command selector. For more details see CommandFunc.

If no Params were defined on a Command all command line arguments following the command invocation will be passed to Command handler via Params.RawArgs.

If no params were defined on a Command and the command has no CommandFunc registered an error is returned.

Example
cl := New()
var barVal string
cl.MustAddCommand("", "", nil).MustAddParam("verbose", "v", "Verbose output.", false, nil)
cl.MustAddCommand("foo", "Do the foo.", nil).MustAddParam("bar", "r", "Enable bar.", true, &barVal)
cl.MustAddCommand("baz", "Do the baz.", nil).MustAddRawParam("bat", "Enable bat.", false, nil)
cl.Parse([]string{"--verbose", "foo", "--bar", "bar", "baz", "bat"})
fmt.Println(cl.Print())

func New

func New() *Parser

New returns a new instance of *Parser.

func (*Parser) Parse

func (p *Parser) Parse(args []string) error

Parse parses specified args, usually invoked as "Parse(os.Args[1:])". If a parse error occurs or an invoked Command handler returns an error it is returned. Returns ErrNoArgs if args are empty and there are defined Commands or Params.

func (Parser) Print

func (p Parser) Print() string

Print prints the Parser as currently configured. Returns output suitable for terminal display.

Jump to

Keyboard shortcuts

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