command

package
v0.0.0-...-6f3d572 Latest Latest
Warning

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

Go to latest
Published: Apr 22, 2024 License: MIT Imports: 15 Imported by: 6

Documentation

Overview

Package command provides classes and functions for defining custom CLIs.

Index

Constants

View Source
const (
	// UnboundedList is used to indicate that an argument list should allow an unbounded amount of arguments.
	UnboundedList = -1
)

Variables

View Source
var (
	PRE_ITEM_PREFIX = "┃   "
	ITEM_PREFIX     = map[bool]string{
					// contains filtered or unexported fields
	}
	POST_ITEM_PREFIX = map[bool]string{
						// contains filtered or unexported fields
	}
)
View Source
var (
	// OSLookupEnv is the env lookup command used internally by the entire `command` project.
	// It's value can be stubbed in tests by using the `commandtest.*TestCase.Env` fields.
	OSLookupEnv = os.LookupEnv
)

Functions

func DevNull

func DevNull() io.Writer

DevNull returns an io.Writer that ignores all output.

func ExtraArgsErr

func ExtraArgsErr(input *Input) error

ExtraArgsErr returns an error for when too many arguments are provided to a command.

func GetData

func GetData[T any](d *Data, key string) T

GetData fetches the value for a given key.

func InputRunAtOffset

func InputRunAtOffset[T any](i *Input, atOffset int, f func(*Input) T) T

func IsExtraArgsError

func IsExtraArgsError(err error) bool

IsExtraArgs returns whether or not the provided error is an `ExtraArgsErr`.

func StderrWriter

func StderrWriter(o Output) io.Writer

StderrWriter returns an io.Writer that writes to stderr.

func StdoutWriter

func StdoutWriter(o Output) io.Writer

StdoutWriter returns an io.Writer that writes to stdout.

Types

type Autocompletion

type Autocompletion struct {
	// Suggestions is the set of autocomplete suggestions.
	Suggestions []string
	// SpacelessCompletion indicates that a space should *not* be added (which happens
	// automatically if there is only one completion suggestion).
	SpacelessCompletion bool
}

Autocompletion is a subset of the `Completion` type and contains only data relevant for the OS package to handle autocompletion logic.

type BranchUsage

type BranchUsage struct {
	// Usage is the usage object for the branched node.
	Usage *Usage
}

type Completion

type Completion struct {
	// Suggestions is the set of autocomplete suggestions.
	Suggestions []string
	// IgnoreFilter indicates whether prefixes that don't match should be filtered out or not.
	IgnoreFilter bool
	// DontComplete indicates whether or not we should fill in partial completions.
	// This is achieved by adding a " " suggestion.
	DontComplete bool
	// CaseInsensitiveSort returns whether or not we should sort irrespective of case.
	CaseInsensitiveSort bool
	// CaseInsensitve is whether or not case should be considered when filtering out suggestions.
	CaseInsensitive bool
	// Distinct is whether or not we should return only distinct suggestions (specifically to prevent duplicates in list arguments).
	// Note: this is only applied for built-in types like `Argument` and `Flag`. To ensure
	// distinctness for custom argument processors, you will need to implement
	// logic in those custom objects yourself.
	Distinct bool
	// SpacelessCompletion indicates that a space should *not* be added (which happens
	// automatically if there is only one completion suggestion).
	SpacelessCompletion bool
	// DeferredCompletion will *execute* another graph before generating the actual
	// completion object.
	DeferredCompletion *DeferredCompletion
}

Completion is the object constructed by a completer.

func (*Completion) Clone

func (c *Completion) Clone() *Completion

func (*Completion) Process

func (c *Completion) Process(lastArg string, delimiter *rune, skipDelimiter bool) []string

process processes a `Completion` object using the provided `lastArg` and `delimiter`. If skipDelimiter is true, then no delimiter changes are done.

func (*Completion) ProcessInput

func (c *Completion) ProcessInput(input *Input) []string

ProcessInput processes a `Completion` object against a given `Input` object.

type Data

