Bot: simplified Arguments of a CommandContext

This commit is contained in:
diamondburned (Forefront) 2020-01-25 14:07:49 -08:00
parent 0c8c43d3f5
commit 39e6188787
4 changed files with 29 additions and 34 deletions

View File

@ -41,7 +41,7 @@ func (r *RawArguments) ParseContent(args []string) error {
return nil
}
func (r *RawArguments) Arg(n int) string {
func (r RawArguments) Arg(n int) string {
if n < 0 || n >= len(r.Arguments) {
return ""
}
@ -49,7 +49,7 @@ func (r *RawArguments) Arg(n int) string {
return r.Arguments[n]
}
func (r *RawArguments) After(n int) string {
func (r RawArguments) After(n int) string {
if n < 0 || n >= len(r.Arguments) {
return ""
}
@ -57,19 +57,23 @@ func (r *RawArguments) After(n int) string {
return strings.Join(r.Arguments[n:], " ")
}
func (r *RawArguments) String() string {
func (r RawArguments) String() string {
return r.Command + " " + strings.Join(r.Arguments, " ")
}
func (r *RawArguments) Length() int {
func (r RawArguments) Length() int {
return len(r.Arguments)
}
// Argument is each argument in a method.
type Argument struct {
String string
Type reflect.Type
// Rule: pointer for structs, direct for primitives
Type reflect.Type
// if nil, then manual
fn argumentValueFn
manual reflect.Method
}
// nilV, only used to return an error

View File

@ -206,8 +206,14 @@ func (ctx *Context) callMessageCreate(mc *gateway.MessageCreateEvent) error {
// Start converting
var argv []reflect.Value
// Here's an edge case: when the handler takes no arguments, we allow that
// anyway, as they might've used the raw content.
if len(cmd.Arguments) == 0 {
goto Call
}
// Check manual parser
if cmd.parseType != nil {
if cmd.Arguments[0].fn == nil {
if len(args[start:]) == 0 {
return &ErrInvalidUsage{
Args: args,
@ -219,10 +225,10 @@ func (ctx *Context) callMessageCreate(mc *gateway.MessageCreateEvent) error {
}
// Create a zero value instance of this
v := reflect.New(cmd.parseType)
v := reflect.New(cmd.Arguments[0].Type)
// Call the manual parse method
ret := cmd.parseMethod.Func.Call([]reflect.Value{
ret := cmd.Arguments[0].manual.Func.Call([]reflect.Value{
v, reflect.ValueOf(args),
})
@ -237,12 +243,6 @@ func (ctx *Context) callMessageCreate(mc *gateway.MessageCreateEvent) error {
goto Call
}
// Here's an edge case: when the handler takes no arguments, we allow that
// anyway, as they might've used the raw content.
if len(cmd.Arguments) == 0 {
goto Call
}
// Not enough arguments given
if len(args[start:]) != len(cmd.Arguments) {
return &ErrInvalidUsage{

View File

@ -70,11 +70,6 @@ type CommandContext struct {
method reflect.Method
Arguments []Argument
// only for ParseContent interface
parseMethod reflect.Method
parseType reflect.Type
parseUsage string
}
// CanSetup is used for subcommands to change variables, such as Description.
@ -86,10 +81,6 @@ type CanSetup interface {
}
func (cctx *CommandContext) Usage() []string {
if cctx.parseType != nil {
return []string{cctx.parseUsage}
}
if len(cctx.Arguments) == 0 {
return nil
}
@ -333,9 +324,15 @@ func (sub *Subcommand) parseCommands() error {
if t := methodT.In(1); t.Implements(typeIManP) {
mt, _ := t.MethodByName("ParseContent")
command.parseMethod = mt
command.parseType = t.Elem()
command.parseUsage = t.String()
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
command.Arguments = []Argument{{
String: t.String(),
Type: t,
manual: mt,
}}
goto Done
}

View File

@ -49,11 +49,8 @@ func TestSubcommand(t *testing.T) {
case "custom":
foundCustom = true
if len(this.Arguments) > 0 {
t.Fatal("arguments should be 0 for custom")
}
if this.parseType == nil {
t.Fatal("custom has nil manualParse")
if len(this.Arguments) != 1 {
t.Fatal("arguments should be 1 for custom")
}
case "noArgs":
@ -61,9 +58,6 @@ func TestSubcommand(t *testing.T) {
if len(this.Arguments) != 0 {
t.Fatal("expected 0 arguments, got non-zero")
}
if this.parseType != nil {
t.Fatal("unexpected parseType")
}
case "noop", "getCounter":
// Found, but whatever