Make BouncerServ commands a tree
For instance, replace "create-network" with "network create".
This commit is contained in:
parent
04dd9d51f3
commit
448464b0e4
90
service.go
90
service.go
@ -12,10 +12,13 @@ import (
|
|||||||
|
|
||||||
const serviceNick = "BouncerServ"
|
const serviceNick = "BouncerServ"
|
||||||
|
|
||||||
|
type serviceCommandSet map[string]*serviceCommand
|
||||||
|
|
||||||
type serviceCommand struct {
|
type serviceCommand struct {
|
||||||
usage string
|
usage string
|
||||||
desc string
|
desc string
|
||||||
handle func(dc *downstreamConn, params []string) error
|
handle func(dc *downstreamConn, params []string) error
|
||||||
|
children serviceCommandSet
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendServicePRIVMSG(dc *downstreamConn, text string) {
|
func sendServicePRIVMSG(dc *downstreamConn, text string) {
|
||||||
@ -33,16 +36,9 @@ func handleServicePRIVMSG(dc *downstreamConn, text string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var name string
|
cmd, params, err := serviceCommands.Get(words)
|
||||||
var params []string
|
if err != nil {
|
||||||
if len(words) > 0 {
|
sendServicePRIVMSG(dc, fmt.Sprintf(`error: %v (type "help" for a list of commands)`, err))
|
||||||
name = strings.ToLower(words[0])
|
|
||||||
params = words[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd, ok := serviceCommands[name]
|
|
||||||
if !ok {
|
|
||||||
sendServicePRIVMSG(dc, fmt.Sprintf(`error: unknown command %q (type "help" for a list of commands)`, name))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,43 +47,93 @@ func handleServicePRIVMSG(dc *downstreamConn, text string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var serviceCommands map[string]serviceCommand
|
func (cmds serviceCommandSet) Get(params []string) (*serviceCommand, []string, error) {
|
||||||
|
if len(params) == 0 {
|
||||||
|
return nil, nil, fmt.Errorf("no command specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
name := params[0]
|
||||||
|
params = params[1:]
|
||||||
|
|
||||||
|
cmd, ok := cmds[name]
|
||||||
|
if !ok {
|
||||||
|
for k := range cmds {
|
||||||
|
if !strings.HasPrefix(k, name) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if cmd != nil {
|
||||||
|
return nil, params, fmt.Errorf("command %q is ambiguous", name)
|
||||||
|
}
|
||||||
|
cmd = cmds[k]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if cmd == nil {
|
||||||
|
return nil, params, fmt.Errorf("command %q not found", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(params) == 0 || len(cmd.children) == 0 {
|
||||||
|
return cmd, params, nil
|
||||||
|
}
|
||||||
|
return cmd.children.Get(params)
|
||||||
|
}
|
||||||
|
|
||||||
|
var serviceCommands serviceCommandSet
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
serviceCommands = map[string]serviceCommand{
|
serviceCommands = serviceCommandSet{
|
||||||
"help": {
|
"help": {
|
||||||
usage: "[command]",
|
usage: "[command]",
|
||||||
desc: "print help message",
|
desc: "print help message",
|
||||||
handle: handleServiceHelp,
|
handle: handleServiceHelp,
|
||||||
},
|
},
|
||||||
"create-network": {
|
"network": {
|
||||||
|
children: serviceCommandSet{
|
||||||
|
"create": {
|
||||||
usage: "-addr <addr> [-name name] [-username username] [-pass pass] [-realname realname] [-nick nick]",
|
usage: "-addr <addr> [-name name] [-username username] [-pass pass] [-realname realname] [-nick nick]",
|
||||||
desc: "add a new network",
|
desc: "add a new network",
|
||||||
handle: handleServiceCreateNetwork,
|
handle: handleServiceCreateNetwork,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendServiceCommandSetHelp(cmds serviceCommandSet, prefix []string, l *[]string) {
|
||||||
|
for name, cmd := range cmds {
|
||||||
|
words := append(prefix, name)
|
||||||
|
if len(cmd.children) == 0 {
|
||||||
|
s := strings.Join(words, " ")
|
||||||
|
*l = append(*l, s)
|
||||||
|
} else {
|
||||||
|
appendServiceCommandSetHelp(cmd.children, words, l)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleServiceHelp(dc *downstreamConn, params []string) error {
|
func handleServiceHelp(dc *downstreamConn, params []string) error {
|
||||||
if len(params) > 0 {
|
if len(params) > 0 {
|
||||||
name := strings.ToLower(params[0])
|
cmd, rest, err := serviceCommands.Get(params)
|
||||||
cmd, ok := serviceCommands[name]
|
if err != nil {
|
||||||
if !ok {
|
return err
|
||||||
return fmt.Errorf("unknown command %q", name)
|
|
||||||
}
|
}
|
||||||
|
words := params[:len(params)-len(rest)]
|
||||||
|
|
||||||
text := name
|
if len(cmd.children) > 0 {
|
||||||
|
var l []string
|
||||||
|
appendServiceCommandSetHelp(cmd.children, words, &l)
|
||||||
|
sendServicePRIVMSG(dc, "available commands: "+strings.Join(l, ", "))
|
||||||
|
} else {
|
||||||
|
text := strings.Join(words, " ")
|
||||||
if cmd.usage != "" {
|
if cmd.usage != "" {
|
||||||
text += " " + cmd.usage
|
text += " " + cmd.usage
|
||||||
}
|
}
|
||||||
text += ": " + cmd.desc
|
text += ": " + cmd.desc
|
||||||
|
|
||||||
sendServicePRIVMSG(dc, text)
|
sendServicePRIVMSG(dc, text)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
var l []string
|
var l []string
|
||||||
for name := range serviceCommands {
|
appendServiceCommandSetHelp(serviceCommands, nil, &l)
|
||||||
l = append(l, name)
|
|
||||||
}
|
|
||||||
sendServicePRIVMSG(dc, "available commands: "+strings.Join(l, ", "))
|
sendServicePRIVMSG(dc, "available commands: "+strings.Join(l, ", "))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -107,7 +153,7 @@ func handleServiceCreateNetwork(dc *downstreamConn, params []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if *addr == "" {
|
if *addr == "" {
|
||||||
return fmt.Errorf("flag addr is required")
|
return fmt.Errorf("flag -addr is required")
|
||||||
}
|
}
|
||||||
|
|
||||||
if *nick == "" {
|
if *nick == "" {
|
||||||
|
@ -71,14 +71,17 @@ The config file has one directive per line.
|
|||||||
|
|
||||||
# IRC SERVICE
|
# IRC SERVICE
|
||||||
|
|
||||||
soju exposes an IRC service called BouncerServ to manage the bouncer. Commands
|
soju exposes an IRC service called *BouncerServ* to manage the bouncer.
|
||||||
can be sent via regular private messages (_/msg BouncerServ <command> [args...]_).
|
Commands can be sent via regular private messages
|
||||||
|
(_/msg BouncerServ <command> [args...]_). Commands may be written in full or
|
||||||
|
abbreviated form, for instance *network* can be abbreviated as *net* or just
|
||||||
|
*n*.
|
||||||
|
|
||||||
*help* [command]
|
*help* [command]
|
||||||
Show a list of commands. If _command_ is specified, show a help message for
|
Show a list of commands. If _command_ is specified, show a help message for
|
||||||
the command.
|
the command.
|
||||||
|
|
||||||
*create-network* *-addr* <addr> [options...]
|
*network create* *-addr* <addr> [options...]
|
||||||
Connect to a new network at _addr_. _-addr_ is mandatory. Other options are:
|
Connect to a new network at _addr_. _-addr_ is mandatory. Other options are:
|
||||||
|
|
||||||
*-name* <name>
|
*-name* <name>
|
||||||
|
Loading…
Reference in New Issue
Block a user