type Data struct {
	// Values is a map from argument name to the data for that argument.
	Values map[string]interface{}
	// Complexecute indictes whether we are running complexecute logic.
	Complexecute bool
	// OS is the current operating system. It is primarily used to execute
	// run logic in the parent shell (e.g. setting/unsetting environment variables)
	OS OS
}

Data contains argument data.

func (*Data) Bool

func (d *Data) Bool(k string) bool

Bool returns the bool data for an argument.

func (*Data) Float

func (d *Data) Float(k string) float64

Float returns the float data for an argument.

func (*Data) FloatList

func (d *Data) FloatList(k string) []float64

FloatList returns the float slice data for an argument.

func (*Data) Get

func (d *Data) Get(k string) interface{}

Get returns the interface data for an argument.

func (*Data) Has

func (d *Data) Has(k string) bool

Has returns whether or not key has been set in the `Data` object.

func (*Data) Int

func (d *Data) Int(k string) int

Int returns the int data for an argument.

func (*Data) IntList

func (d *Data) IntList(k string) []int

IntList returns the int slice data for an argument.

func (*Data) Set

func (d *Data) Set(k string, i interface{})

Set sets the provided key-value pair in the `Data` object.

func (*Data) String

func (d *Data) String(k string) string

String returns the string data for an argument.

func (*Data) StringList

func (d *Data) StringList(k string) []string

StringList returns the string slice data for an argument.

type DeferredCompletion

type DeferredCompletion struct {
	// Graph is the root of a command `Node` graph that will be *execute* (i.e.
	// not completed) before the respective function, `F`, is run. However, the
	// `ExecuteData` generated by executing this graph will be ignored.
	Graph Node
	// F is the function to run after `Graph` has been executed.
	F func(*Completion, *Data) (*Completion, error)
}

DeferredCompletion is a Completer that generates a `Completion` object after executing a graph.

type Edge

type Edge interface {
	// Next fetches the next node in the command graph based on
	// the provided `Input` and `Data`.
	Next(*Input, *Data) (Node, error)
	// UsageNext fetches the next node in the command graph when
	// command graph usage is being constructed. This is separate from
	// the `Next` function because `Next` is input-dependent whereas `UsageNext`
	// receives no input arguments.
	UsageNext(*Input, *Data) (Node, error)
}

Edge determines which `Node` to execute next.

type ExecuteData

type ExecuteData struct {
	// Executable is a list of bash commands to run after all nodes have been processed.
	Executable []string
	// Executor is a set of functions to run after all nodes have been processed.
	Executor []func(Output, *Data) error
	// FunctionWrap is whether or not to wrap the Executable contents
	// in a function. This allows Executable to use things like "return" and "local".
	FunctionWrap bool
}

ExecuteData contains operations to resolve after all nodes have been processed. This separation is needed for caching and shortcuts nodes.

type Input

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

Input is a type that tracks the entire input and how much of the input has been parsed. It also takes care of input snapshots (i.e. snapshots for shortcuts and caching purposes).

func NewInput

func NewInput(args []string, delimiter *rune) *Input

NewInput creates a new `Input` object from a set of args and quote delimiter.

func ParseCompLine

func ParseCompLine(compLine string, passthroughArgs ...string) *Input

ParseCompLine parses the COMP_LINE value provided by the shell

func ParseExecuteArgs

func ParseExecuteArgs(strArgs []string) *Input

ParseExecuteArgs converts a list of strings into an Input struct.

func (*Input) ConvertedArgs

func (i *Input) ConvertedArgs() []string

func (*Input) FullyProcessed

func (i *Input) FullyProcessed() bool

FullyProcessed returns whether or not the input has been fully processed.

func (*Input) GetSnapshot

func (i *Input) GetSnapshot(is spycommand.InputSnapshot) []string

GetSnapshot retrieves the snapshot.

func (*Input) MustPop

func (i *Input) MustPop(d *Data) string

MustPop runs `Pop` and panics if there isn't at least one value remaining.

func (*Input) NumRemaining

func (i *Input) NumRemaining() int

func (*Input) NumSnapshots

func (i *Input) NumSnapshots() int

