134 lines
2.6 KiB
Go
134 lines
2.6 KiB
Go
package action
|
|
|
|
import (
|
|
tea "github.com/charmbracelet/bubbletea"
|
|
)
|
|
|
|
type ExitCommandMode struct{}
|
|
|
|
func (a ExitCommandMode) Execute(m Model) tea.Cmd {
|
|
m.SetCommandCursor(0)
|
|
m.SetCommand("")
|
|
m.SetCommandOutput("")
|
|
m.SetCommandError(nil)
|
|
m.SetMode(NormalMode)
|
|
return nil
|
|
}
|
|
|
|
type InsertCommandChar struct {
|
|
Char string
|
|
}
|
|
|
|
func (a InsertCommandChar) Execute(m Model) tea.Cmd {
|
|
cur := m.CommandCursor()
|
|
cmd := m.Command()
|
|
|
|
m.SetCommand(cmd[:cur] + a.Char + cmd[cur:])
|
|
m.SetCommandCursor(cur + 1)
|
|
return nil
|
|
}
|
|
|
|
type CommandBackspace struct{}
|
|
|
|
func (a CommandBackspace) Execute(m Model) tea.Cmd {
|
|
cur := m.CommandCursor()
|
|
cmd := m.Command()
|
|
|
|
if cur > 0 {
|
|
m.SetCommand(cmd[:cur-1] + cmd[cur:])
|
|
m.SetCommandCursor(cur - 1)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type CommandDelete struct{}
|
|
|
|
func (a CommandDelete) Execute(m Model) tea.Cmd {
|
|
cur := m.CommandCursor()
|
|
cmd := m.Command()
|
|
|
|
if cur < len(cmd)-1 {
|
|
m.SetCommand(cmd[:cur+1] + cmd[cur+2:])
|
|
} else if cur == len(cmd)-1 {
|
|
// last text char, delete it
|
|
m.SetCommand(cmd[:cur] + cmd[cur+1:])
|
|
} else if cur == len(cmd) && cur > 0 {
|
|
// if at end, we do backspace op
|
|
m.SetCommand(cmd[:cur-1] + cmd[cur:])
|
|
m.SetCommandCursor(cur - 1)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type CommandDeletePreviousWord struct{}
|
|
|
|
func (a CommandDeletePreviousWord) Execute(m Model) tea.Cmd {
|
|
cur := m.CommandCursor()
|
|
cmd := m.Command()
|
|
|
|
if cur > 0 {
|
|
newCur := cur
|
|
|
|
// If we are on puncuation, we should just skip them all and quit
|
|
if isPunctuation(cmd[newCur-1]) {
|
|
for newCur > 0 && isPunctuation(cmd[newCur-1]) {
|
|
newCur--
|
|
}
|
|
|
|
m.SetCommand(cmd[:newCur] + cmd[cur:])
|
|
m.SetCommandCursor(newCur)
|
|
|
|
return nil
|
|
}
|
|
|
|
// Skip whitespace immediately before the cursor
|
|
for newCur > 0 && (cmd[newCur-1] == ' ' || cmd[newCur-1] == '\t') {
|
|
newCur--
|
|
}
|
|
|
|
// Skip the word characters before the cursor
|
|
for newCur > 0 && isWordChar(cmd[newCur-1]) {
|
|
newCur--
|
|
}
|
|
|
|
// Delete everything from newCur up to cur in one operation
|
|
m.SetCommand(cmd[:newCur] + cmd[cur:])
|
|
m.SetCommandCursor(newCur)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type CommandExecute struct {
|
|
Registry CommandRegistry
|
|
}
|
|
|
|
// CommandRegistry interface for executing commands
|
|
type CommandRegistry interface {
|
|
Execute(m Model, cmdLine string) (tea.Cmd, error)
|
|
}
|
|
|
|
func (a CommandExecute) Execute(m Model) tea.Cmd {
|
|
cmdLine := m.Command()
|
|
|
|
// Clear command state and return to normal mode
|
|
m.SetCommandCursor(0)
|
|
m.SetCommandError(nil)
|
|
m.SetMode(NormalMode)
|
|
|
|
if a.Registry == nil || cmdLine == "" {
|
|
return nil
|
|
}
|
|
|
|
cmd, err := a.Registry.Execute(m, cmdLine)
|
|
if err != nil {
|
|
// TODO: Display error message to user
|
|
m.SetCommandError(err)
|
|
return nil
|
|
}
|
|
|
|
return cmd
|
|
}
|