Documentation
¶
Index ¶
- Constants
- Variables
- type CallOrDef
- type Cmd
- func (x *Cmd) Add(name string, aliases ...string) *Cmd
- func (x *Cmd) AliasSlice() []string
- func (x *Cmd) AppendCmd(cmd *Cmd)
- func (x *Cmd) CacheAlias()
- func (x *Cmd) CacheCmdAlias()
- func (x *Cmd) CacheHide()
- func (x *Cmd) CacheOpts()
- func (x *Cmd) Can(names ...string) *Cmd
- func (x *Cmd) CmdAliasMap() map[string]*Cmd
- func (x *Cmd) CmdNames() []string
- func (x *Cmd) Fill(tmpl string) string
- func (x *Cmd) Get(key string) (string, error)
- func (x *Cmd) HideSlice() []string
- func (x *Cmd) IsHidden() bool
- func (x *Cmd) Names() []string
- func (x *Cmd) Opt(p string) string
- func (x *Cmd) OptsSlice() []string
- func (x *Cmd) Path(more ...string) string
- func (x *Cmd) PathCmds() []*Cmd
- func (x *Cmd) PathNames() []string
- func (x *Cmd) PathWithDashes(more ...string) string
- func (x *Cmd) PrependCmd(cmd *Cmd)
- func (x *Cmd) Print(tmpl string)
- func (x *Cmd) Println(tmpl string)
- func (x *Cmd) Resolve(name string) *Cmd
- func (x *Cmd) Root() *Cmd
- func (x *Cmd) Run(args ...string)
- func (x *Cmd) Seek(args []string) (*Cmd, []string)
- func (x *Cmd) Set(key, val string) error
- func (x Cmd) String() string
- type Completer
- type IncorrectUsage
- type InvalidMultiName
- type InvalidName
- type Method
- type MissingVar
- type NoCallNoDef
- type NotEnoughArgs
- type TooManyArgs
- type Uncallable
- type UnsupportedVar
- type VarsInitFailed
- type WrongNumArgs
Examples ¶
Constants ¶
const ( FAILED = -1 NOTFOUND = 0 SUCCESS = 1 )
Variables ¶
var FuncMap = template.FuncMap{ "exe": func(a string) string { return term.Under + a + term.Reset }, "pkg": func(a string) string { return term.Bold + a + term.Reset }, "cmd": func(a string) string { return term.Bold + a + term.Reset }, "indent": indent, "pre": func(a string) string { return term.Under + a + term.Reset }, "exepath": run.ExePath, "exename": run.ExeName, "execachedir": run.ExeCacheDir, "exestatedir": run.ExeStateDir, "execonfigdir": run.ExeConfigDir, "cachedir": futil.UserCacheDir, "confdir": futil.UserConfigDir, "homedir": futil.UserHomeDir, "statedir": futil.UserStateDir, "pathsep": func() string { return string(os.PathSeparator) }, "pathjoin": filepath.Join, }
FuncMap contains the package global default template domain specific language implemented as a collection of functions in a template.FuncMap which can be supplemented or overridden by Bonzai developers. Note this is in addition to any specific syntax added specifically to a Cmd with Cmd.FuncMap (which takes higher priority). Note that there is no protection against any [Cmd.Call] function changing one or all of these entries for every other Cmd within the same executable. This flexibility is by design but must be taken into careful consideration when deciding to alter this package-scoped variable. It is almost always preferable to use the [Cmd.FuncMap] instead.
var IsValidName = is.AllLatinASCIILower
IsValidName is assigned a function that returns a boolean for the given name. See is.AllLatinASCIILower for an example. Note that if this is changed certain characters may break the creation of multicall binary links and bash completion.
var Vars vars.Driver
Functions ¶
This section is empty.
Types ¶
type Cmd ¶
type Cmd struct {
Name string // ex: delete
Alias string // ex: rm|d|del
Opts string // ex: mon|wed|fri
// Work done by this command
Init Method // run-time initialization/validation
Call Method // if nil, Def must be set
// Delegation to subcommands
Def *Cmd // default [Cmd] if no Call and no matching Cmds
Cmds []*Cmd // compiled/composed commands in no particular order
Hide string // disable completion: ex: old|defunct
// Minimal when [Cmd.Docs] is overkill
Usage string
Vers string
Short string
Long string
// Faster than lots of "if" conditions in [Cmd.Call]. Consider
// [Cmd.Init] when more complex argument validation is needed.
MinArgs int // min
MaxArgs int // max
NumArgs int // exact, also used for NoArg (0)
MatchArgs string // PCRE/Go regular expression (requires Usage)
// Self-completion support: complete -C foo foo
Comp Completer
// Def vars declaration and initial values. Does not overwrite
// existing vars. All vars used with [Cmd.Get] and [Cmd.Set] must be declared
// even if empty. See [Vars], [VarsDriver], and package [is].
Vars map[string]string
// Optional embedded documentation in any format used by help and
// documentation commands such as [doc.Cmd] from the core/cmds
// package. Embedded content is usually lazy loaded only when the doc
// command is called. Structure and format of the files can be anything
// supported by any [Cmd] but Bonzai [mark] is recommended for
// greatest compatibility. Use of an embedded file system instead of
// a string allows, for example, support for multiple languages to be
// embedded into a single binary.
Docs embed.FS
// Template commands/functions to be added (or overwrite) the internal
// [FuncMap] collection of template commands used by the [Cmd.Fill]
// command. These apply to this [Cmd] only and will not be available
// to subcommands. To share between commands (including subcommands)
// assign the same FuncMap to all of them.
FuncMap template.FuncMap
// Following are never assigned in declarations but are instead
// set at [Run] time for use in [Call] methods:
Caller *Cmd // delegation
// contains filtered or unexported fields
}
func (*Cmd) Add ¶
Add creates a new Cmd and sets the [Name] and [Alias] and adds to [Cmds] returning a reference to the new Cmd. Name must be first.
func (*Cmd) AliasSlice ¶
AliasSlice updates the [aliases] internal cache ([CacheAlias]) and returns it as a slice.
Example ¶
package main
import (
"fmt"
bonzai "github.com/rwxrob/bonzai/pkg"
)
func main() {
barCmd := &bonzai.Cmd{
Name: `bar`,
Alias: `b|rab`,
Call: func(_ *bonzai.Cmd, _ ...string) error {
fmt.Println(`i am bar`)
return nil
},
}
fmt.Printf("%q", barCmd.AliasSlice())
fooCmd := &bonzai.Cmd{
Name: `foo`,
Cmds: []*bonzai.Cmd{barCmd},
}
fmt.Printf("%q", fooCmd.AliasSlice())
}
Output: ["b" "rab"][]
func (*Cmd) CacheAlias ¶
func (x *Cmd) CacheAlias()
CacheAlias updates the [aliases] cache by splitting [Alias] and adding the [Name] to the end. Remember to call this whenever dynamically altering the value at runtime.
func (*Cmd) CacheCmdAlias ¶
func (x *Cmd) CacheCmdAlias()
CacheCmdAlias splits the [Cmd.Alias] for each Cmd in [Cmds] with its respective Cmd.AliasSlice and assigns them the Cmd.CmdAliasMap cache map. This is primarily used for bash tab completion support in [Run] and use as a multicall binary. If [Cmds] is nil or [Name] is empty silently returns.
func (*Cmd) CacheHide ¶
func (x *Cmd) CacheHide()
CacheHide updates the [hidden] cache by splitting [Hide] . Remember to call this whenever dynamically altering the value at runtime.
func (*Cmd) CacheOpts ¶
func (x *Cmd) CacheOpts()
CacheOpts updates the [opts] cache by splitting [Opts]. Remember to call this whenever dynamically altering the value at runtime.
func (*Cmd) Can ¶
Can returns the *Cmd from [Cmds] if the [Cmd.Name] or any alias in [Cmd.Alias] for that command matches the name passed. If more than one argument is passed calls itself recursively on each item in the list.
Example ¶
package main
import (
"fmt"
bonzai "github.com/rwxrob/bonzai/pkg"
)
func main() {
barCmd := &bonzai.Cmd{
Name: `bar`,
Call: func(_ *bonzai.Cmd, _ ...string) error {
fmt.Println(`i am bar`)
return nil
},
}
fooCmd := &bonzai.Cmd{
Name: `foo`,
Cmds: []*bonzai.Cmd{barCmd},
}
fmt.Println(fooCmd.Can(`bar`))
}
Output: bar
func (*Cmd) CmdAliasMap ¶
CmdAliasMap calls [CacheCmdAlias] to update cache if it is nil and then returns it. [Hide] is not applied.
func (*Cmd) Fill ¶
Fill fills out the text/template string using the Cmd data fields and [Cmd.FuncMap] values combined with bonzai.FuncMap.
func (*Cmd) Get ¶
Get is a shorter version of Vars.Get(x.Path()+"."+key) which fetches and returns persisted cache values (see Vars and [VarsDriver]). If a value has not yet been assigned returns the value from Vars and sets it with [Set]. All var keys must be declared and assigned initial values with Vars or they cannot be used and throw an UnsupportedVar run.ExitError.
func (*Cmd) HideSlice ¶
HideSlice updates the [hidden] internal cache ([CacheHide]) and returns it as a slice.
func (*Cmd) OptsSlice ¶
OptsSlice updates the [params] internal cache ([CacheOpts]) and returns it as a slice.
func (*Cmd) Path ¶
Path returns a dotted notation of the [PathNames] including an initial dot (for root). This is useful for associating configuration and other data specifically with this command. If any arguments are passed then will be added with dots between them.
func (*Cmd) PathCmds ¶
PathCmds returns the path of commands used to arrive at this command. The path is determined by walking backward from current Caller up rather than depending on anything from the command line used to invoke the composing binary. Also see [Path], [PathNames].
func (*Cmd) PathNames ¶
PathNames returns the path of command names used to arrive at this command. The path is determined by walking backward from current Caller up rather than depending on anything from the command line used to invoke the composing binary. Also see Path.
func (*Cmd) PathWithDashes ¶
PathWithDashes is the same as [Path] but with dashes/hyphens instead and without the leading dot.
func (*Cmd) PrependCmd ¶
PrependCmd safely prepends the passed *Cmd to the [Cmds] slice.
func (*Cmd) Print ¶
Print calls [Fill] on string and prints it with fmt.Print. This is a rather expensive operation by comparison. Consider the simpler alternative or term.Print.
func (*Cmd) Println ¶
Println calls [Fill] on string and prints it with fmt.Println. This is a rather expensive operation by comparison. Consider the simpler alternative or term.Print.
func (*Cmd) Resolve ¶
Resolve looks up a given Cmd by name or alias from [Alias] (caching a lookup map of aliases in the process).
func (*Cmd) Root ¶
Root returns the root Cmd from the current [Path]. This must always be calculated every time since any Cmd can change positions and pedigrees at any time at run time. Returns self if no [PathCmds] found.
func (*Cmd) Run ¶
Run method resolves [Cmd.Alias] and seeks the leaf Cmd. It then calls the leaf's first-class [Cmd.Call] function passing itself as the first argument along with any remaining command line arguments. Run returns nothing because it usually exits the program. Normally, Run is called from within main() to convert the Cmd into an actual executable program. Use Call instead of Run when delegation is needed. However, avoid tight-coupling that comes from delegation with Call when possible. Also, Call automatically assumes the proper number and type of arguments have already been checked (see [Cmd.MinArgs], etc.) which is normally done by Run.
Completion ¶
Since Run is the main execution entry point for all Bonzai command trees it is also responsible for handling bash completion. Only bash completion is supported within the binary itself because only bash provides self-completion (complete -C foo foo). However, zsh can also be made to support it by adding a few functions from the oh-my-zsh code base).
Completion mode is triggered by the detection of the COMP_LINE environment variable. (complete -C cmd cmd).
When COMP_LINE is set, Run prints a list of possible completions to standard output by calling the [Completer.Complete] function of its [Comp] field. If [Comp] is nil no completion is attempted. Each Cmd explicitly manages its own completion and can draw from an growing ecosystem of Completers or assign its own. See the core/comp package for more examples.
Multicall binary and links ¶
Popularized by BusyBox/Alpine, a multicall binary is a single executable that behaves differently based on its name, either through copying the binary to another name, or linking (symbolic or hard). All Bonzai compiled binaries automatically behave as multicall binaries provided the name of the actual binary or link matches the name of Cmd.
Note that this method should never be used to obscure a highly sensitive command thinking it won't be discovered. Discovering every possible command is very easy to brute force.
Never panic ¶
All panics are trapped with run.TrapPanic which normally exits with 1 and outputs the main message. See run.TrapPanic for details.
Valid name check ¶
Throws InvalidName error and exist if [Name] does not pass InvalidName check.
Subcommand optional arguments ¶
If any argument is detected, delegation through recursive Run calls to subcommands is attempted. If more than one argument, each argument is assumed to be a [Name] or alias from [Alias] and so on (see [Can] for details). As a convenience, if only one argument is passed and that argument contains a dash, it is assumed to be a [PathWithDashes] and is split and expanded into a new args list as if every field where passed as separate strings instead.
func (*Cmd) Seek ¶
Seek checks the args for command names returning the deepest along with the remaining arguments. Typically the args passed are directly from the command line. Seek also sets the Caller on each Cmd found during resolution.
func (Cmd) String ¶
String fulfills the fmt.Stringer interface for debugging.
type Completer ¶
Completer specifies a struct with a [Completer.Complete] function that will complete the first argument (usually a command of some kind) based on the remaining arguments. The [Complete] method must never panic and always return at least an empty slice of strings. By convention Completers that do not make use of or other arguments should use an underscore identifier since they are ignored.
type IncorrectUsage ¶
type IncorrectUsage struct {
Cmd *Cmd
}
func (IncorrectUsage) Error ¶
func (e IncorrectUsage) Error() string
type InvalidMultiName ¶
func (InvalidMultiName) Error ¶
func (e InvalidMultiName) Error() string
type InvalidName ¶
type InvalidName struct {
Name string
}
func (InvalidName) Error ¶
func (e InvalidName) Error() string
type Method ¶
Method defines the main code to execute for a command [Cmd.Call]. By convention the parameter list should be named "args" and the caller "x". If either is unused an underscore should be used instead.
type MissingVar ¶
type MissingVar struct {
Path string
}
func (MissingVar) Error ¶
func (e MissingVar) Error() string
type NoCallNoDef ¶
type NoCallNoDef struct {
Cmd *Cmd
}
func (NoCallNoDef) Error ¶
func (e NoCallNoDef) Error() string
type NotEnoughArgs ¶
func (NotEnoughArgs) Error ¶
func (e NotEnoughArgs) Error() string
type TooManyArgs ¶
func (TooManyArgs) Error ¶
func (e TooManyArgs) Error() string
type Uncallable ¶
type Uncallable struct {
Cmd *Cmd
}
func (Uncallable) Error ¶
func (e Uncallable) Error() string
type UnsupportedVar ¶
type UnsupportedVar struct {
Name string
}
func (UnsupportedVar) Error ¶
func (e UnsupportedVar) Error() string
type VarsInitFailed ¶
type VarsInitFailed struct {
Err error
}
func (VarsInitFailed) Error ¶
func (e VarsInitFailed) Error() string
type WrongNumArgs ¶
func (WrongNumArgs) Error ¶
func (e WrongNumArgs) Error() string