Gim/internal/action/replace.go
Hayden Hargreaves 43b3992522
All checks were successful
Run Test Suite / test (push) Successful in 15s
Run Test Suite / test (pull_request) Successful in 15s
feat: implemented replace mode, tested!
Looking great, maybe I will actually use this lol
2026-04-05 23:53:24 -07:00

130 lines
2.6 KiB
Go

package action
import (
"strings"
"git.gophernest.net/azpect/TextEditor/internal/core"
tea "github.com/charmbracelet/bubbletea"
)
type ReplaceChar struct {
Char string
Count int
}
func (m ReplaceChar) WithChar(char string) Motion {
m.Char = char
return m
}
func (m ReplaceChar) Type() core.MotionType {
return core.CharwiseInclusive
}
// WithCount sets the count (required by Repeatable interface)
func (m ReplaceChar) WithCount(n int) Action {
m.Count = n
return m
}
func (a ReplaceChar) Execute(m Model) tea.Cmd {
win := m.ActiveWindow()
buf := m.ActiveBuffer()
if buf.UndoStack != nil && !buf.UndoStack.Recording() {
buf.UndoStack.BeginBlock(win.Cursor)
}
pos := win.Cursor.Col
line := buf.Line(win.Cursor.Line)
for i := 0; i < a.Count && pos < len(line); i++ {
line = line[:pos] + a.Char + line[pos+1:]
buf.SetLine(win.Cursor.Line, line)
pos++
}
win.SetCursorCol(pos - 1)
m.SetMode(core.NormalMode)
if buf.UndoStack != nil {
buf.UndoStack.EndBlock(win.Cursor)
}
return nil
}
type EnterReplace struct {
Count int
}
func (a EnterReplace) WithCount(n int) Action {
a.Count = n
return a
}
func (a EnterReplace) Execute(m Model) tea.Cmd {
m.SetMode(core.ReplaceMode)
return nil
}
type ReplaceModeChar struct {
Char string
}
// ReplaceModeChar.Execute: Inserts a single character at the cursor position, overwriting current
// character.
func (a ReplaceModeChar) Execute(m Model) tea.Cmd {
win := m.ActiveWindow()
buf := m.ActiveBuffer()
x, y := win.Cursor.Col, win.Cursor.Line
l := buf.Line(y)
if x < len(l) {
buf.SetLine(y, l[:x]+a.Char+l[x+1:])
} else {
buf.SetLine(y, l+a.Char)
}
win.SetCursorCol(x + len(a.Char))
return nil
}
// ReplaceNewline splits the current line at the cursor (enter key)
type ReplaceNewline struct{}
// ReplaceNewline.Execute: Splits the current line at the cursor (Enter key).
func (a ReplaceNewline) Execute(m Model) tea.Cmd {
win := m.ActiveWindow()
buf := m.ActiveBuffer()
x, y := win.Cursor.Col, win.Cursor.Line
l := buf.Line(y)
if x == len(l) {
buf.InsertLine(y+1, "")
} else {
buf.SetLine(y, l[:x])
buf.InsertLine(y+1, l[x+1:])
}
win.SetCursorPos(y+1, 0)
return nil
}
// ReplaceTab inserts spaces equal to the tab size
type ReplaceTab struct{}
// ReplaceTab.Execute: Inserts spaces equal to the tab size (Tab key).
func (a ReplaceTab) Execute(m Model) tea.Cmd {
win := m.ActiveWindow()
buf := m.ActiveBuffer()
x, y := win.Cursor.Col, win.Cursor.Line
l := buf.Line(y)
tabs := strings.Repeat(" ", m.Settings().TabStop)
if x < len(l) {
buf.SetLine(y, l[:x]+tabs+l[x+1:])
} else {
buf.SetLine(y, l+tabs)
}
win.SetCursorCol(x + len(tabs))
return nil
}