Documentation
¶
Overview ¶
Package cmdkit provides a very simple framework for building command-line applications that follow Unix command-line interface conventions.
The package tries to build upon Go's flag package to provide a more structured approach to CLI development while maintaining simplicity and familiarity.
Example ¶
package main import ( "errors" "fmt" "go.cipher.host/cmdkit" ) func main() { var ( // Create a new application with explicit metadata. You can also leave // the name and version empty to have the application infer them from // os.Args[0] and Go module information. app = cmdkit.New("myapp", "A simple example application", "1.0.0") // Add a simple command to the application. greet = cmdkit.NewCommand("greet", "Greet someone by name", "[--formal] <name>") ) var formal bool // Register your flags using flag.TypeVar-kind of methods, e.g. // flag.BoolVar. If you want to add a Unix-style short form, register both // the long and short forms and then use App.AddShorthand. greet.Flags.BoolVar(&formal, "formal", false, "use formal greeting") // Set the command's run function. greet.RunE = func(args []string) error { if len(args) < 1 { return errors.New("name is required") } if formal { fmt.Fprintf(greet.OutWriter(), "Good day, %s!\n", args[0]) } else { fmt.Fprintf(greet.OutWriter(), "Hi, %s!\n", args[0]) } return nil } // Add the command to the application. app.AddCommand(greet) // Run the application with example arguments. You'd normally use // os.Args[1:] instead. if err := app.Run([]string{"greet", "Alice"}); err != nil { app.Errorf("error: %v", err) cmdkit.Exit(err) } }
Output: Hi, Alice!
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Exit ¶
func Exit(err error)
Exit provides a consistent way to terminate a command-line application while respecting Unix exit code conventions.
It handles the following cases:
- nil error -> exit 0 (success) - flag.ErrHelp -> exit 0 (help display is not an error) - ExitError -> use provided exit code - other errors -> exit 1 (general failure)
This function should typically be called at the top level of main().
func InputOrFile ¶
func InputOrFile(path, message string) (io.ReadCloser, error)
InputOrFile provides a flexible input mechanism that handles both file and stdin input transparently. It follows the Unix convention where "-" represents stdin, allowing commands to be part of pipelines.
The function adds user-friendly behavior by displaying an optional message when reading from an interactive terminal, helping users understand that the program is waiting for input.
func IsTerminal ¶
IsTerminal detects whether a given file descriptor represents an interactive terminal.
func LoadEnv ¶
LoadEnv bridges environment variables to command-line flags. It follows the common Unix pattern of using uppercase environment variables with a prefix.
The function only sets flags that haven't been explicitly set via command-line arguments, maintaining the precedence: 1. Command-line flags. 2. Environment variables. 3. Default values.
For example, for an app "gravity" with flag "--character", "GRAVITY_CHARACTER=mabel" would set the flag if not provided on command line.
func WantColor ¶
func WantColor() bool
WantColor determines whether the application should use ANSI color codes in its output. It implements a comprehensive color detection system following modern terminal conventions:
The function respects: - NO_COLOR environment variable. - Terminal capability detection. - Special terminal types (e.g., "dumb" terminals).
This provides a consistent and user-configurable color experience across different terminal environments.
Types ¶
type App ¶
type App struct { // OutWriter receives normal output. When initialized from New, defaults to // [os.Stdout]. // // Configurable primarily for testing and special output handling. // // [os.Stdout]: https://pkg.go.dev/os#Stdout OutWriter io.Writer // ErrWriter receives error output and help text. When initialized from New, // defaults to [os.Stderr]. // // Separated from OutWriter to follow Unix output conventions. // // [os.Stderr]: https://pkg.go.dev/os#Stderr ErrWriter io.Writer // Flags holds the global flag set. These flags apply to all subcommands and // are parsed before command-specific flags. Flags *flag.FlagSet // Before is called before any subcommand execution, allowing for global // setup like configuration loading or resource initialization. Before func() error // After is called after subcommand execution, regardless of success or // failure. Useful for cleanup and resource release. After func() error // Name is the application name. When initialized from New, if not provided, // defaults to [os.Args[0]]. // // [os.Args[0]]: https://pkg.go.dev/os#Args Name string // Description explains the application's purpose. Shown in help text to // guide users. Description string // Version indicates the application version. When initialized from new, if // not provided, defaults to [debug.ReadBuildInfo]. // // [debug.ReadBuildInfo]: https://pkg.go.dev/runtime/debug#ReadBuildInfo Version string // Examples provides usage examples shown in help text. Each example should // be a complete command line. Examples []string // Commands holds the registered subcommands. Commands []*Command // contains filtered or unexported fields }
App represents a command-line application. It serves as the top-level container for application state and coordinates the execution of subcommands while managing global flags and configuration.
func New ¶
New creates a new App instance with sane defaults.
Name resolution:
- Uses provided name if non-empty.
- Falls back to base name of [os.Args[0]] if name is empty.
Version resolution:
- Uses provided version if non-empty.
- Attempts to read version from Go module information.
- Falls back to "unknown" if no version information is available.
func (*App) AddCommand ¶
AddCommand registers a new subcommand with the application. Commands are stored in registration order, which affects help text display.
func (*App) AddShorthand ¶
AddShorthand creates a Unix-style short form for a flag. This enables the common pattern where flags have both long and short forms (e.g., "--help" and "-h").
You should register both the long and short forms with flag.TypeVar-kind of methods, e.g. flag.StringVar before using this method.
func (*App) Errorf ¶
Errorf writes a formatted error message to the application's error output. It prefixes the message with the application name to provide context in error messages.
func (*App) Run ¶
Run executes the application with the provided arguments, typically [os.Args[1:]].
func (*App) ShowVersion ¶
func (a *App) ShowVersion()
ShowVersion displays the application's version.
type Command ¶
type Command struct { // Flags holds command-specific flags that only apply to this command. These // are parsed after global flags but before command arguments. Flags *flag.FlagSet // RunE executes the command's logic. It receives the remaining arguments // after flag parsing. RunE func(args []string) error // Before runs before command execution, allowing for command-specific setup // like validating flags or preparing resources. Before func() error // After runs after command execution for cleanup. Executes even if the // command fails. After func() error // Name is the command name as used in the command line. Name string // Description explains the command's purpose. Shown in both parent app help // and command-specific help. Description string // Usage describes the command's argument pattern. E.g., "[flags] <input> // <output>". Usage string // Examples shows example invocations of this specific command. Examples []string // contains filtered or unexported fields }
Command represents a single subcommand in a command-line application. It encapsulates all the behavior and flags specific to one function of the application, following the Unix principle of small, focused tools.
Commands are designed to be self-contained units that can be composed into larger applications. Each command manages its own flags and handles its own argument validation and processing.
func NewCommand ¶
NewCommand creates a new Command instance with the provided metadata.
For the best user experience, the usage string should follow Unix conventions: - Optional elements in square brackets: [--flag]. - Required elements in angle brackets: <file>. - Variable numbers of arguments with ellipsis: [file...].
func (*Command) AddShorthand ¶
AddShorthand creates a short form alias for a command-specific flag. This works the same way as App.AddShorthand but scoped to the command's flags.
type Error ¶
type Error string
Error is an immutable error type.
const ErrUnknownCommand Error = "unknown command"
ErrUnknownCommand is returned when a command is not found.
var ErrCommandRunMissing Error = "command has no run function"
ErrCommandRunMissing is returned when a command is created without the RunE field.
type ExitError ¶
type ExitError struct { // Err is the underlying error being wrapped. Err error // No is the process exit code to use. E.g., 0 for success, 1-255 for // errors. No int }
ExitError wraps an error with an exit code, allowing commands to control their process exit status in a Unix-compatible way similar to the errno standard in C.
func NewExitError ¶
NewExitError returns a new Error instance with the given error code.
type RepeatValue ¶
type RepeatValue []string
RepeatValue implements flag.Value to support repeated flag options. This allows flags to be specified multiple times to build a list of values.
func (*RepeatValue) Set ¶
func (r *RepeatValue) Set(value string) error
Set satisfies the flag.Value interface.
func (*RepeatValue) String ¶
func (r *RepeatValue) String() string
String satisfies the flag.Value interface.
Directories
¶
Path | Synopsis |
---|---|
internal
|
|
term
Package term provides support functions for dealing with terminals, as commonly found on UNIX systems.
|
Package term provides support functions for dealing with terminals, as commonly found on UNIX systems. |
xflag
Package xflag provides a extension to the flag package.
|
Package xflag provides a extension to the flag package. |