NumSnapshots returns the number of snapshots

func (*Input) Peek

func (i *Input) Peek() (string, bool)

Peek returns the next argument and whether or not there is another argument.

func (*Input) PeekAt

func (i *Input) PeekAt(idx int) (string, bool)

PeekAt peeks at a specific argument and returns whether or not there are at least that many arguments.

func (*Input) Pop

func (i *Input) Pop(d *Data) (string, bool)

Pop removes the next argument from the input and returns if there is at least one more argument.

func (*Input) PopAt

func (i *Input) PopAt(offset int, d *Data) (string, bool)

func (*Input) PopBreakers

func (i *Input) PopBreakers(n int)

func (*Input) PopN

func (i *Input) PopN(n, optN int, breakers []InputBreaker, d *Data) ([]*string, bool)

PopN pops the next `n` arguments from the input and returns whether or not there are enough arguments left.

func (*Input) PopNAt

func (outerInput *Input) PopNAt(atOffset, n, optN int, breakers []InputBreaker, d *Data) ([]*string, bool)

PopNAt pops the `n` arguments starting at the provided offset.

func (*Input) PushBreakers

func (i *Input) PushBreakers(vs ...InputBreaker)

func (*Input) PushFront

func (i *Input) PushFront(sl ...string)

PushFront pushes arguments to the front of the remaining input.

func (*Input) PushFrontAt

func (i *Input) PushFrontAt(atOffset int, sl ...string)

PushFrontAt pushes arguments starting at a specific spot in the remaining arguments.

func (*Input) Remaining

func (i *Input) Remaining() []string

Remaining returns the remaining arguments.

func (*Input) Snapshot

func (i *Input) Snapshot() spycommand.InputSnapshot

Snapshot takes a snapshot of the remaining input arguments.

func (*Input) Used

func (i *Input) Used() []string

Used returns the input arguments that have already been processed.

type InputBreaker

type InputBreaker interface {
	// Break returns whether the input processing should stop.
	Break(string, *Data) bool
	// DiscardBreak returns whether the value responsible for breaking the input shoud be popped or not.
	DiscardBreak(string, *Data) bool
}

InputBreaker is an interface used to break a list of values returned by `Input.Pop` functions.

type InputTransformer

type InputTransformer struct {
	// F is the function that will be run on each element in Input.
	F func(Output, *Data, string) ([]string, error)
	// UpToIndexInclusive is the input argument index that F will be run through.
	// This is zero-indexed so default behavior (UpToIndexInclusive: 0) will run
	// on the first argument only. If UpToIndexInclusive is less than zero
	// (or command.UnboundedList), then this will run on all remaining arguments.
	UpToIndexInclusive int
}

InputTransformer checks the next input argument (as a string), runs `F` on that argument, and inserts the values returned from `F` in its place. See `FileNumberInputTransformer` for a useful example.

Note: `InputTransformer` should only be used when the number of arguments or the argument type is expected to change. If the number of arguments and type will remain the same, use an `Argument` with a `Transformer` option.

func (*InputTransformer) Complete

func (it *InputTransformer) Complete(input *Input, data *Data) (*Completion, error)

func (*InputTransformer) Execute

func (it *InputTransformer) Execute(i *Input, o Output, data *Data, eData *ExecuteData) error

func (*InputTransformer) Transform

func (it *InputTransformer) Transform(input *Input, output Output, data *Data, complete bool) error

func (*InputTransformer) Usage

func (it *InputTransformer) Usage(*Input, *Data, *Usage) error

type Node

type Node interface {
	Processor
	Edge
}

Node defines a cohesive node in the command graph. It is simply a combination of a `Processor` and an `Edge`.

type OS

type OS interface {
	// SetEnvVar returns a shell command that sets the environment variable
	// `envVar` to `value`. Environment variable modifications can't and shouldn't
	// be done by os.Setenv because the go CLI executable is run in a sub-shell.
	SetEnvVar(envVar, value string) string

	// UnsetEnvVar returns a shell command that unsets the environment variable
	// `envVar`. Environment variable changes can't and shouldn't be done by
	// os.Unsetenv because the go CLI executable is run in a sub-shell.
	UnsetEnvVar(envVar string) string
}

