Gim/internal/action/paste.go
2026-02-21 21:31:31 -07:00

150 lines
2.9 KiB
Go

package action
import (
"fmt"
"strings"
tea "github.com/charmbracelet/bubbletea"
)
// Paste implements Action (p) - pastes after cursor
type Paste struct {
Count int
}
func (a Paste) Execute(m Model) tea.Cmd {
// Get reg
reg, found := m.GetRegister('"')
if !found {
m.SetCommandError(fmt.Errorf("\"\" register is broken. Uh oh."))
return nil
}
// Exit if blank
if len(reg.Content) == 0 {
return nil
}
switch reg.Type {
case LinewiseRegister:
{
initY := m.CursorY()
lines := reg.Content
insertPos := initY + 1
// Run count times
for range a.Count {
for _, line := range lines {
m.InsertLine(insertPos, line)
insertPos++
}
}
if m.LineCount() > 1 {
m.SetCursorY(initY + 1)
}
}
case CharwiseRegister:
{
lines := reg.Content
// Shouldn't happen, just a check
if len(lines) != 1 {
m.SetCommandError(fmt.Errorf("Charwise register should only have a single line of content."))
break
}
x := m.CursorX()
y := m.CursorY()
cnt := strings.Repeat(lines[0], max(1, a.Count))
curLine := m.Line(y)
// Catch edge cases, end of line, start of blank line
insertAt := min(x+1, len(curLine))
newLine := curLine[:insertAt] + cnt + curLine[insertAt:]
m.SetLine(y, newLine)
m.SetCursorX(x + len(cnt))
m.ClampCursorX()
}
default:
m.SetCommandError(fmt.Errorf("Register type is not implemented."))
}
return nil
}
// Ensure Paste implements Repeatable
var _ Repeatable = Paste{}
func (a Paste) WithCount(n int) Action {
return Paste{Count: n}
}
// PasteBefore implements Action (P) - pastes before cursor
type PasteBefore struct {
Count int
}
func (a PasteBefore) Execute(m Model) tea.Cmd {
// Get reg
reg, found := m.GetRegister('"')
if !found {
m.SetCommandError(fmt.Errorf("\"\" register is broken. Uh oh."))
return nil
}
switch reg.Type {
case LinewiseRegister:
{
initY := m.CursorY()
lines := reg.Content
insertPos := initY // Leave here, this will effectively move the lines below
// Run count times
for range a.Count {
for _, line := range lines {
m.InsertLine(insertPos, line)
insertPos++
}
}
}
case CharwiseRegister:
{
lines := reg.Content
// Shouldn't happen, just a check
if len(lines) != 1 {
m.SetCommandError(fmt.Errorf("Charwise register should only have a single line of content."))
break
}
x := m.CursorX()
y := m.CursorY()
cnt := strings.Repeat(lines[0], max(1, a.Count))
curLine := m.Line(y)
// Catch edge cases, end of line, start of blank line
insertAt := min(x, len(curLine))
newLine := curLine[:insertAt] + cnt + curLine[insertAt:]
m.SetLine(y, newLine)
m.SetCursorX(x + len(cnt))
m.ClampCursorX()
}
default:
m.SetCommandError(fmt.Errorf("Register type is not implemented."))
}
return nil
}
// Ensure PasteBefore implements Repeatable
var _ Repeatable = PasteBefore{}
func (a PasteBefore) WithCount(n int) Action {
return PasteBefore{Count: n}
}