The tests are starting to get messy, lots of duplication. Going to resolve that. Lots of this is due to AI generation of tests.
155 lines
3.9 KiB
Go
155 lines
3.9 KiB
Go
package action
|
|
|
|
import (
|
|
"git.gophernest.net/azpect/TextEditor/internal/core"
|
|
tea "github.com/charmbracelet/bubbletea"
|
|
)
|
|
|
|
// ExitCommandMode implements Action - exits command mode and returns to normal mode.
|
|
type ExitCommandMode struct{}
|
|
|
|
// ExitCommandMode.Execute: Exits command mode and returns to normal mode (Esc key).
|
|
func (a ExitCommandMode) Execute(m Model) tea.Cmd {
|
|
m.SetCommandCursor(0)
|
|
m.SetCommandHistoryCursor(0)
|
|
m.SetCommand("")
|
|
m.SetCommandOutput(&core.CommandOutput{})
|
|
m.SetMode(core.NormalMode)
|
|
return nil
|
|
}
|
|
|
|
// InsertCommandChar implements Action - inserts a character in command mode.
|
|
type InsertCommandChar struct {
|
|
Char string
|
|
}
|
|
|
|
// InsertCommandChar.Execute: Inserts a character at the command cursor position.
|
|
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
|
|
}
|
|
|
|
// CommandBackspace implements Action - deletes character before cursor in command mode.
|
|
type CommandBackspace struct{}
|
|
|
|
// CommandBackspace.Execute: Deletes the character before the command cursor (Backspace key).
|
|
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
|
|
}
|
|
|
|
// CommandDelete implements Action - deletes character at cursor in command mode.
|
|
type CommandDelete struct{}
|
|
|
|
// CommandDelete.Execute: Deletes the character at the command cursor (Delete key).
|
|
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
|
|
}
|
|
|
|
// CommandDeletePreviousWord implements Action - deletes word before cursor in command mode.
|
|
type CommandDeletePreviousWord struct{}
|
|
|
|
// CommandDeletePreviousWord.Execute: Deletes the word before the command cursor (Ctrl+W).
|
|
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
|
|
}
|
|
|
|
// CommandExecute implements Action - executes the command line.
|
|
type CommandExecute struct {
|
|
Registry CommandRegistry
|
|
}
|
|
|
|
// CommandRegistry: Interface for executing commands.
|
|
type CommandRegistry interface {
|
|
Execute(m Model, cmdLine string) (tea.Cmd, error)
|
|
}
|
|
|
|
// CommandExecute.Execute: Executes the command line (Enter key).
|
|
func (a CommandExecute) Execute(m Model) tea.Cmd {
|
|
cmdLine := m.Command()
|
|
|
|
// Clear command state and return to normal mode
|
|
m.SetCommandCursor(0)
|
|
m.SetCommandHistoryCursor(0)
|
|
m.SetMode(core.NormalMode)
|
|
|
|
if a.Registry == nil || cmdLine == "" {
|
|
return nil
|
|
}
|
|
|
|
history := append([]string{cmdLine}, m.CommandHistory()...)
|
|
// history = append([]string{cmdLine}, history...)
|
|
m.SetCommandHistory(history)
|
|
|
|
cmd, err := a.Registry.Execute(m, cmdLine)
|
|
if err != nil {
|
|
out := core.CommandOutput{
|
|
Lines: []string{err.Error()},
|
|
Inline: true,
|
|
IsError: true,
|
|
}
|
|
m.SetCommandOutput(&out)
|
|
return nil
|
|
}
|
|
|
|
return cmd
|
|
}
|