diff --git a/commands/event.go b/commands/event.go index 7370844c..10d6283f 100644 --- a/commands/event.go +++ b/commands/event.go @@ -126,17 +126,20 @@ func (evt *Event[MetaType]) MarkRead() { } } -// PromoteFirstArgToCommand promotes the first argument to the command name. -// -// Command will be set to the lowercased first item in the Args list. -// Both Args and RawArgs will be updated to remove the first argument, but RawInput will be left as-is. -// -// The caller MUST check that there are args before calling this function. -func (evt *Event[MetaType]) PromoteFirstArgToCommand() { +// ShiftArg removes the first argument from the Args list and RawArgs data and returns it. +// RawInput will not be modified. +func (evt *Event[MetaType]) ShiftArg() string { if len(evt.Args) == 0 { - panic(fmt.Errorf("PromoteFirstArgToCommand called with no args")) + return "" } - evt.Command = strings.ToLower(evt.Args[0]) + firstArg := evt.Args[0] evt.RawArgs = strings.TrimLeft(strings.TrimPrefix(evt.RawArgs, evt.Args[0]), " ") evt.Args = evt.Args[1:] + return firstArg +} + +// UnshiftArg reverses ShiftArg by adding the given value to the beginning of the Args list and RawArgs data. +func (evt *Event[MetaType]) UnshiftArg(arg string) { + evt.RawArgs = arg + " " + evt.RawArgs + evt.Args = append([]string{arg}, evt.Args...) } diff --git a/commands/handler.go b/commands/handler.go index d4c53ff6..b01d594f 100644 --- a/commands/handler.go +++ b/commands/handler.go @@ -11,6 +11,7 @@ import ( ) type Handler[MetaType any] struct { + // Func is the function that is called when the command is executed. Func func(ce *Event[MetaType]) // Name is the primary name of the command. It must be lowercase. @@ -19,6 +20,10 @@ type Handler[MetaType any] struct { Aliases []string // Subcommands are subcommands of this command. Subcommands []*Handler[MetaType] + // PreFunc is a function that is called before checking subcommands. + // It can be used to have parameters between subcommands (e.g. `!rooms `). + // Event.ShiftArg will likely be useful for implementing such parameters. + PreFunc func(ce *Event[MetaType]) subcommandContainer *CommandContainer[MetaType] } diff --git a/commands/prevalidate.go b/commands/prevalidate.go index 66da2b49..facca4da 100644 --- a/commands/prevalidate.go +++ b/commands/prevalidate.go @@ -61,7 +61,7 @@ func (f AnyPreValidator[MetaType]) Validate(ce *Event[MetaType]) bool { func ValidatePrefixCommand[MetaType any](prefix string) PreValidator[MetaType] { return FuncPreValidator[MetaType](func(ce *Event[MetaType]) bool { if ce.Command == prefix && len(ce.Args) > 0 { - ce.PromoteFirstArgToCommand() + ce.Command = strings.ToLower(ce.ShiftArg()) return true } return false diff --git a/commands/processor.go b/commands/processor.go index c4077250..1e0a99a2 100644 --- a/commands/processor.go +++ b/commands/processor.go @@ -65,20 +65,31 @@ func (proc *Processor[MetaType]) Process(ctx context.Context, evt *event.Event) if !proc.PreValidator.Validate(parsed) { return } + parsed.Proc = proc + parsed.Meta = proc.Meta + parsed.Ctx = ctx handler := proc.GetHandler(parsed.Command) if handler == nil { return } + parsed.Handler = handler + if handler.PreFunc != nil { + handler.PreFunc(parsed) + } handlerChain := zerolog.Arr() handlerChain.Str(handler.Name) for handler.subcommandContainer != nil && len(parsed.Args) > 0 { subHandler := handler.subcommandContainer.GetHandler(strings.ToLower(parsed.Args[0])) if subHandler != nil { + handler = subHandler parsed.ParentCommands = append(parsed.ParentCommands, parsed.Command) handlerChain.Str(subHandler.Name) - parsed.PromoteFirstArgToCommand() - handler = subHandler + parsed.Command = strings.ToLower(parsed.ShiftArg()) + parsed.Handler = subHandler + if subHandler.PreFunc != nil { + subHandler.PreFunc(parsed) + } } } @@ -95,9 +106,6 @@ func (proc *Processor[MetaType]) Process(ctx context.Context, evt *event.Event) } log = logWith.Logger() parsed.Ctx = log.WithContext(ctx) - parsed.Handler = handler - parsed.Proc = proc - parsed.Meta = proc.Meta log.Debug().Msg("Processing command") handler.Func(parsed)