package command import ( "fmt" "strings" "git.gophernest.net/azpect/TextEditor/internal/action" tea "github.com/charmbracelet/bubbletea" ) // Command: Represents a command that can be executed from command mode. type Command struct { Name string // Full name: "quit" ShortForm string // Minimum abbreviation: "q" Handler func(m action.Model, args []string, force bool) tea.Cmd // Handler function } // Registry: Holds all registered commands. type Registry struct { commands []Command } // NewRegistry: Creates a new command registry with default commands. func NewRegistry() *Registry { r := &Registry{} r.registerDefaults() return r } // Registry.Register: Adds a command to the registry. func (r *Registry) Register(cmd Command) { r.commands = append(r.commands, cmd) } // Registry.Lookup: Finds a command by name or abbreviation with error handling. func (r *Registry) Lookup(input string) (*Command, error) { if input == "" { return nil, fmt.Errorf("no command given") } var matches []*Command for i := range r.commands { cmd := &r.commands[i] // Exact match on short form if input == cmd.ShortForm { return cmd, nil } // Exact match on full name if input == cmd.Name { return cmd, nil } // Prefix match: input must be at least as long as short form // and must be a prefix of the full name if len(input) >= len(cmd.ShortForm) && strings.HasPrefix(cmd.Name, input) { matches = append(matches, cmd) } } if len(matches) == 0 { return nil, fmt.Errorf("unknown command: %s", input) } if len(matches) > 1 { names := make([]string, len(matches)) for i, m := range matches { names[i] = m.Name } return nil, fmt.Errorf("ambiguous command: %s (could be: %s)", input, strings.Join(names, ", ")) } return matches[0], nil } // Parse: Splits a command line into command name and arguments. func Parse(cmdLine string) (name string, args []string, force bool) { parts := strings.Fields(cmdLine) if len(parts) == 0 { return "", nil, false } name = parts[0] args = parts[1:] // Check if command ends with ! (force flag) if strings.HasSuffix(name, "!") { name = strings.TrimSuffix(name, "!") force = true } return name, args, force } // Registry.Execute: Parses and executes a command line. func (r *Registry) Execute(m action.Model, cmdLine string) (tea.Cmd, error) { name, args, force := Parse(cmdLine) cmd, err := r.Lookup(name) if err != nil { return nil, err } return cmd.Handler(m, args, force), nil } // DefaultRegistry is the global command registry var DefaultRegistry = NewRegistry() // Registry.registerDefaults: Registers the built-in commands. func (r *Registry) registerDefaults() { // Quit commands r.Register(Command{ Name: "quit", ShortForm: "q", Handler: cmdQuit, }) r.Register(Command{ Name: "qall", ShortForm: "qa", Handler: cmdQuitAll, }) // Write commands r.Register(Command{ Name: "write", ShortForm: "w", Handler: cmdWrite, }) r.Register(Command{ Name: "wall", ShortForm: "wa", Handler: cmdWriteAll, }) r.Register(Command{ Name: "wq", ShortForm: "wq", Handler: cmdWriteQuit, }) r.Register(Command{ Name: "wqall", ShortForm: "wqa", Handler: cmdWriteQuitAll, }) // Set command r.Register(Command{ Name: "set", ShortForm: "se", Handler: cmdSet, }) // Register commands r.Register(Command{ Name: "register", ShortForm: "reg", Handler: cmdRegisters, }) // History commands r.Register(Command{ Name: "history", ShortForm: "his", Handler: cmdHistory, }) // Buffer commands r.Register(Command{ Name: "buffers", ShortForm: "buffers", Handler: cmdListBuffers, }) r.Register(Command{ Name: "ls", ShortForm: "ls", Handler: cmdListBuffers, }) r.Register(Command{ Name: "bn", ShortForm: "bn", Handler: cmdNextBuffer, }) r.Register(Command{ Name: "bp", ShortForm: "bp", Handler: cmdPrevBuffer, }) r.Register(Command{ Name: "bf", ShortForm: "bf", Handler: cmdFirstBuffer, }) r.Register(Command{ Name: "bl", ShortForm: "bl", Handler: cmdLastBuffer, }) r.Register(Command{ Name: "b", ShortForm: "b", Handler: cmdSelectBuffer, }) r.Register(Command{ Name: "bdelete", ShortForm: "bd", Handler: cmdDeleteBuffer, }) // File commands r.Register(Command{ Name: "edit", ShortForm: "e", Handler: cmdEdit, }) // Color scheme commands r.Register(Command{ Name: "colorscheme", ShortForm: "colo", Handler: cmdColorscheme, }) r.Register(Command{ Name: "colorschemes", ShortForm: "colorschemes", Handler: cmdListColorschemes, }) }