summaryrefslogtreecommitdiff
path: root/internal/hexaiaction/action_handler.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/hexaiaction/action_handler.go')
-rw-r--r--internal/hexaiaction/action_handler.go88
1 files changed, 88 insertions, 0 deletions
diff --git a/internal/hexaiaction/action_handler.go b/internal/hexaiaction/action_handler.go
new file mode 100644
index 0000000..8da90ea
--- /dev/null
+++ b/internal/hexaiaction/action_handler.go
@@ -0,0 +1,88 @@
+package hexaiaction
+
+import (
+ "context"
+ "fmt"
+ "io"
+ "sync"
+
+ "codeberg.org/snonux/hexai/internal/appconfig"
+)
+
+type actionRequest struct {
+ parts InputParts
+ cfg actionConfig
+ client chatDoer
+ stderr io.Writer
+ selectedCustom *appconfig.CustomAction
+}
+
+// ActionHandler executes one tmux action kind.
+type ActionHandler interface {
+ Execute(context.Context, actionRequest) (string, error)
+}
+
+// CodeActionHandler is kept as a compatibility name for tmux code-action handlers.
+type CodeActionHandler = ActionHandler
+
+type actionHandlerFunc func(context.Context, actionRequest) (string, error)
+
+func (f actionHandlerFunc) Execute(ctx context.Context, req actionRequest) (string, error) {
+ return f(ctx, req)
+}
+
+type actionHandlerRegistry struct {
+ mu sync.RWMutex
+ handlers map[ActionKind]ActionHandler
+}
+
+func newActionHandlerRegistry() *actionHandlerRegistry {
+ return &actionHandlerRegistry{handlers: make(map[ActionKind]ActionHandler)}
+}
+
+func (r *actionHandlerRegistry) register(kind ActionKind, handler ActionHandler) {
+ if kind == "" {
+ panic("hexaiaction: cannot register empty action kind")
+ }
+ if handler == nil {
+ panic(fmt.Sprintf("hexaiaction: cannot register nil handler for %q", kind))
+ }
+
+ r.mu.Lock()
+ defer r.mu.Unlock()
+ if _, exists := r.handlers[kind]; exists {
+ panic(fmt.Sprintf("hexaiaction: handler already registered for %q", kind))
+ }
+ r.handlers[kind] = handler
+}
+
+func (r *actionHandlerRegistry) lookup(kind ActionKind) (ActionHandler, bool) {
+ r.mu.RLock()
+ defer r.mu.RUnlock()
+ handler, ok := r.handlers[kind]
+ return handler, ok
+}
+
+func (r *actionHandlerRegistry) snapshot() map[ActionKind]ActionHandler {
+ r.mu.RLock()
+ defer r.mu.RUnlock()
+ handlers := make(map[ActionKind]ActionHandler, len(r.handlers))
+ for kind, handler := range r.handlers {
+ handlers[kind] = handler
+ }
+ return handlers
+}
+
+var actionHandlers = newActionHandlerRegistry()
+
+func registerActionHandler(kind ActionKind, handler ActionHandler) {
+ actionHandlers.register(kind, handler)
+}
+
+func lookupActionHandler(kind ActionKind) (ActionHandler, bool) {
+ return actionHandlers.lookup(kind)
+}
+
+func codeActionHandlers() map[ActionKind]CodeActionHandler {
+ return actionHandlers.snapshot()
+}