feat(cli): separate python commands into own namespace
This commit is contained in:
parent
b6d8cc534d
commit
d1200b81d1
2 changed files with 65 additions and 32 deletions
57
cli/cli.go
57
cli/cli.go
|
@ -25,27 +25,40 @@ type Command struct {
|
|||
// Must be initialized with commands via AddCommand before running
|
||||
// with Run.
|
||||
type CLI struct {
|
||||
// Commands in enumeration order.
|
||||
OrderedCommands []string
|
||||
// Command metadata entries.
|
||||
Commands map[string]Command
|
||||
Namespaces map[string]Namespace
|
||||
Metadata map[string]string
|
||||
}
|
||||
|
||||
type Namespace struct {
|
||||
Label string
|
||||
Commands map[string]Command
|
||||
OrderedCommands []string
|
||||
}
|
||||
|
||||
func (c *CLI) AddNamespace(namespace Namespace) *CLI {
|
||||
if c.Namespaces == nil {
|
||||
c.Namespaces = map[string]Namespace{}
|
||||
}
|
||||
|
||||
c.Namespaces[namespace.Label] = namespace
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
// Registers a command.
|
||||
// This specifies a label that is used to route the user input to
|
||||
// the right command, a handler that is called when the label is used,
|
||||
// and usage/description details that get included in autogenerated help messaging.
|
||||
func (c CLI) AddCommand(label string, handler func([]string, Flags, state.State) error, usage string, description string) CLI {
|
||||
if c.Commands == nil {
|
||||
c.Commands = map[string]Command{}
|
||||
c.OrderedCommands = []string{}
|
||||
func (n *Namespace) AddCommand(label string, handler func([]string, Flags, state.State) error, usage string, description string) *Namespace {
|
||||
if n.Commands == nil {
|
||||
n.Commands = map[string]Command{}
|
||||
n.OrderedCommands = []string{}
|
||||
}
|
||||
|
||||
c.OrderedCommands = append(c.OrderedCommands, label)
|
||||
c.Commands[label] = Command{Label: label, Handler: handler, Usage: usage, Description: description}
|
||||
n.OrderedCommands = append(n.OrderedCommands, label)
|
||||
n.Commands[label] = Command{Label: label, Handler: handler, Usage: usage, Description: description}
|
||||
|
||||
return c
|
||||
return n
|
||||
}
|
||||
|
||||
// Executes one of the registered commands if any match the provided
|
||||
|
@ -56,26 +69,38 @@ func (c CLI) Run(args []string, currentState state.State) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
command := args[0]
|
||||
action := args[0]
|
||||
|
||||
if command == "help" {
|
||||
if action == "help" {
|
||||
c.Help()
|
||||
return nil
|
||||
}
|
||||
|
||||
flags := collectFlags(args)
|
||||
return c.Commands[command].Handler(args, flags, currentState)
|
||||
|
||||
namespace, isNamespace := c.Namespaces[action]
|
||||
|
||||
if isNamespace {
|
||||
action = args[1]
|
||||
return namespace.Commands[action].Handler(args[1:], flags, currentState)
|
||||
}
|
||||
|
||||
rootNamespace := c.Namespaces[""]
|
||||
|
||||
return rootNamespace.Commands[action].Handler(args, flags, currentState)
|
||||
}
|
||||
|
||||
// Prints autogenerated help documentation specifying command usage
|
||||
// and descriptions based on registered commands (see: AddCommand).
|
||||
func (c CLI) Help() {
|
||||
logger.InfoLogger.Printf("v: A simple version manager. (v%s)\n---", c.Metadata["Version"])
|
||||
for _, commandLabel := range c.OrderedCommands {
|
||||
command := c.Commands[commandLabel]
|
||||
for _, namespace := range c.Namespaces {
|
||||
for _, commandLabel := range namespace.OrderedCommands {
|
||||
command := namespace.Commands[commandLabel]
|
||||
logger.InfoLogger.Printf("\033[1m%-30s\033[0m%s\n", command.Usage, command.Description)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Traverses input arguments and extracts flags of
|
||||
// the form --<flag-label>.
|
||||
|
|
38
v.go
38
v.go
|
@ -18,27 +18,35 @@ func main() {
|
|||
args := os.Args[1:]
|
||||
currentState := state.ReadState()
|
||||
|
||||
root := cli.Namespace{Label: ""}
|
||||
root.AddCommand(
|
||||
"init", Initialize, "v init", "Initializes the v state.",
|
||||
)
|
||||
|
||||
pythonCommands := cli.Namespace{Label: "python"}
|
||||
pythonCommands.AddCommand(
|
||||
"install", python.InstallPython, "v python install <version>", "Downloads, builds and installs a new version of Python.",
|
||||
).AddCommand(
|
||||
"uninstall", python.UninstallPython, "v python uninstall <version>", "Uninstalls the given Python version.",
|
||||
).AddCommand(
|
||||
"use", python.Use, "v python use <version>", "Selects which Python version to use.",
|
||||
).AddCommand(
|
||||
"ls", python.ListVersions, "v python ls", "Lists the installed Python versions.",
|
||||
).AddCommand(
|
||||
"version", python.CurrentVersion, "v python version", "Prints the current version and its source.",
|
||||
).AddCommand(
|
||||
"which", python.Which, "v python which", "Prints the path to the current Python version.",
|
||||
)
|
||||
|
||||
cli := cli.CLI{
|
||||
Metadata: map[string]string{
|
||||
"Version": Version,
|
||||
},
|
||||
}
|
||||
|
||||
err := cli.AddCommand(
|
||||
"install", python.InstallPython, "v install <version>", "Downloads, builds and installs a new version of Python.",
|
||||
).AddCommand(
|
||||
"uninstall", python.UninstallPython, "v uninstall <version>", "Uninstalls the given Python version.",
|
||||
).AddCommand(
|
||||
"use", python.Use, "v use <version>", "Selects which Python version to use.",
|
||||
).AddCommand(
|
||||
"ls", python.ListVersions, "v ls", "Lists the installed Python versions.",
|
||||
).AddCommand(
|
||||
"version", python.CurrentVersion, "v version", "Prints the current version and its source.",
|
||||
).AddCommand(
|
||||
"which", python.Which, "v which", "Prints the path to the current Python version.",
|
||||
).AddCommand(
|
||||
"init", Initialize, "v init", "Initializes the v state.",
|
||||
).Run(args, currentState)
|
||||
cli.AddNamespace(root).AddNamespace(pythonCommands)
|
||||
|
||||
err := cli.Run(args, currentState)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
|
Loading…
Reference in a new issue