type Output

type Output interface {
	// Writes the provided text to stdout.
	Stdout(string)
	// Writes the provided text to stderr and returns an error with the same message.
	Stderr(string) error
	// Writes a formatted string to stdout.
	Stdoutf(string, ...interface{})
	// Writes a formatted string to stderr and returns an error with the same message.
	Stderrf(string, ...interface{}) error
	// Writes interfaces to stdout and appends a newline.
	Stdoutln(...interface{})
	// Writes interfaces to stderr and appends a newline.
	Stderrln(...interface{}) error
	// Writes the provided error to stderr and returns the provided error.
	Err(err error) error
	// Annotate prepends the message to the error
	Annotate(error, string) error
	// Annotatef prepends the message to the error
	Annotatef(error, string, ...interface{}) error
	// Terminate terminates the execution with the provided error (if it's not nil).
	Terminate(error)
	// Terminatef terminates the execution with a formatted error.
	Terminatef(string, ...interface{})
	// Tannotate terminates the execution with the an annotation of provided error (if it's not nil).
	Tannotate(error, string)
	// Tannotatef terminates the execution with an annotation of the provided error (if it's not nil).
	Tannotatef(error, string, ...interface{})
	// Close informs the os that no more data will be written.
	Close()
	// Color changes the format of stdout to the provided formats.
	Color(fs ...color.Format)
	// Colerr (color + err hehe) changes the format of stderr to the provided formats.
	Colerr(fs ...color.Format)
}

Output defines methods for writing output.

func NewIgnoreAllOutput

func NewIgnoreAllOutput() Output

NewIgnoreAllOutput is an output that ignores all output.

func NewIgnoreErrOutput

func NewIgnoreErrOutput(o Output, fs ...func(error) bool) Output

NewIgnoreErrOutput is an output that ignores errors that satisfy any of the provided functions.

func NewOutput

func NewOutput() Output

NewOutput returns an output that points to stdout and stderr.

func OutputFromFuncs

func OutputFromFuncs(stdoutFunc, stderrFunc func(string)) Output

OutputFromFuncs returns an Output object that forwards data to the provided stdout and stderr functions.

If you need an Output object for testing purposes, consider using commandtest.NewOutput() which provides the `GetStdout/GetStderr` and `GetStdoutByCalls/GetStderrByCalls` functions.

type Processor

type Processor interface {
	// Execute is the function called when a command graph is
	// being executed.
	Execute(*Input, Output, *Data, *ExecuteData) error
	// Complete is the function called when a command graph is
	// being autocompleted. If it returns a non-nil `Completion` object,
	// then the graph traversal stops and uses the returned object
	// to construct the command completion suggestions.
	Complete(*Input, *Data) (*Completion, error)
	// Usage is the function called when the usage data for a command
	// graph is being constructed. A
	// The input `Usage` object should be
	// updated for each `Node`.
	Usage(*Input, *Data, *Usage) error
}

Processor defines the logic that should be executed at a `Node`.

type Usage

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

func (*Usage) AddArg

func (u *Usage) AddArg(name, description string, required, optional int)

func (*Usage) AddFlag

func (u *Usage) AddFlag(fullFlag string, shortFlag rune, argName string, description string, required, optional int)

func (*Usage) AddSymbol

func (u *Usage) AddSymbol(symbol, description string)

func (*Usage) SetBranches

func (u *Usage) SetBranches(branches []*BranchUsage)

func (*Usage) SetDescription

func (u *Usage) SetDescription(desc string)

func (*Usage) String

func (u *Usage) String() string

type UsageSection

type UsageSection string
const (
	// ArgSection is the title of the arguments usage section.
	ArgSection UsageSection = "Arguments"
	// FlagSection is the title of the flags usage section.
	FlagSection UsageSection = "Flags"
	// SymbolSection is the title of the symbols usage section.
	SymbolSection UsageSection = "Symbols"
)

Jump to

Keyboard shortcuts

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