-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcmdmux.go
110 lines (94 loc) · 2.39 KB
/
cmdmux.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// Package cmdmux is used to parse and route commands of terminal program.
package cmdmux
import (
"errors"
"fmt"
"io"
"os"
"strings"
)
// CmdHanlder is the type of callback function for command.
// if error is nil, then return value int is useful.
type CmdHandler func([]string, interface{}) (int, error)
// CmdMux represents program's commands.
type CmdMux struct {
root *cmdNode
}
var std = New()
// New creates a CmdMux with the default "/" empty command.
func New() *CmdMux {
n := newCmdNode("/")
c := &CmdMux{root: n}
return c
}
// PrintTree outputs a simple tree structure of c
func (c *CmdMux) PrintTree(w io.Writer) {
c.root.printTree(w)
}
// HandleFunc registers the handler function for the given command path cmdpath
func (c *CmdMux) HandleFunc(cmdpath string, handler CmdHandler) error {
if cmdpath[0] != '/' {
return errors.New("cmdmux: cmdpath should be absolute")
}
if cmdpath == "/" {
c.root.handler = handler
return nil
}
cmdStrs := strings.Split(cmdpath, "/")[1:]
last := len(cmdStrs) - 1
node := c.root
for i, v := range cmdStrs {
sub := node.hasSubNode(v)
if sub == nil {
sub = newCmdNode(v)
node.subNodes = append(node.subNodes, sub)
}
if i == last {
node = sub
break
}
node = sub
}
node.handler = handler
//fmt.Printf("cmdmux: add handler %s -> %s\n", cmdpath, node.name)
return nil
}
// Execute accepts the os.Args as command and executes it with data
func (c *CmdMux) Execute(data interface{}) (int, error) {
path := ""
node := c.root
var opts []string
args := os.Args[1:]
for i, v := range args {
sub := node.hasSubNode(v)
if sub == nil {
opts = args[i:]
break
}
node = sub
path = path + "/" + node.name
}
if path == "" {
path = "/"
}
if node.handler == nil {
msg := fmt.Sprintf("cmdmux: %s does not have a handler.", path)
return 0, errors.New(msg)
}
//fmt.Printf("cmdmux: invode %s\n", path)
return node.handler(opts, data)
}
// HandleFunc registers the handler function for the given command path cmdpath
// in the default CmdMux.
func HandleFunc(cmdpath string, handler CmdHandler) error {
return std.HandleFunc(cmdpath, handler)
}
// Execute accepts the os.Args as command and executes it with data
// in the default CmdMux
func Execute(data interface{}) (int, error) {
return std.Execute(data)
}
// PrintTree outputs a simple tree structure of built-in cmdmux
func PrintTree(w io.Writer) {
std.PrintTree(w)
}