Documentation
¶
Overview ¶
Package cmdr provides an organized way to implement command line tools, with predictable behavior, arbitrary sub-commands and symlink-based multiplexing.
Index ¶
- Constants
- func Name(ctx context.Context) (name string)
- func RunMain(cmd Cmd, args []string, opts ...Option)
- func RunSubCommand(ctx context.Context, cmd Cmd, name string, args []string) error
- func Stdio(ctx context.Context) (stdin io.Reader, stdout, stderr io.Writer)
- func WithStdio(parent context.Context, stdin io.Reader, stdout, stderr io.Writer) context.Context
- type Args0Observer
- type Cmd
- type ExitCoder
- type ExitMessenger
- type Func
- type Option
- type PanicBehavior
- type SilentError
Examples ¶
Constants ¶
const ExeSuffix = ""
ExeSuffix is the suffix for executable programs.
Variables ¶
This section is empty.
Functions ¶
func Name ¶ added in v1.5.0
Name returns the name of the command.
Name always returns the accurate name of the executing command, which may be a nested name, for as long as RunMain and router.Cmd are used.
If the context is handled incorrectly, Name panics.
func RunMain ¶
RunMain runs the given command with arguments.
A context.NotifyContext with os.Interrupt signal is provided as context, allowing commands to gracefully terminate on the interrupt signal. Other signals may be intercepted by passing WithSignals option.
If cmd has PassArgv0() bool method which returns true, then args[0] is preserved. This allows implementing symlink-based command multiplexers, such as Router.
If the command panics, the panic is recovered and an error message is printed. Other behaviors can be selected by passing WithPanicBehavior option. If the command returns an error, the error is printed, unless it is equal to flag.ErrHelp.
The exit code from the process is non-zero when the command returns an error or causes a panic. Errors implementing the ExitCoder interface can provide the exit code explicitly. The special flag.ErrHelp is translated to EX_USAGE (64). All other errors set exit code to one.
The standard output and error streams are always synchronized before terminating the process.
Example ¶
You can structure your application as a number of command types that get invoked at the right time. All you need is a `Run(context.Context, []string) error` function on your types. Inside that function, you can do anything.
cmdr.RunMain(helloCmd{}, []string{"example"})
Output: Hello World
func RunSubCommand ¶ added in v1.7.0
RunSubCommand runs a given command as a sub-command.
This function allows replicating all the router functionality in a custom type, perhaps one with logic beyond the capabilities of the default router.
Unlike just running the command directly, the invoked sub-command can access the correctly nested sub-command name through cmdr.Name.
func Stdio ¶ added in v1.1.0
Stdio returns the standard IO streams for the given context.
If the context was returned by WithStdio, the encoded streams are recovered. In all other cases os.{Stdin,Stdout,Stderr} is returned.
IO streams may be replaced for testing. Recovering the streams from the context avoids the need to use and manage per-command global variables.
Example ¶
Apart from serving the usual role, the context may be used to obtain the three standard input and output streams. The returned streams are os.Stdin, os.Stdout and os.Stderr. In unit tests, those may be redirected to buffers to aid in testing the output produced by commands. This is especially useful and easy with the cmdtest package.
cmd := cmdr.Func(func(ctx context.Context, args []string) error { _, stdout, _ := cmdr.Stdio(ctx) _, _ = fmt.Fprintln(stdout, "Hello World") return nil }) inv := cmdtest.Invoke(cmd) if err := inv.ExpectStdout("Hello World\n"); err != nil { log.Fatal(err) } // This produces no output as the output is captured the invocation helper // and is available for tests to inspect.
Output:
Types ¶
type Args0Observer ¶
type Args0Observer interface {
PreserveArgs0() bool
}
Args0Observer instructs RunMain to preserve args[0].
type Cmd ¶
type Cmd interface { // Run runs the command with the given context and arguments. // The context can be used to pass global options to a command. Run(ctx context.Context, args []string) error }
Cmd is a runnable command.
type ExitCoder ¶
type ExitCoder interface {
ExitCode() int
}
ExitCoder is an interface for errors to convey a process exit code.
type ExitMessenger ¶ added in v1.6.0
type ExitMessenger interface {
ExitMessage() string
}
ExitMessenger is an interface for errors to convey a specific error message.
ExitMessenger may be used to suppress the system that automatically prints the error value if the error message returned is empty.
type Func ¶
Func is the type of functions runnable as commands.
Example ¶
The most basic example uses `cmdr.RunMain` to run a function that takes a context, arguments and returns an error. The context has multiple uses as we will see later. The `cmdr.Func` type adapts a function to `cmdr.Cmd` interface. In essence, anything that can be called with string arguments is runnable as a command.
cmd := cmdr.Func(func(ctx context.Context, args []string) error { fmt.Println("Hello World") return nil }) cmdr.RunMain(cmd, []string{"example"})
Output: Hello World
type Option ¶ added in v1.2.0
type Option func(*mainOpts)
Option influences how RunMain operates.
func WithArgv0 ¶ added in v1.2.0
WithArgv0 sets the name of the main command.
RunMain occasionally prints the name of the main command. The name of the main command is either "?" or the base name of os.Args[0]. This option allows using a custom name.
func WithBaseContext ¶ added in v1.2.0
WithBaseContext sets the base of the context provided to the main command.
RunMain provides a context to executed command. This context defaults to a context derived from context.Background. This option allows using a custom base context, for example, a context with a deadline.
func WithExitFunc ¶ added in v1.2.1
WithExitFunc overrides the default os.Exit with a custom function.
Note that the exit function when a non-zero needs to be returned. On successful exit or when the error maps to an exit code of zero, the exit function is not called.
func WithPanicBehavior ¶ added in v1.2.0
func WithPanicBehavior(b PanicBehavior) Option
WithPanicBehavior configures panic behavior.
RunMain recovers any panic that happens during execution of the main command. By default, only the panic message is printed. This option allows selecting other behavior.
func WithSignals ¶ added in v1.2.0
WithSignals sets signals canceling the context passed to the main command.
RunMain establishes signal handlers through signal.NotifyContext. By default, os.Interrupt is intercepted. This option allows using a different set of signals.
type PanicBehavior ¶ added in v1.2.0
type PanicBehavior int
PanicBehavior controls reaction to panic encountered in RunMain.
Use WithPanicBehavior to
const ( // RecoverExit is the default panic behavior of RunMain. // // Panic caused by command execution is recovered. The recovered value // is printed to standard error. Program execution is terminated with // os.Exit, or the configured exit function, with code 70. RecoverExit PanicBehavior = iota // RecoverTraceExit prints a stack trace on panic. // // RecoverStackTrace is like RecoverExit in the sense that a panic is // both recovered and that the process terminates with an exit code. In // addition, the stack trace of the go routine which has caused the // panic is printed to standard error. RecoverTraceExit )
type SilentError ¶ added in v1.6.0
type SilentError uint8
SilentError is an error type that produces a given error code but no error message.
func (SilentError) Error ¶ added in v1.6.0
func (e SilentError) Error() string
Error returns the empty string.
func (SilentError) ExitCode ¶ added in v1.6.0
func (e SilentError) ExitCode() int
ExitCode returns the integer encoded in the error.
func (SilentError) ExitMessage ¶ added in v1.6.0
func (e SilentError) ExitMessage() string
ExitMessage returns the empty string.
cmdr.RunMain suppresses error output when ExitMessage is implemented by the error value and the value is the empty string.
Directories
¶
Path | Synopsis |
---|---|
Package cmdtest contains utilities for testing commands.
|
Package cmdtest contains utilities for testing commands. |
internal/install
Package install exists to provide regression tests against https://gitlab.com/zygoon/go-cmdr/-/issues/4
|
Package install exists to provide regression tests against https://gitlab.com/zygoon/go-cmdr/-/issues/4 |
Package flagcmd implements extensible commands based on standard library flag.FlagSet argument parser.
|
Package flagcmd implements extensible commands based on standard library flag.FlagSet argument parser. |
Package format implements the output format hint system.
|
Package format implements the output format hint system. |
jsonformat
Package jsonformat implements support for outputting JSON.
|
Package jsonformat implements support for outputting JSON. |
diff
Package diff computes differences between text files or strings.
|
Package diff computes differences between text files or strings. |
diff/difftest
Package difftest supplies a set of tests that will operate on any implementation of a diff algorithm as exposed by "golang.org/x/tools/internal/diff"
|
Package difftest supplies a set of tests that will operate on any implementation of a diff algorithm as exposed by "golang.org/x/tools/internal/diff" |
diff/lcs
Package lcs contains code to find longest-common-subsequences (and diffs)
|
Package lcs contains code to find longest-common-subsequences (and diffs) |
Package router provides command router useful for creating arbitrary sub-command trees.
|
Package router provides command router useful for creating arbitrary sub-command trees. |
samples
module
|