subcommands

package module
v1.1.1 Latest Latest
Warning

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

Go to latest
Published: Sep 22, 2021 License: Apache-2.0 Imports: 11 Imported by: 277

README

subcommands golang library

This package permits a Go application to implement subcommands support similar to what is supported by the 'go' tool.

The library is designed so that the test cases can run concurrently. Using global flags variables is discouraged to keep your program testable concurrently.

The intended command is found via heuristic search;

  • exact match
  • unique prefix, e.g. lo will run longcommand as long as there's no command with the same prefix.
  • case insensitivity; for those weird enough to use Upper Cased Commands.
  • levenshtein distance; where longcmmand or longcmomand will properly trigger longcommand.

PkgGoDev Coverage Status

Examples

  • See sample-simple for a barebone sample skeleton usable as-is.
  • See sample-complex for a complex sample using advanced features.
  • See module subcommands/subcommandstest for tools to help testing an application using subcommands. One of the main benefit is t.Parallel() just works, because subcommands help wrapping global variables.

Documentation

Overview

Package subcommands permits a Go application to implement subcommands support similar to what is supported by the 'go' tool.

The library is designed so that the test cases can run concurrently. Using global flags variables is discouraged to keep your program testable conccurently.

Index

Constants

This section is empty.

Variables

View Source
var CmdHelp = &Command{
	UsageLine: "help [<command>|-advanced]",
	ShortDesc: "prints help about a command",
	LongDesc:  "Prints an overview of every command or information about a specific command.\nPass -advanced to see help for advanced commands.",
	CommandRun: func() CommandRun {
		ret := &helpRun{}
		ret.Flags.BoolVar(&ret.advanced, "advanced", false, "show advanced commands")
		return ret
	},
}

CmdHelp defines the help command. It should be included in your application's Commands list.

It is not added automatically but it will be run automatically if added.

Functions

func KillStdLog

func KillStdLog()

KillStdLog sets an output that will panic if used. This permits trapping any log.*() calls that would inhibit efficient use of t.Parallel().

func Run

func Run(a Application, args []string) int

Run runs the application, scheduling the subcommand. This is the main entry point of the library.

Unit tests should call this function directly with args provided so this is concurrent safe.

It is safer to use a base class embedding CommandRunBase that is then embedded by each CommandRun implementation to define flags available for all commands.

func Usage added in v1.1.0

func Usage(out io.Writer, a Application, includeAdvanced bool)

Usage prints out the general application Usage.

This is primarily useful when using embedded commands. See sample-complex for an example.

Beware that using the form "<tool> help -advanced <command>" will not propagate CmdHelp's help into the subcommand help Usage.

func VoidStdLog

func VoidStdLog()

VoidStdLog sets an output that will be ignored. This permits ignoring any log.*() calls that would inhibit efficient use of t.Parallel().

Types

type Application

type Application interface {
	// GetName returns the 'name' of the application.
	GetName() string

	// GetTitle returns a one-line title explaining the purpose of the tool.
	GetTitle() string

	// GetCommands returns the list of the subcommands that are supported.
	GetCommands() []*Command

	// GetOut is used for testing to allow parallel test case execution, should
	// be normally os.Stdout.
	GetOut() io.Writer

	// GetErr is used for testing to allow parallel test case execution, should
	// be normally os.Stderr.
	GetErr() io.Writer

	// GetEnvVars returns the map of EnvVarName -> EnvVarDefinition that this
	// Application responds to.
	GetEnvVars() map[string]EnvVarDefinition
}

Application describes an application with subcommand support.

type Command

type Command struct {
	UsageLine  string
	ShortDesc  string
	LongDesc   string
	Advanced   bool
	CommandRun func() CommandRun
	// contains filtered or unexported fields
}

Command describes a subcommand. It has one generator to generate a command object which is executable. The purpose of this design is to enable safe parallel execution of test cases.

func FindCommand

func FindCommand(a Application, name string) *Command

FindCommand finds a Command by name and returns it if found.

func FindNearestCommand

func FindNearestCommand(a Application, name string) *Command

FindNearestCommand heuristically finds a Command the user wanted to type but failed to type correctly.

func Section

func Section(name string) *Command

Section returns an un-runnable command that can act as a nice section heading for other commands.

func (*Command) Name

func (c *Command) Name() string

Name returns the command's name: the first word in the usage line.

type CommandRun

type CommandRun interface {
	// Run execute the actual command. When this function is called by
	// command_support.Run(), the flags have already been parsed.
	Run(a Application, args []string, env Env) int

	// GetFlags returns the flags for this specific command.
	//
	// If this returns `nil`, then any additional arguments for this command will
	// be passed unaltered as `args` to `Run()`. This is useful to delay command
	// line parsing for implementing, for example, wrapper commands around other
	// scripts.
	GetFlags() *flag.FlagSet
}

CommandRun is an initialized object representing a subcommand that is ready to be executed.

type CommandRunBase

type CommandRunBase struct {
	Flags flag.FlagSet
}

CommandRunBase implements GetFlags of CommandRun. It should be embedded in another struct that implements Run().

func (*CommandRunBase) GetFlags

func (c *CommandRunBase) GetFlags() *flag.FlagSet

GetFlags implements CommandRun.

type DefaultApplication

type DefaultApplication struct {
	Name     string
	Title    string
	Commands []*Command
	EnvVars  map[string]EnvVarDefinition
}

DefaultApplication implements all of Application interface's methods. An application should usually have a global instance of DefaultApplication and route main() to command_support.Run(app).

func (*DefaultApplication) GetCommands

func (a *DefaultApplication) GetCommands() []*Command

GetCommands implements interface Application.

func (*DefaultApplication) GetEnvVars

func (a *DefaultApplication) GetEnvVars() map[string]EnvVarDefinition

GetEnvVars implements interface Application.

func (*DefaultApplication) GetErr

func (a *DefaultApplication) GetErr() io.Writer

GetErr implements interface Application.

func (*DefaultApplication) GetName

func (a *DefaultApplication) GetName() string

GetName implements interface Application.

func (*DefaultApplication) GetOut

func (a *DefaultApplication) GetOut() io.Writer

GetOut implements interface Application.

func (*DefaultApplication) GetTitle

func (a *DefaultApplication) GetTitle() string

GetTitle implements interface Application.

type Env

type Env map[string]EnvVar

Env is the mapping of resolved environment variables passed to CommandRun.Run.

type EnvVar

type EnvVar struct {
	Value  string
	Exists bool
}

EnvVar will document the value and existence of a given environment variable, as defined by Application.GetEnvVars. Value will be the value from the environment, or the Default value if it didn't exist. Exists will be true iff the value was present in the environment.

type EnvVarDefinition

type EnvVarDefinition struct {
	Advanced  bool
	ShortDesc string
	Default   string
}

EnvVarDefinition describes an environment variable that this application responds to.

type PanicWriter

type PanicWriter struct {
}

PanicWriter is an io.Writer that will panic if used.

func (PanicWriter) Write

func (p PanicWriter) Write(b []byte) (n int, err error)

Write implements io.Writer.

Directories

Path Synopsis
sample-complex - Sample app to demonstrate example usage of package subcommand.
sample-complex - Sample app to demonstrate example usage of package subcommand.
sample-simple - Sample app to demonstrate a very basic example usage of package subcommand.
sample-simple - Sample app to demonstrate a very basic example usage of package subcommand.
Package subcommandstest includes tools to help with concurrent testing.
Package subcommandstest includes tools to help with concurrent testing.

Jump to

Keyboard shortcuts

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