Commit 4af61ad9 authored by Matt Bell's avatar Matt Bell Committed by Juan Batiz-Benet

commands: Added Command#Resolve

parent 4b0f44e4
...@@ -3,6 +3,7 @@ package commands ...@@ -3,6 +3,7 @@ package commands
import ( import (
"fmt" "fmt"
"strings" "strings"
"errors"
) )
type Command struct { type Command struct {
...@@ -12,6 +13,8 @@ type Command struct { ...@@ -12,6 +13,8 @@ type Command struct {
subcommands map[string]*Command subcommands map[string]*Command
} }
var NotCallableError = errors.New("This command can't be called directly. Try one of its subcommands.")
// Register adds a subcommand // Register adds a subcommand
func (c *Command) Register(id string, sub *Command) error { func (c *Command) Register(id string, sub *Command) error {
if c.subcommands == nil { if c.subcommands == nil {
...@@ -37,10 +40,21 @@ func (c *Command) Register(id string, sub *Command) error { ...@@ -37,10 +40,21 @@ func (c *Command) Register(id string, sub *Command) error {
// Call invokes the command at the given subcommand path // Call invokes the command at the given subcommand path
func (c *Command) Call(req *Request) *Response { func (c *Command) Call(req *Request) *Response {
cmd := c
res := &Response{req: req} res := &Response{req: req}
options, err := cmd.GetOptions(req.path) cmds, err := c.Resolve(req.path)
if err != nil {
res.SetError(err, Client)
return res
}
cmd := cmds[len(cmds)-1]
if(cmd.f == nil) {
res.SetError(NotCallableError, Client)
return res
}
options, err := c.GetOptions(req.path)
if err != nil { if err != nil {
res.SetError(err, Client) res.SetError(err, Client)
return res return res
...@@ -57,24 +71,38 @@ func (c *Command) Call(req *Request) *Response { ...@@ -57,24 +71,38 @@ func (c *Command) Call(req *Request) *Response {
return res return res
} }
// GetOptions gets the options in the given path of commands // Resolve gets the subcommands at the given path
func (c *Command) GetOptions(path []string) (map[string]Option, error) { func (c *Command) Resolve(path []string) ([]*Command, error) {
options := make([]Option, len(c.Options)) cmds := make([]*Command, len(path) + 1)
copy(options, c.Options) cmds[0] = c
options = append(options, globalOptions...)
// a nil path means this command, not a subcommand (same as an empty path) cmd := c
if path != nil { for i, name := range path {
for i, id := range path { cmd = cmd.Sub(name)
cmd := c.Sub(id)
if cmd == nil { if cmd == nil {
pathS := strings.Join(path[0:i], "/") pathS := strings.Join(path[0:i], "/")
return nil, fmt.Errorf("Undefined command: '%s'", pathS) return nil, fmt.Errorf("Undefined command: '%s'", pathS)
} }
options = append(options, cmd.Options...) cmds[i+1] = cmd
}
return cmds, nil
}
// GetOptions gets the options in the given path of commands
func (c *Command) GetOptions(path []string) (map[string]Option, error) {
options := make([]Option, len(c.Options))
copy(options, c.Options)
options = append(options, globalOptions...)
cmds, err := c.Resolve(path)
if err != nil {
return nil, err
} }
for _, cmd := range cmds {
options = append(options, cmd.Options...)
} }
optionsMap := make(map[string]Option) optionsMap := make(map[string]Option)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment