cmdline

package
v0.1.19 Latest Latest
Warning

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

Go to latest
Published: Mar 14, 2024 License: BSD-3-Clause Imports: 23 Imported by: 237

Documentation

Overview

Package cmdline implements a data-driven mechanism for writing command-line programs with built-in support for help.

Commands are linked together to form a command tree. Since commands may be arbitrarily nested within other commands, it's easy to create wrapper programs that invoke existing commands.

The syntax for each command-line program is:

command [flags] [subcommand [flags]]* [args]

Each sequence of flags is associated with the command that immediately precedes it. Flags registered on flag.CommandLine are considered global flags, and are allowed anywhere a command-specific flag is allowed.

Pretty usage documentation is automatically generated, and accessible either via the standard -h / -help flags from the Go flag package, or a special help command. The help command is automatically appended to commands that already have at least one child, and don't already have a "help" child. Commands that do not have any children will exit with an error if invoked with the arguments "help ..."; this behavior is relied on when generating recursive help to distinguish between external subcommands with and without children.

Pitfalls

The cmdline package must be in full control of flag parsing. Typically you call cmdline.Main in your main function, and flag parsing is taken care of. If a more complicated ordering is required, you can call cmdline.Parse and then handle any special initialization.

The problem is that flags registered on the root command must be merged together with the global flags for the root command to be parsed. If flag.Parse is called before cmdline.Main or cmdline.Parse, it will fail if any root command flags are specified on the command line.

Index

Constants

View Source
const ErrUsage = ErrExitCode(2)

ErrUsage indicates an error in command usage; e.g. unknown flags, subcommands or args. It corresponds to exit code 2.

Variables

This section is empty.

Functions

func ExitCode

func ExitCode(err error, w io.Writer) int

ExitCode returns the exit code corresponding to err.

0:    if err == nil
code: if err is ErrExitCode(code)
1:    all other errors

Writes the error message for "all other errors" to w, if w is non-nil.

func HideGlobalFlagsExcept

func HideGlobalFlagsExcept(regexps ...*regexp.Regexp)

HideGlobalFlagsExcept hides global flags from the default compact-style usage message, except for the given regexps. Global flag names that match any of the regexps will still be shown in the compact usage message. Multiple calls behave as if all regexps were provided in a single call.

All global flags are always shown in non-compact style usage messages.

func Main

func Main(root *Command)

Main implements the main function for the command tree rooted at root.

It initializes a new environment from the underlying operating system, parses os.Args[1:] against the root command, and runs the resulting runner. Calls os.Exit with an exit code that is 0 for success, or non-zero for errors.

Most main packages should be implemented as follows:

var root := &cmdline.Command{...}

func main() {
  cmdline.Main(root)
}

func ParseAndRun

func ParseAndRun(root *Command, env *Env, args []string) error

ParseAndRun is a convenience that calls Parse, and then calls Run on the returned runner with the given env and parsed args.

Types

type Command

type Command struct {
	Name     string // Name of the command.
	Short    string // Short description, shown in help called on parent.
	Long     string // Long description, shown in help called on itself.
	ArgsName string // Name of the args, shown in usage line.
	ArgsLong string // Long description of the args, shown in help.

	// Flags defined for this command.  When a flag F is defined on a command C,
	// we allow F to be specified on the command line immediately after C, or
	// after any descendant of C. This FlagSet is only used to specify the
	// flags and their associated value variables, it is never parsed and hence
	// methods on FlagSet that are generally used after parsing cannot be
	// used on Flags. ParsedFlags should be used instead.
	Flags flag.FlagSet
	// FlagsDefs represents flags that are to be associated with this
	// command. The flags variables are defined as tagged (`cmdline:""`)
	// fields in a struct as per the v.io/x/lib/cmd/flagvar package.
	FlagDefs FlagDefinitions
	// ParsedFlags contains the FlagSet created by the Command
	// implementation and that has had its Parse method called. It
	// should be used instead of the Flags field for handling methods
	// that assume Parse has been called (e.g. Parsed, Visit,
	// NArgs etc).
	ParsedFlags *flag.FlagSet
	// DontPropagateFlags indicates whether to prevent the flags defined on this
	// command and the ancestor commands from being propagated to the descendant
	// commands.
	DontPropagateFlags bool
	// DontInheritFlags indicates whether to stop inheriting the flags from the
	// ancestor commands. The flags for the ancestor commands will not be
	// propagated to the child commands as well.
	DontInheritFlags bool

	// Children of the command.
	Children []*Command

	// LookPath indicates whether to look for external subcommands in the
	// directories specified by the PATH environment variable.  The compiled-in
	// children always take precedence; the check for external children only
	// occurs if none of the compiled-in children match.
	//
	// All global flags and flags set on ancestor commands are passed through to
	// the external child.
	LookPath bool

	// Runner that runs the command.
	// Use RunnerFunc to adapt regular functions into Runners.
	//
	// At least one of Children or Runner must be specified.  If both are
	// specified, ArgsName and ArgsLong must be empty, meaning the Runner doesn't
	// take any args.  Otherwise there's a possible conflict between child names
	// and the runner args, and an error is returned from Parse.
	Runner Runner

	// Topics that provide additional info via the default help command.
	Topics []Topic
}

