Add Cmd.Shortcuts

pull/97/head v0.12.0
rwxrob 2 years ago
parent c5d6bb50aa
commit c7583b8f82
No known key found for this signature in database
GPG Key ID: 2B9111F33082AE77

@ -89,6 +89,8 @@ type Command interface {
GetName() string GetName() string
GetTitle() string GetTitle() string
GetAliases() []string GetAliases() []string
GetShortcutsMap() map[string][]string
GetShortcuts() []string
GetSummary() string GetSummary() string
GetUsage() string GetUsage() string
GetVersion() string GetVersion() string

@ -290,6 +290,20 @@ func ArgsOrIn(args []string) string {
return strings.Join(args, " ") return strings.Join(args, " ")
} }
// ArgMap is a map keyed to individual arguments that should be
// expanded by being replaced with the slice of strings. Z.Aliases and
// Cmd.Shortcuts are both ArgMaps.
type ArgMap map[string][]string
// Keys returns only the key names.
func (m ArgMap) Keys() []string {
var list []string
for k, _ := range m {
list = append(list, k)
}
return list
}
// Shortcuts allows Bonzai tree developers to create single-word // Shortcuts allows Bonzai tree developers to create single-word
// shortcuts (similar to shell aliases) that are directly translated // shortcuts (similar to shell aliases) that are directly translated
// into arguments to the Bonzai tree executable by overriding the // into arguments to the Bonzai tree executable by overriding the
@ -297,7 +311,7 @@ func ArgsOrIn(args []string) string {
// of strings that will replace the os.Args[2:]. A slice is used // of strings that will replace the os.Args[2:]. A slice is used
// (instead of a string parsed with strings.Fields) to ensure that // (instead of a string parsed with strings.Fields) to ensure that
// hard-coded arguments containing whitespace are properly handled. // hard-coded arguments containing whitespace are properly handled.
var Shortcuts = make(map[string][]string) var Shortcuts = make(ArgMap)
// AllowPanic disables TrapPanic stopping it from cleaning panic errors. // AllowPanic disables TrapPanic stopping it from cleaning panic errors.
var AllowPanic = false var AllowPanic = false

@ -25,6 +25,7 @@ type Cmd struct {
// main documentation, use Get* for filled template // main documentation, use Get* for filled template
Name string `json:"name,omitempty"` // plain Name string `json:"name,omitempty"` // plain
Aliases []string `json:"aliases,omitempty"` // plain Aliases []string `json:"aliases,omitempty"` // plain
Shortcuts ArgMap `json:"shortcuts,omitempty"` // plain
Summary string `json:"summary,omitempty"` // template Summary string `json:"summary,omitempty"` // template
Usage string `json:"usage,omitempty"` // template Usage string `json:"usage,omitempty"` // template
Version string `json:"version,omitempty"` // template Version string `json:"version,omitempty"` // template
@ -185,19 +186,19 @@ func (x *Cmd) cacheSections() {
} }
} }
// Run method resolves aliases and seeks the leaf Cmd. It then calls the // Run method resolves Shortcuts and Aliases and seeks the leaf Cmd. It
// leaf's first-class Call function passing itself as the first argument // then calls the leaf's first-class Call function passing itself as the
// along with any remaining command line arguments. Run returns nothing // first argument along with any remaining command line arguments. Run
// because it usually exits the program. Normally, Run is called from // returns nothing because it usually exits the program. Normally, Run
// within main() to convert the Cmd into an actual executable program. // is called from within main() to convert the Cmd into an actual
// Exiting can be controlled, however, by calling ExitOn or ExitOff // executable program. Exiting can be controlled, however, by calling
// (primarily for testing). Use Call instead of Run when delegation is // ExitOn or ExitOff (primarily for testing). Use Call instead of Run
// needed. However, avoid tight-coupling that comes from delegation with // when delegation is needed. However, avoid tight-coupling that comes
// Call when possible. Also, Call automatically assumes the proper // from delegation with Call when possible. Also, Call automatically
// number and type of arguments have already been checked (see MinArgs, // assumes the proper number and type of arguments have already been
// MaxArgs, NumArgs, etc.) which is normally done by Run. Use // checked (see MinArgs, MaxArgs, NumArgs, etc.) which is normally done
// a high-level branch pkg instead (which is idiomatic for good Bonzai // by Run. Use a high-level branch pkg instead (which is idiomatic for
// branch development). // good Bonzai branch development).
// //
// Handling Completion // Handling Completion
// //
@ -459,7 +460,8 @@ func (x *Cmd) IsHidden(name string) bool {
// Seek checks the args for command names returning the deepest along // Seek checks the args for command names returning the deepest along
// with the remaining arguments. Typically the args passed are directly // with the remaining arguments. Typically the args passed are directly
// from the command line. // from the command line. Seek also sets the Caller on each Cmd found
// during resolution. Cmd.Shortcuts are expanded.
func (x *Cmd) Seek(args []string) (*Cmd, []string) { func (x *Cmd) Seek(args []string) (*Cmd, []string) {
if args == nil || x.Commands == nil { if args == nil || x.Commands == nil {
return x, args return x, args
@ -474,6 +476,13 @@ func (x *Cmd) Seek(args []string) (*Cmd, []string) {
next.Caller = cur next.Caller = cur
cur = next cur = next
} }
if len(cur.Shortcuts) > 0 {
if v, has := cur.Shortcuts[args[n]]; has {
nargs := v
nargs = append(nargs, args[n+1:]...)
return cur.Seek(nargs)
}
}
return cur, args[n:] return cur, args[n:]
} }
@ -604,6 +613,14 @@ func (x *Cmd) GetTitle() string { return x.Title() }
// GetAliases fulfills the bonzai.Command interface. No Fill. // GetAliases fulfills the bonzai.Command interface. No Fill.
func (x *Cmd) GetAliases() []string { return x.Aliases } func (x *Cmd) GetAliases() []string { return x.Aliases }
// GetShortcutsMap fulfills the bonzai.Command interface. No Fill.
func (x *Cmd) GetShortcutsMap() map[string][]string {
return map[string][]string(x.Shortcuts)
}
// GetShortcuts fulfills the bonzai.Command interface. No Fill.
func (x *Cmd) GetShortcuts() []string { return x.Shortcuts.Keys() }
// GetSummary fulfills the bonzai.Command interface. Uses Fill. // GetSummary fulfills the bonzai.Command interface. Uses Fill.
func (x *Cmd) GetSummary() string { return x.Fill(x.Summary) } func (x *Cmd) GetSummary() string { return x.Fill(x.Summary) }

Loading…
Cancel
Save