Command represents a single command in a command-line program. A program with subcommands is represented as a root Command with children representing each subcommand. The command graph must be a tree; each command may either have no parent (the root) or exactly one parent, and cycles are not allowed.

type Env

type Env struct {
	Stdin  io.Reader
	Stdout io.Writer
	Stderr io.Writer
	Vars   map[string]string // Environment variables
	Timer  *timing.Timer

	// Usage is a function that prints usage information to w.  Typically set by
	// calls to Main or Parse to print usage of the leaf command.
	Usage func(env *Env, w io.Writer)
}

Env represents the environment for command parsing and running. Typically EnvFromOS is used to produce a default environment. The environment may be explicitly set for finer control; e.g. in tests.

func EnvFromOS

func EnvFromOS() *Env

EnvFromOS returns a new environment based on the operating system.

func (*Env) LookPath

func (e *Env) LookPath(name string) (string, error)

LookPath returns the absolute path of the executable with the given name, based on the directories in PATH. Calls lookpath.Look.

func (*Env) LookPathPrefix

func (e *Env) LookPathPrefix(prefix string, names map[string]bool) ([]string, error)

LookPathPrefix returns the absolute paths of all executables with the given name prefix, based on the directories in PATH. Calls lookpath.LookPrefix.

func (*Env) TimerPop

func (e *Env) TimerPop()

TimerPop calls e.Timer.Pop(), only if the Timer is non-nil.

func (*Env) TimerPush

func (e *Env) TimerPush(name string)

TimerPush calls e.Timer.Push(name), only if the Timer is non-nil.

func (*Env) UsageErrorf

func (e *Env) UsageErrorf(format string, args ...interface{}) error

UsageErrorf prints the error message represented by the printf-style format and args, followed by the output of the Usage function. Returns ErrUsage to make it easy to use from within the Runner.Run function.

type ErrExitCode

type ErrExitCode int

ErrExitCode may be returned by Runner.Run to cause the program to exit with a specific error code.

func (ErrExitCode) Error

func (x ErrExitCode) Error() string

Error implements the error interface method.

type FlagDefinitions

type FlagDefinitions struct {
	Flags         interface{}
	ValueDefaults map[string]interface{}
	UsageDefaults map[string]string
}

FlagDefinitions represents a struct containing flag variables and their associated default values as per RegisterFlagsInStruct.

type Runner

type Runner interface {
	Run(env *Env, args []string) error
}

Runner is the interface for running commands. Return ErrExitCode to indicate the command should exit with a specific exit code.

func Parse

func Parse(root *Command, env *Env, args []string) (Runner, []string, error)

Parse parses args against the command tree rooted at root down to a leaf command. A single path through the command tree is traversed, based on the sub-commands specified in args. Global and command-specific flags are parsed as the tree is traversed.

On success returns the runner corresponding to the leaf command, along with the args to pass to the runner. In addition the env.Usage function is set to produce a usage message corresponding to the leaf command.

Most main packages should just call Main. Parse should only be used if special processing is required after parsing the args, and before the runner is run. An example:

var root := &cmdline.Command{...}

func main() {
  env := cmdline.EnvFromOS()
  os.Exit(cmdline.ExitCode(parseAndRun(env), env.Stderr))
}

func parseAndRun(env *cmdline.Env) error {
  runner, args, err := cmdline.Parse(env, root, os.Args[1:])
  if err != nil {
    return err
  }
  // ... perform initialization that might parse flags ...
  return runner.Run(env, args)
}

Parse merges root flags into flag.CommandLine and sets ContinueOnError, so that subsequent calls to flag.Parsed return true.

type RunnerFunc

type RunnerFunc func(*Env, []string) error

RunnerFunc is an adapter that turns regular functions into Runners.

func (RunnerFunc) Run

func (f RunnerFunc) Run(env *Env, args []string) error

Run implements the Runner interface method by calling f(env, args).

type Topic

type Topic struct {
	Name  string // Name of the topic.
	Short string // Short description, shown in help for the command.
	Long  string // Long description, shown in help for this topic.
}

Topic represents a help topic that is accessed via the help command.

Directories

Path Synopsis
Usage of gendoc:
Usage of gendoc:

Jump to

Keyboard shortcuts

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