Compare commits

...

5 Commits

Author SHA1 Message Date
Hayden Hargreaves
ea3ebcdc83 feat: implemented :<n> command, tested
All checks were successful
Run Test Suite / test (push) Successful in 17s
Also added tons of tests for the actual command mode, since that was all
untested...
2026-04-02 14:03:36 -07:00
Hayden Hargreaves
e3b0f30c75 doc: updated FEATURES.md
All checks were successful
Run Test Suite / test (push) Successful in 17s
2026-04-02 13:47:40 -07:00
Hayden Hargreaves
0e2867b948 feat: added better lexer selection handling
All checks were successful
Run Test Suite / test (push) Successful in 18s
2026-04-02 12:55:46 -07:00
Hayden Hargreaves
e362c9f118 feat: gap buffer is implemented, tested
All checks were successful
Run Test Suite / test (push) Successful in 56s
Not sure if this is perfect, but it seems to be working
2026-04-02 12:39:30 -07:00
Hayden Hargreaves
1a98d3a4de fix: p and P differ in V mode, resolved and tested.
P should not replace the register, p should
2026-04-01 18:21:15 -07:00
36 changed files with 2662 additions and 1229 deletions

View File

@ -129,7 +129,7 @@
### Undo/Redo
- [x] `u` - Undo
- [x] `ctrl+r` - Redo
- [ ] `.` - Repeat last change
- [x] `.` - Repeat last change
- [ ] `U` - Undo all changes on line
### Other Normal Mode
@ -219,7 +219,7 @@
- [x] `:q!` - Force quit
- [x] `:e {file}` - Edit file
- [x] `:bn` / `:bp` - Next/previous buffer
- [ ] `:{range}` - Go to line
- [x] `:{range}` - Go to line
- [ ] `:%s/old/new/g` - Search and replace
- [ ] `:!{cmd}` - Run shell command
- [ ] `:help` - Show help
@ -408,63 +408,3 @@ Buffers are in-memory representations of files. A buffer exists for each open fi
- [ ] Spell check
---
### Well Tested - Editor Core
#### Command Execution (179 tests)
- [x] Command parsing and validation
- [x] Command lookup and prefix matching
- [x] Force flag handling (!)
- [x] Write commands (`:w`, `:w {file}`, `:w!`)
- [x] Write all commands (`:wa`, `:wall`, `:wa!`)
- [x] Quit commands (`:q`, `:q!`, `:qa`, `:qa!`)
- [x] Write-quit commands (`:wq`, `:wq!`, `:wqa`, `:wqa!`)
- [x] Edit command (`:e {file}`)
- [x] Register display (`:register`, `:reg {name}`)
- [x] Set commands (`:set number`, `:set tabstop=N`, etc.)
- [x] Setting lookup and validation
- [x] Buffer-level readonly protection
- [x] Scratch buffer write protection
- [x] Force write bypassing readonly/scratch checks
- [x] Multiple buffer write operations
- [x] File write error handling (permissions, paths)
- [x] Modified buffer tracking
- [x] Unicode filename and content handling
- [x] Edge cases (empty args, long filenames, special chars)
#### Program Initialization (70 tests)
- [x] Empty program creation
- [x] File program with nonexistent files (new file buffers)
- [x] File program with existing files (content loading)
- [x] Line ending handling (Unix `\n`, Windows `\r\n`, mixed)
- [x] Tab to space conversion based on TabStop
- [x] Unicode content preservation (CJK, emoji)
- [x] File extension and type detection
- [x] Buffer state initialization (flags, metadata)
- [x] Large file handling (10,000+ lines)
- [x] Long line handling (10,000+ chars)
- [x] Empty file handling
- [x] Builder pattern method chaining
- [x] Program option accumulation
- [x] Model state defaults (settings, registers, mode)
- [x] Error handling (permissions, invalid paths)
- [x] Integration workflows (end-to-end)
- [x] Edge cases (empty filenames, relative paths, dot files)
### Moderately Tested
- [x] Basic motions (h, j, k, l)
- [x] Word motions (w, e, b)
- [x] Jump motions (G, gg, 0, $, _, ^, |)
- [x] Scroll actions (ctrl+u, ctrl+d)
- [x] Delete operator (d, dd)
- [x] Yank operator (y, yy)
- [x] Paste actions (p, P)
- [x] Change operator (c, cc, C)
- [x] Substitute action (s, S)
- [x] Insert mode entry (i, a, I, A, o, O)
- [x] Insert mode editing (enter, backspace, delete, tab, ctrl+w)
- [x] Visual modes (v, V, ctrl+v)
- [x] Visual mode with motions
- [x] Delete actions (x, D)
- [x] Register behavior

View File

@ -16,7 +16,7 @@ func (a ChangeToEndOfLine) Execute(m Model) tea.Cmd {
buf := m.ActiveBuffer()
pos := win.Cursor.Col
line := buf.Lines[win.Cursor.Line]
line := buf.Line(win.Cursor.Line)
// Save deleted text to register
if pos < len(line) {
@ -51,7 +51,7 @@ func (a SubstituteChar) Execute(m Model) tea.Cmd {
buf := m.ActiveBuffer()
pos := win.Cursor.Col
line := buf.Lines[win.Cursor.Line]
line := buf.Line(win.Cursor.Line)
// Calculate how many chars to delete (limited by line length)
count := min(a.Count, len(line)-pos)
@ -97,7 +97,7 @@ func (a SubstituteLine) Execute(m Model) tea.Cmd {
// Collect and delete lines
for range count {
lines = append(lines, buf.Lines[y])
lines = append(lines, buf.Line(y))
buf.DeleteLine(y)
}

View File

@ -1,6 +1,8 @@
package action
import (
"strconv"
"git.gophernest.net/azpect/TextEditor/internal/core"
tea "github.com/charmbracelet/bubbletea"
)
@ -139,6 +141,12 @@ func (a CommandExecute) Execute(m Model) tea.Cmd {
// history = append([]string{cmdLine}, history...)
m.SetCommandHistory(history)
// try to parse entire thing as a number
num, err := strconv.Atoi(cmdLine)
if err == nil {
return cmdGoToLine(m, num)
}
cmd, err := a.Registry.Execute(m, cmdLine)
if err != nil {
out := core.CommandOutput{
@ -152,3 +160,23 @@ func (a CommandExecute) Execute(m Model) tea.Cmd {
return cmd
}
// cmdGoToLine: DOES NOT implement command.Command. Instead, is called directly
// by CommandExecture.Execute(). Jumps the cursor to the line provided
func cmdGoToLine(m Model, line int) tea.Cmd {
// number below 0 just goes back that many
win := m.ActiveWindow()
buf := m.ActiveBuffer()
if line <= 0 {
newLine := max(0, win.Cursor.Line+line)
win.SetCursorLine(newLine)
return nil
}
newLine := min(line-1, buf.LineCount())
win.SetCursorLine(newLine)
return nil
}

View File

@ -0,0 +1,725 @@
package action
import (
"testing"
"git.gophernest.net/azpect/TextEditor/internal/core"
tea "github.com/charmbracelet/bubbletea"
)
// mockCommandRegistry for testing - returns nil for all commands (used for numeric goto)
type mockCommandRegistry struct{}
func (r *mockCommandRegistry) Execute(m Model, cmdLine string) (tea.Cmd, error) {
return nil, nil
}
// TestCommandExecute_GoToLine tests the :<num> command functionality
func TestCommandExecute_GoToLine(t *testing.T) {
t.Run("goto positive line number within bounds", func(t *testing.T) {
// Create buffer with 10 lines
buf := core.NewBufferBuilder().
WithLines([]string{"line1", "line2", "line3", "line4", "line5", "line6", "line7", "line8", "line9", "line10"}).
Build()
m := NewMockModelWithBuffer(&buf)
win := m.ActiveWindow()
win.SetCursorLine(0)
// Set command to "5"
m.SetCommand("5")
m.SetMode(core.CommandMode)
action := CommandExecute{Registry: &mockCommandRegistry{}}
action.Execute(m)
// Should jump to line 5 (0-indexed: line 4)
if win.Cursor.Line != 4 {
t.Fatalf("expected cursor at line 4, got %d", win.Cursor.Line)
}
// Should exit command mode
if m.Mode() != core.NormalMode {
t.Fatalf("expected normal mode, got %v", m.Mode())
}
})
t.Run("goto line 1", func(t *testing.T) {
buf := core.NewBufferBuilder().
WithLines([]string{"line1", "line2", "line3", "line4", "line5"}).
Build()
m := NewMockModelWithBuffer(&buf)
win := m.ActiveWindow()
win.SetCursorLine(3) // Start at line 4
m.SetCommand("1")
m.SetMode(core.CommandMode)
action := CommandExecute{Registry: &mockCommandRegistry{}}
action.Execute(m)
// Should jump to line 1 (0-indexed: line 0)
if win.Cursor.Line != 0 {
t.Fatalf("expected cursor at line 0, got %d", win.Cursor.Line)
}
})
t.Run("goto last line", func(t *testing.T) {
buf := core.NewBufferBuilder().
WithLines([]string{"line1", "line2", "line3", "line4", "line5"}).
Build()
m := NewMockModelWithBuffer(&buf)
win := m.ActiveWindow()
win.SetCursorLine(0)
m.SetCommand("5")
m.SetMode(core.CommandMode)
action := CommandExecute{Registry: &mockCommandRegistry{}}
action.Execute(m)
// Should jump to line 5 (0-indexed: line 4)
if win.Cursor.Line != 4 {
t.Fatalf("expected cursor at line 4, got %d", win.Cursor.Line)
}
})
t.Run("goto line beyond buffer length clamps to last line", func(t *testing.T) {
buf := core.NewBufferBuilder().
WithLines([]string{"line1", "line2", "line3"}).
Build()
m := NewMockModelWithBuffer(&buf)
win := m.ActiveWindow()
win.SetCursorLine(0)
m.SetCommand("999")
m.SetMode(core.CommandMode)
action := CommandExecute{Registry: &mockCommandRegistry{}}
action.Execute(m)
// Should clamp to last line (0-indexed: line 2)
// Note: cmdGoToLine uses min(line-1, buf.LineCount())
// LineCount() returns 3, so min(998, 3) = 3
// But SetCursorLine calls ClampCursor() which clamps to valid range [0, LineCount-1]
lastLine := buf.LineCount() - 1
if win.Cursor.Line != lastLine {
t.Fatalf("expected cursor at line %d (last line), got %d", lastLine, win.Cursor.Line)
}
})
t.Run("goto line zero goes to beginning", func(t *testing.T) {
buf := core.NewBufferBuilder().
WithLines([]string{"line1", "line2", "line3", "line4", "line5"}).
Build()
m := NewMockModelWithBuffer(&buf)
win := m.ActiveWindow()
win.SetCursorLine(3)
m.SetCommand("0")
m.SetMode(core.CommandMode)
action := CommandExecute{Registry: &mockCommandRegistry{}}
action.Execute(m)
// Line 0 or below goes relative: max(0, currentLine + 0) = currentLine
// But with the logic: if line <= 0, newLine = max(0, win.Cursor.Line + line)
// So for line=0: max(0, 3+0) = 3 (stays at same line)
if win.Cursor.Line != 3 {
t.Fatalf("expected cursor at line 3, got %d", win.Cursor.Line)
}
})
t.Run("negative number moves relative backwards", func(t *testing.T) {
buf := core.NewBufferBuilder().
WithLines([]string{"line1", "line2", "line3", "line4", "line5", "line6", "line7", "line8", "line9", "line10"}).
Build()
m := NewMockModelWithBuffer(&buf)
win := m.ActiveWindow()
win.SetCursorLine(5) // Start at line 6 (0-indexed)
m.SetCommand("-3")
m.SetMode(core.CommandMode)
action := CommandExecute{Registry: &mockCommandRegistry{}}
action.Execute(m)
// Should move back 3 lines: 5 + (-3) = 2
if win.Cursor.Line != 2 {
t.Fatalf("expected cursor at line 2, got %d", win.Cursor.Line)
}
})
t.Run("negative number beyond start clamps to line 0", func(t *testing.T) {
buf := core.NewBufferBuilder().
WithLines([]string{"line1", "line2", "line3", "line4", "line5"}).
Build()
m := NewMockModelWithBuffer(&buf)
win := m.ActiveWindow()
win.SetCursorLine(2)
m.SetCommand("-10")
m.SetMode(core.CommandMode)
action := CommandExecute{Registry: &mockCommandRegistry{}}
action.Execute(m)
// Should clamp to line 0: max(0, 2 + (-10)) = max(0, -8) = 0
if win.Cursor.Line != 0 {
t.Fatalf("expected cursor at line 0, got %d", win.Cursor.Line)
}
})
t.Run("goto same line", func(t *testing.T) {
buf := core.NewBufferBuilder().
WithLines([]string{"line1", "line2", "line3", "line4", "line5"}).
Build()
m := NewMockModelWithBuffer(&buf)
win := m.ActiveWindow()
win.SetCursorLine(2) // At line 3
m.SetCommand("3")
m.SetMode(core.CommandMode)
action := CommandExecute{Registry: &mockCommandRegistry{}}
action.Execute(m)
// Should stay at line 3 (0-indexed: line 2)
if win.Cursor.Line != 2 {
t.Fatalf("expected cursor at line 2, got %d", win.Cursor.Line)
}
})
t.Run("empty buffer", func(t *testing.T) {
buf := core.NewBufferBuilder().
WithLines([]string{""}).
Build()
m := NewMockModelWithBuffer(&buf)
win := m.ActiveWindow()
m.SetCommand("1")
m.SetMode(core.CommandMode)
action := CommandExecute{Registry: &mockCommandRegistry{}}
action.Execute(m)
// Should stay at line 0
if win.Cursor.Line != 0 {
t.Fatalf("expected cursor at line 0, got %d", win.Cursor.Line)
}
})
t.Run("single line buffer goto line 1", func(t *testing.T) {
buf := core.NewBufferBuilder().
WithLines([]string{"only line"}).
Build()
m := NewMockModelWithBuffer(&buf)
win := m.ActiveWindow()
m.SetCommand("1")
m.SetMode(core.CommandMode)
action := CommandExecute{Registry: &mockCommandRegistry{}}
action.Execute(m)
if win.Cursor.Line != 0 {
t.Fatalf("expected cursor at line 0, got %d", win.Cursor.Line)
}
})
t.Run("single line buffer goto beyond", func(t *testing.T) {
buf := core.NewBufferBuilder().
WithLines([]string{"only line"}).
Build()
m := NewMockModelWithBuffer(&buf)
win := m.ActiveWindow()
m.SetCommand("10")
m.SetMode(core.CommandMode)
action := CommandExecute{Registry: &mockCommandRegistry{}}
action.Execute(m)
// Should clamp to the available lines
if win.Cursor.Line > 0 {
t.Fatalf("expected cursor at line 0 or 1, got %d", win.Cursor.Line)
}
})
t.Run("large line number", func(t *testing.T) {
buf := core.NewBufferBuilder().
WithLines([]string{"line1", "line2", "line3"}).
Build()
m := NewMockModelWithBuffer(&buf)
win := m.ActiveWindow()
m.SetCommand("1000000")
m.SetMode(core.CommandMode)
action := CommandExecute{Registry: &mockCommandRegistry{}}
action.Execute(m)
// Should clamp to last available line
lineCount := buf.LineCount()
if win.Cursor.Line > lineCount {
t.Fatalf("expected cursor at or before line %d, got %d", lineCount, win.Cursor.Line)
}
})
t.Run("command with leading/trailing spaces", func(t *testing.T) {
buf := core.NewBufferBuilder().
WithLines([]string{"line1", "line2", "line3", "line4", "line5"}).
Build()
m := NewMockModelWithBuffer(&buf)
win := m.ActiveWindow()
win.SetCursorLine(0)
// strconv.Atoi should handle leading spaces
m.SetCommand(" 3 ")
m.SetMode(core.CommandMode)
action := CommandExecute{Registry: &mockCommandRegistry{}}
action.Execute(m)
// strconv.Atoi(" 3 ") will fail, so this won't be treated as a line number
// It should stay at the same position and potentially show an error
// depending on the CommandRegistry behavior
})
t.Run("mixed alphanumeric command not treated as line number", func(t *testing.T) {
buf := core.NewBufferBuilder().
WithLines([]string{"line1", "line2", "line3"}).
Build()
m := NewMockModelWithBuffer(&buf)
win := m.ActiveWindow()
initialLine := 1
win.SetCursorLine(initialLine)
m.SetCommand("3abc")
m.SetMode(core.CommandMode)
action := CommandExecute{Registry: &mockCommandRegistry{}}
action.Execute(m)
// "3abc" is not a valid number, so won't trigger goto line
// Cursor should stay at original position
if win.Cursor.Line != initialLine {
t.Fatalf("expected cursor at line %d, got %d", initialLine, win.Cursor.Line)
}
})
}
// TestCommandExecute_EmptyCommand tests empty command behavior
func TestCommandExecute_EmptyCommand(t *testing.T) {
t.Run("empty command does nothing", func(t *testing.T) {
m := NewMockModel()
win := m.ActiveWindow()
initialLine := 0
win.SetCursorLine(initialLine)
m.SetCommand("")
m.SetMode(core.CommandMode)
action := CommandExecute{Registry: &mockCommandRegistry{}}
action.Execute(m)
// Should exit command mode
if m.Mode() != core.NormalMode {
t.Fatalf("expected normal mode, got %v", m.Mode())
}
// Cursor should not move
if win.Cursor.Line != initialLine {
t.Fatalf("expected cursor at line %d, got %d", initialLine, win.Cursor.Line)
}
})
}
// TestCommandExecute_CommandHistory tests that commands are added to history
func TestCommandExecute_CommandHistory(t *testing.T) {
t.Run("numeric command added to history", func(t *testing.T) {
buf := core.NewBufferBuilder().
WithLines([]string{"line1", "line2", "line3", "line4", "line5"}).
Build()
m := NewMockModelWithBuffer(&buf)
m.SetCommand("3")
m.SetMode(core.CommandMode)
m.SetCommandHistory([]string{})
action := CommandExecute{Registry: &mockCommandRegistry{}}
action.Execute(m)
history := m.CommandHistory()
if len(history) != 1 {
t.Fatalf("expected 1 item in history, got %d", len(history))
}
if history[0] != "3" {
t.Fatalf("expected '3' in history, got '%s'", history[0])
}
})
t.Run("commands prepended to existing history", func(t *testing.T) {
m := NewMockModel()
m.SetCommandHistory([]string{"oldcommand1", "oldcommand2"})
m.SetCommand("5")
m.SetMode(core.CommandMode)
action := CommandExecute{Registry: &mockCommandRegistry{}}
action.Execute(m)
history := m.CommandHistory()
if len(history) != 3 {
t.Fatalf("expected 3 items in history, got %d", len(history))
}
if history[0] != "5" {
t.Fatalf("expected '5' as first item, got '%s'", history[0])
}
if history[1] != "oldcommand1" {
t.Fatalf("expected 'oldcommand1' as second item, got '%s'", history[1])
}
})
}
// TestCommandExecute_ModeTransition tests command mode exit behavior
func TestCommandExecute_ModeTransition(t *testing.T) {
t.Run("exits command mode after execution", func(t *testing.T) {
m := NewMockModel()
m.SetMode(core.CommandMode)
m.SetCommand("5")
action := CommandExecute{Registry: &mockCommandRegistry{}}
action.Execute(m)
if m.Mode() != core.NormalMode {
t.Fatalf("expected normal mode, got %v", m.Mode())
}
})
t.Run("resets command cursor to 0", func(t *testing.T) {
m := NewMockModel()
m.SetCommandCursor(10)
m.SetCommand("5")
action := CommandExecute{Registry: &mockCommandRegistry{}}
action.Execute(m)
if m.CommandCursor() != 0 {
t.Fatalf("expected command cursor at 0, got %d", m.CommandCursor())
}
})
t.Run("resets command history cursor to 0", func(t *testing.T) {
m := NewMockModel()
m.SetCommandHistoryCursor(5)
m.SetCommand("5")
action := CommandExecute{Registry: &mockCommandRegistry{}}
action.Execute(m)
if m.CommandHistoryCursor() != 0 {
t.Fatalf("expected command history cursor at 0, got %d", m.CommandHistoryCursor())
}
})
}
// TestExitCommandMode tests the Esc key behavior
func TestExitCommandMode(t *testing.T) {
t.Run("exit command mode clears state", func(t *testing.T) {
m := NewMockModel()
m.SetMode(core.CommandMode)
m.SetCommand("test command")
m.SetCommandCursor(5)
m.SetCommandHistoryCursor(3)
action := ExitCommandMode{}
action.Execute(m)
if m.Mode() != core.NormalMode {
t.Fatalf("expected normal mode, got %v", m.Mode())
}
if m.Command() != "" {
t.Fatalf("expected empty command, got '%s'", m.Command())
}
if m.CommandCursor() != 0 {
t.Fatalf("expected command cursor at 0, got %d", m.CommandCursor())
}
if m.CommandHistoryCursor() != 0 {
t.Fatalf("expected command history cursor at 0, got %d", m.CommandHistoryCursor())
}
})
}
// TestInsertCommandChar tests character insertion in command mode
func TestInsertCommandChar(t *testing.T) {
t.Run("insert character at empty command", func(t *testing.T) {
m := NewMockModel()
m.SetCommand("")
m.SetCommandCursor(0)
action := InsertCommandChar{Char: "5"}
action.Execute(m)
if m.Command() != "5" {
t.Fatalf("expected '5', got '%s'", m.Command())
}
if m.CommandCursor() != 1 {
t.Fatalf("expected cursor at 1, got %d", m.CommandCursor())
}
})
t.Run("insert character at end", func(t *testing.T) {
m := NewMockModel()
m.SetCommand("12")
m.SetCommandCursor(2)
action := InsertCommandChar{Char: "3"}
action.Execute(m)
if m.Command() != "123" {
t.Fatalf("expected '123', got '%s'", m.Command())
}
if m.CommandCursor() != 3 {
t.Fatalf("expected cursor at 3, got %d", m.CommandCursor())
}
})
t.Run("insert character in middle", func(t *testing.T) {
m := NewMockModel()
m.SetCommand("13")
m.SetCommandCursor(1)
action := InsertCommandChar{Char: "2"}
action.Execute(m)
if m.Command() != "123" {
t.Fatalf("expected '123', got '%s'", m.Command())
}
if m.CommandCursor() != 2 {
t.Fatalf("expected cursor at 2, got %d", m.CommandCursor())
}
})
}
// TestCommandBackspace tests backspace in command mode
func TestCommandBackspace(t *testing.T) {
t.Run("backspace at beginning does nothing", func(t *testing.T) {
m := NewMockModel()
m.SetCommand("123")
m.SetCommandCursor(0)
action := CommandBackspace{}
action.Execute(m)
if m.Command() != "123" {
t.Fatalf("expected '123', got '%s'", m.Command())
}
if m.CommandCursor() != 0 {
t.Fatalf("expected cursor at 0, got %d", m.CommandCursor())
}
})
t.Run("backspace in middle", func(t *testing.T) {
m := NewMockModel()
m.SetCommand("123")
m.SetCommandCursor(2)
action := CommandBackspace{}
action.Execute(m)
if m.Command() != "13" {
t.Fatalf("expected '13', got '%s'", m.Command())
}
if m.CommandCursor() != 1 {
t.Fatalf("expected cursor at 1, got %d", m.CommandCursor())
}
})
t.Run("backspace at end", func(t *testing.T) {
m := NewMockModel()
m.SetCommand("123")
m.SetCommandCursor(3)
action := CommandBackspace{}
action.Execute(m)
if m.Command() != "12" {
t.Fatalf("expected '12', got '%s'", m.Command())
}
if m.CommandCursor() != 2 {
t.Fatalf("expected cursor at 2, got %d", m.CommandCursor())
}
})
}
// TestCommandDelete tests delete key in command mode
func TestCommandDelete(t *testing.T) {
t.Run("delete at cursor position 0 deletes character after cursor", func(t *testing.T) {
m := NewMockModel()
m.SetCommand("123")
m.SetCommandCursor(0)
action := CommandDelete{}
action.Execute(m)
// At position 0, delete removes char at position 1 (the next char)
// Result: "1" + "3" = "13"
if m.Command() != "13" {
t.Fatalf("expected '13', got '%s'", m.Command())
}
})
t.Run("delete at cursor position 1", func(t *testing.T) {
m := NewMockModel()
m.SetCommand("123")
m.SetCommandCursor(1)
action := CommandDelete{}
action.Execute(m)
// At position 1, delete removes char at position 2 (the next char)
// Result: "12" + "" = "12"
if m.Command() != "12" {
t.Fatalf("expected '12', got '%s'", m.Command())
}
})
t.Run("delete at last character", func(t *testing.T) {
m := NewMockModel()
m.SetCommand("123")
m.SetCommandCursor(2)
action := CommandDelete{}
action.Execute(m)
if m.Command() != "12" {
t.Fatalf("expected '12', got '%s'", m.Command())
}
})
t.Run("delete at end acts as backspace", func(t *testing.T) {
m := NewMockModel()
m.SetCommand("123")
m.SetCommandCursor(3)
action := CommandDelete{}
action.Execute(m)
if m.Command() != "12" {
t.Fatalf("expected '12', got '%s'", m.Command())
}
if m.CommandCursor() != 2 {
t.Fatalf("expected cursor at 2, got %d", m.CommandCursor())
}
})
}
// TestCommandDeletePreviousWord tests Ctrl+W behavior in command mode
func TestCommandDeletePreviousWord(t *testing.T) {
t.Run("delete word from middle of text", func(t *testing.T) {
m := NewMockModel()
m.SetCommand("hello world")
m.SetCommandCursor(11) // At end
action := CommandDeletePreviousWord{}
action.Execute(m)
if m.Command() != "hello " {
t.Fatalf("expected 'hello ', got '%s'", m.Command())
}
if m.CommandCursor() != 6 {
t.Fatalf("expected cursor at 6, got %d", m.CommandCursor())
}
})
t.Run("delete word with leading spaces", func(t *testing.T) {
m := NewMockModel()
m.SetCommand("hello world")
m.SetCommandCursor(13) // At end
action := CommandDeletePreviousWord{}
action.Execute(m)
if m.Command() != "hello " {
t.Fatalf("expected 'hello ', got '%s'", m.Command())
}
})
t.Run("delete at beginning does nothing", func(t *testing.T) {
m := NewMockModel()
m.SetCommand("hello")
m.SetCommandCursor(0)
action := CommandDeletePreviousWord{}
action.Execute(m)
if m.Command() != "hello" {
t.Fatalf("expected 'hello', got '%s'", m.Command())
}
if m.CommandCursor() != 0 {
t.Fatalf("expected cursor at 0, got %d", m.CommandCursor())
}
})
t.Run("delete punctuation", func(t *testing.T) {
m := NewMockModel()
m.SetCommand("hello...")
m.SetCommandCursor(8) // After the dots
action := CommandDeletePreviousWord{}
action.Execute(m)
if m.Command() != "hello" {
t.Fatalf("expected 'hello', got '%s'", m.Command())
}
if m.CommandCursor() != 5 {
t.Fatalf("expected cursor at 5, got %d", m.CommandCursor())
}
})
t.Run("delete word in middle of command", func(t *testing.T) {
m := NewMockModel()
m.SetCommand("one two three")
m.SetCommandCursor(7) // After "two"
action := CommandDeletePreviousWord{}
action.Execute(m)
if m.Command() != "one three" {
t.Fatalf("expected 'one three', got '%s'", m.Command())
}
if m.CommandCursor() != 4 {
t.Fatalf("expected cursor at 4, got %d", m.CommandCursor())
}
})
t.Run("delete single character word", func(t *testing.T) {
m := NewMockModel()
m.SetCommand("a b c")
m.SetCommandCursor(3) // After "b"
action := CommandDeletePreviousWord{}
action.Execute(m)
if m.Command() != "a c" {
t.Fatalf("expected 'a c', got '%s'", m.Command())
}
})
t.Run("delete from whitespace position", func(t *testing.T) {
m := NewMockModel()
m.SetCommand("hello world")
m.SetCommandCursor(6) // At the space after "hello"
action := CommandDeletePreviousWord{}
action.Execute(m)
// Should skip the space and delete "hello" and the space
if m.Command() != "world" {
t.Fatalf("expected 'world', got '%s'", m.Command())
}
if m.CommandCursor() != 0 {
t.Fatalf("expected cursor at 0, got %d", m.CommandCursor())
}
})
}

View File

@ -13,7 +13,7 @@ func (a DeleteChar) Execute(m Model) tea.Cmd {
buf := m.ActiveBuffer()
pos := win.Cursor.Col
line := buf.Lines[win.Cursor.Line]
line := buf.Line(win.Cursor.Line)
for i := 0; i < a.Count && pos < len(line); i++ {
line = line[:pos] + line[pos+1:]
buf.SetLine(win.Cursor.Line, line)
@ -38,7 +38,7 @@ func (a DeletePrevChar) Execute(m Model) tea.Cmd {
buf := m.ActiveBuffer()
pos := win.Cursor.Col
line := buf.Lines[win.Cursor.Line]
line := buf.Line(win.Cursor.Line)
for i := 0; i < a.Count && pos <= len(line); i++ {
if pos > 0 {
line = line[:pos-1] + line[pos:]
@ -69,7 +69,7 @@ func (a DeleteToEndOfLine) Execute(m Model) tea.Cmd {
// Delete to end of line
pos := win.Cursor.Col
line := buf.Lines[win.Cursor.Line]
line := buf.Line(win.Cursor.Line)
buf.SetLine(win.Cursor.Line, line[:pos])
win.SetCursorCol(pos - 1)

View File

@ -76,7 +76,7 @@ type EnterInsertLineEnd struct {
func (a EnterInsertLineEnd) Execute(m Model) tea.Cmd {
win := m.ActiveWindow()
buf := m.ActiveBuffer()
win.SetCursorCol(len(buf.Lines[win.Cursor.Line]))
win.SetCursorCol(buf.Lines[win.Cursor.Line].Len())
// Start recording
m.SetInsertRecording(a.Count, a)
@ -158,7 +158,7 @@ func (a InsertChar) Execute(m Model) tea.Cmd {
buf := m.ActiveBuffer()
x, y := win.Cursor.Col, win.Cursor.Line
l := buf.Lines[y]
l := buf.Line(y)
if x < len(l) {
buf.SetLine(y, l[:x]+a.Char+l[x:])
} else {
@ -177,7 +177,7 @@ func (a InsertNewline) Execute(m Model) tea.Cmd {
buf := m.ActiveBuffer()
x, y := win.Cursor.Col, win.Cursor.Line
l := buf.Lines[y]
l := buf.Line(y)
if x == len(l) {
buf.InsertLine(y+1, "")
} else {
@ -197,12 +197,12 @@ func (a InsertBackspace) Execute(m Model) tea.Cmd {
buf := m.ActiveBuffer()
x, y := win.Cursor.Col, win.Cursor.Line
l := buf.Lines[y]
l := buf.Line(y)
if x > 0 {
buf.SetLine(y, l[:x-1]+l[x:])
win.SetCursorCol(x - 1)
} else if y > 0 {
prevLine := buf.Lines[y-1]
prevLine := buf.Line(y - 1)
newX := len(prevLine)
buf.SetLine(y-1, prevLine+l)
buf.DeleteLine(y)
@ -220,9 +220,9 @@ func (a InsertDelete) Execute(m Model) tea.Cmd {
buf := m.ActiveBuffer()
x, y := win.Cursor.Col, win.Cursor.Line
l := buf.Lines[y]
l := buf.Line(y)
if x == len(l) && y < buf.LineCount()-1 {
nextLine := buf.Lines[y+1]
nextLine := buf.Line(y + 1)
buf.SetLine(y, l+nextLine)
buf.DeleteLine(y + 1)
} else if x < len(l) {
@ -240,7 +240,7 @@ func (a InsertTab) Execute(m Model) tea.Cmd {
buf := m.ActiveBuffer()
x, y := win.Cursor.Col, win.Cursor.Line
l := buf.Lines[y]
l := buf.Line(y)
tabs := strings.Repeat(" ", m.Settings().TabStop)
if x < len(l) {
buf.SetLine(y, l[:x]+tabs+l[x:])
@ -275,12 +275,12 @@ func (a InsertDeletePreviousWord) Execute(m Model) tea.Cmd {
buf := m.ActiveBuffer()
x, y := win.Cursor.Col, win.Cursor.Line
line := buf.Lines[y]
line := buf.Line(y)
// At start of line: merge with previous line (same as backspace)
if x == 0 {
if y > 0 {
prevLine := buf.Lines[y-1]
prevLine := buf.Line(y - 1)
newX := len(prevLine)
buf.SetLine(y-1, prevLine+line)
buf.DeleteLine(y)

View File

@ -63,7 +63,7 @@ func (a Paste) Execute(m Model) tea.Cmd {
x := win.Cursor.Col
y := win.Cursor.Line
curLine := buf.Lines[y]
curLine := buf.Line(y)
insertAt := min(x+1, len(curLine))
if len(lines) == 1 {
@ -101,11 +101,11 @@ func (a Paste) Execute(m Model) tea.Cmd {
// Last line: append the suffix
lastLineIdx := y + len(pastedLines) - 1
buf.SetLine(lastLineIdx, buf.Lines[lastLineIdx]+suffix)
buf.SetLine(lastLineIdx, buf.Line(lastLineIdx)+suffix)
// Set cursor to end of last pasted content (before suffix)
win.SetCursorLine(lastLineIdx)
win.SetCursorCol(len(buf.Lines[lastLineIdx]) - len(suffix) - 1)
win.SetCursorCol(len(buf.Line(lastLineIdx)) - len(suffix) - 1)
}
}
default:
@ -175,7 +175,7 @@ func (a PasteBefore) Execute(m Model) tea.Cmd {
x := win.Cursor.Col
y := win.Cursor.Line
curLine := buf.Lines[y]
curLine := buf.Line(y)
insertAt := min(x, len(curLine))
if len(lines) == 1 {
@ -213,11 +213,11 @@ func (a PasteBefore) Execute(m Model) tea.Cmd {
// Last line: append the suffix
lastLineIdx := y + len(pastedLines) - 1
buf.SetLine(lastLineIdx, buf.Lines[lastLineIdx]+suffix)
buf.SetLine(lastLineIdx, buf.Line(lastLineIdx)+suffix)
// Set cursor to end of last pasted content (before suffix)
win.SetCursorLine(lastLineIdx)
win.SetCursorCol(len(buf.Lines[lastLineIdx]) - len(suffix) - 1)
win.SetCursorCol(len(buf.Line(lastLineIdx)) - len(suffix) - 1)
}
}
default:
@ -240,9 +240,11 @@ func (a PasteBefore) WithCount(n int) Action {
return PasteBefore{Count: n}
}
// VisualPaste implements Action (p in visual mode) - replaces selection with register content
// VisualPaste implements Action (p/p in visual mode) - replaces selection with
// register content when Replace flag is set
type VisualPaste struct {
Count int
Replace bool
}
// VisualPaste.Execute: Replaces visual selection with register content (p in visual mode).
@ -266,11 +268,11 @@ func (a VisualPaste) Execute(m Model) tea.Cmd {
switch mode {
case core.VisualMode:
visualCharPaste(m, reg, start, end)
visualCharPaste(m, reg, start, end, a.Replace)
case core.VisualBlockMode:
visualBlockPaste(m, reg, start, end)
visualBlockPaste(m, reg, start, end, a.Replace)
case core.VisualLineMode:
visualLinePaste(m, reg, start, end)
visualLinePaste(m, reg, start, end, a.Replace)
}
// Exit visual mode
@ -295,7 +297,7 @@ func normalizeSelection(m Model) (core.Position, core.Position) {
}
// visualCharPaste: Handles paste operation in visual (character) mode.
func visualCharPaste(m Model, reg core.Register, start, end core.Position) {
func visualCharPaste(m Model, reg core.Register, start, end core.Position, replace bool) {
win := m.ActiveWindow()
buf := m.ActiveBuffer()
@ -311,7 +313,7 @@ func visualCharPaste(m Model, reg core.Register, start, end core.Position) {
} else if reg.Type == core.CharwiseRegister {
// Charwise paste: insert text at cursor position
if len(reg.Content) == 1 {
line := buf.Lines[start.Line]
line := buf.Line(start.Line)
insertAt := min(start.Col, len(line))
newLine := line[:insertAt] + reg.Content[0] + line[insertAt:]
buf.SetLine(start.Line, newLine)
@ -326,7 +328,7 @@ func visualCharPaste(m Model, reg core.Register, start, end core.Position) {
for i, content := range reg.Content {
if i == 0 {
// First line: insert at start position
line := buf.Lines[start.Line]
line := buf.Line(start.Line)
insertAt := min(start.Col, len(line))
newLine := line[:insertAt] + content
if len(reg.Content) == 1 {
@ -344,11 +346,13 @@ func visualCharPaste(m Model, reg core.Register, start, end core.Position) {
}
// Update register with deleted text
if replace {
m.UpdateDefaultRegister(core.CharwiseRegister, []string{deletedText})
}
}
// visualBlockPaste: Handles paste operation in visual block mode.
func visualBlockPaste(m Model, reg core.Register, start, end core.Position) {
func visualBlockPaste(m Model, reg core.Register, start, end core.Position, replace bool) {
win := m.ActiveWindow()
buf := m.ActiveBuffer()
@ -358,7 +362,7 @@ func visualBlockPaste(m Model, reg core.Register, start, end core.Position) {
// Extract deleted text (for register)
var deletedLines []string
for y := start.Line; y <= end.Line; y++ {
line := buf.Lines[y]
line := buf.Line(y)
if startCol < len(line) {
ec := min(endCol+1, len(line))
deletedLines = append(deletedLines, line[startCol:ec])
@ -369,7 +373,7 @@ func visualBlockPaste(m Model, reg core.Register, start, end core.Position) {
// Delete the block selection
for y := start.Line; y <= end.Line; y++ {
line := buf.Lines[y]
line := buf.Line(y)
if startCol >= len(line) {
continue
}
@ -385,7 +389,7 @@ func visualBlockPaste(m Model, reg core.Register, start, end core.Position) {
}
for y := start.Line; y <= end.Line; y++ {
line := buf.Lines[y]
line := buf.Line(y)
insertAt := min(startCol, len(line))
// Pad with spaces if needed
for len(line) < insertAt {
@ -400,18 +404,20 @@ func visualBlockPaste(m Model, reg core.Register, start, end core.Position) {
win.SetCursorCol(startCol)
// Update register with deleted block text (joined)
if replace {
m.UpdateDefaultRegister(core.CharwiseRegister, []string{strings.Join(deletedLines, "\n")})
}
}
// visualLinePaste: Handles paste operation in visual line mode.
func visualLinePaste(m Model, reg core.Register, start, end core.Position) {
func visualLinePaste(m Model, reg core.Register, start, end core.Position, replace bool) {
win := m.ActiveWindow()
buf := m.ActiveBuffer()
// Extract deleted lines (for register)
var deletedLines []string
for y := start.Line; y <= end.Line; y++ {
deletedLines = append(deletedLines, buf.Lines[y])
deletedLines = append(deletedLines, buf.Line(y))
}
// Delete the selected lines (from end to start to preserve indices)
@ -451,15 +457,17 @@ func visualLinePaste(m Model, reg core.Register, start, end core.Position) {
win.SetCursorCol(0)
// Update register with deleted lines
if replace {
m.UpdateDefaultRegister(core.LinewiseRegister, deletedLines)
}
}
// extractCharSelection: Extracts text from a character selection range.
func extractCharSelection(m Model, start, end core.Position) string {
buf := m.ActiveBuffer()
if start.Line == end.Line {
line := buf.Lines[start.Line]
line := buf.Line(start.Line)
endCol := min(end.Col+1, len(line))
startCol := min(start.Col, len(line))
if startCol >= endCol {
@ -472,7 +480,7 @@ func extractCharSelection(m Model, start, end core.Position) string {
var result strings.Builder
// First line: from start.Col to end
firstLine := buf.Lines[start.Line]
firstLine := buf.Line(start.Line)
if start.Col < len(firstLine) {
result.WriteString(firstLine[start.Col:])
}
@ -480,12 +488,12 @@ func extractCharSelection(m Model, start, end core.Position) string {
// Middle lines: entire lines
for y := start.Line + 1; y < end.Line; y++ {
result.WriteString(buf.Lines[y])
result.WriteString(buf.Line(y))
result.WriteString("\n")
}
// Last line: from beginning to end.Col
lastLine := buf.Lines[end.Line]
lastLine := buf.Line(end.Line)
endCol := min(end.Col+1, len(lastLine))
result.WriteString(lastLine[:endCol])
@ -498,12 +506,12 @@ func deleteCharSelectionForPaste(m Model, start, end core.Position) {
buf := m.ActiveBuffer()
if start.Line == end.Line {
line := buf.Lines[start.Line]
line := buf.Line(start.Line)
endCol := min(end.Col+1, len(line))
buf.SetLine(start.Line, line[:start.Col]+line[endCol:])
} else {
startLine := buf.Lines[start.Line]
endLine := buf.Lines[end.Line]
startLine := buf.Line(start.Line)
endLine := buf.Line(end.Line)
prefix := ""
if start.Col < len(startLine) {
@ -531,5 +539,5 @@ var _ Repeatable = VisualPaste{}
// VisualPaste.WithCount: Returns a new VisualPaste with the given count.
func (a VisualPaste) WithCount(n int) Action {
return VisualPaste{Count: n}
return VisualPaste{Count: n, Replace: a.Replace}
}

View File

@ -63,7 +63,7 @@ func writeBuffer(m action.Model, buf *core.Buffer, args []string, force bool) (t
// Using a bufio.Writer because its more efficient
writer := bufio.NewWriter(file)
for _, line := range buf.Lines {
n, err := writer.WriteString(line + "\n")
n, err := writer.WriteString(line.String() + "\n")
if err != nil {
return nil, err
}

View File

@ -20,7 +20,7 @@ type Buffer struct {
// File data
Filename string
Filetype string
Lines []string
Lines []*GapBuffer // Changed from []string to []*GapBuffer
// Flags (not used yet)
Modified bool
@ -42,7 +42,7 @@ func (b *Buffer) Line(idx int) string {
if idx < 0 || idx >= len(b.Lines) {
return ""
}
return b.Lines[idx]
return b.Lines[idx].String()
}
// Buffer.SetLine: Set the content of the line at an index. Does nothing if the
@ -51,9 +51,9 @@ func (b *Buffer) SetLine(idx int, content string) {
if idx >= 0 && idx < len(b.Lines) {
// Record set line in undo stack
if b.UndoStack != nil {
b.UndoStack.RecordSetLine(idx, b.Lines[idx], content)
b.UndoStack.RecordSetLine(idx, b.Lines[idx].String(), content)
}
b.Lines[idx] = content
b.Lines[idx].Set(content)
}
b.Modified = true
}
@ -74,7 +74,8 @@ func (b *Buffer) InsertLine(idx int, content string) {
b.UndoStack.RecordInsertLine(idx, content)
}
b.Lines = append(b.Lines[:idx], append([]string{content}, b.Lines[idx:]...)...)
newLine := NewGapBuffer(content)
b.Lines = append(b.Lines[:idx], append([]*GapBuffer{newLine}, b.Lines[idx:]...)...)
b.Modified = true
}
@ -84,7 +85,7 @@ func (b *Buffer) DeleteLine(idx int) {
if idx >= 0 && idx < len(b.Lines) {
// Record delete line in undo stack
if b.UndoStack != nil {
b.UndoStack.RecordDeleteLine(idx, b.Lines[idx])
b.UndoStack.RecordDeleteLine(idx, b.Lines[idx].String())
}
b.Lines = append(b.Lines[:idx], b.Lines[idx+1:]...)
}
@ -121,7 +122,7 @@ func (b *Buffer) Undo(w *Window) bool {
case SetLineChange:
// Restore old data
if change.Line >= 0 && change.Line < len(b.Lines) {
b.Lines[change.Line] = change.OldData
b.Lines[change.Line].Set(change.OldData)
}
case InsertLineChange:
// Remove the inserted line
@ -131,7 +132,8 @@ func (b *Buffer) Undo(w *Window) bool {
case DeleteLineChange:
// Re-insert the deleted line
if change.Line <= len(b.Lines) {
b.Lines = append(b.Lines[:change.Line], append([]string{change.OldData}, b.Lines[change.Line:]...)...)
newLine := NewGapBuffer(change.OldData)
b.Lines = append(b.Lines[:change.Line], append([]*GapBuffer{newLine}, b.Lines[change.Line:]...)...)
}
}
@ -165,12 +167,13 @@ func (b *Buffer) Redo(w *Window) bool {
case SetLineChange:
// Apply new data
if change.Line >= 0 && change.Line < len(b.Lines) {
b.Lines[change.Line] = change.NewData
b.Lines[change.Line].Set(change.NewData)
}
case InsertLineChange:
// Re-insert the line
if change.Line <= len(b.Lines) {
b.Lines = append(b.Lines[:change.Line], append([]string{change.NewData}, b.Lines[change.Line:]...)...)
newLine := NewGapBuffer(change.NewData)
b.Lines = append(b.Lines[:change.Line], append([]*GapBuffer{newLine}, b.Lines[change.Line:]...)...)
}
case DeleteLineChange:
// Re-delete the line
@ -208,7 +211,10 @@ func (b *Buffer) SetFiletype(filetype string) {
// Buffer.SetLines: Replace all lines in the buffer with the provided lines.
// This is useful when loading a file or resetting buffer content.
func (b *Buffer) SetLines(lines []string) {
b.Lines = lines
b.Lines = make([]*GapBuffer, len(lines))
for i, line := range lines {
b.Lines[i] = NewGapBuffer(line)
}
}
// Buffer.SetModified: Set the modified flag for this buffer. A modified buffer

View File

@ -16,7 +16,7 @@ func NewBufferBuilder() *BufferBuilder {
Type: ScatchBuffer, // Default buffer type
Filename: "",
Filetype: "",
Lines: []string{""},
Lines: []*GapBuffer{NewEmptyGapBuffer()},
Modified: false,
Loaded: false,
Listed: false,
@ -40,7 +40,10 @@ func (b *BufferBuilder) WithFiletype(filetype string) *BufferBuilder {
// BufferBuilder.WithLines: Attaches a lines to the buffer that is being built.
func (b *BufferBuilder) WithLines(lines []string) *BufferBuilder {
b.buffer.Lines = lines
b.buffer.Lines = make([]*GapBuffer, len(lines))
for i, line := range lines {
b.buffer.Lines[i] = NewGapBuffer(line)
}
return b
}

180
internal/core/gap_buffer.go Normal file
View File

@ -0,0 +1,180 @@
package core
// GapBuffer represents a single line of text using the gap buffer data structure.
// It maintains a gap (empty space) in the buffer where the cursor is positioned,
// making insertions and deletions at the cursor position very efficient (O(1)).
type GapBuffer struct {
buffer []rune // The underlying buffer containing text and gap
gapStart int // Index where the gap starts
gapEnd int // Index where the gap ends (exclusive)
}
// NewGapBuffer: creates a new gap buffer with the given initial content.
// The gap is positioned at the end of the content.
func NewGapBuffer(content string) *GapBuffer {
runes := []rune(content)
initialCapacity := len(runes) + 16 // Extra space for the gap
buffer := make([]rune, initialCapacity)
copy(buffer, runes)
return &GapBuffer{
buffer: buffer,
gapStart: len(runes),
gapEnd: initialCapacity,
}
}
// NewEmptyGapBuffer: Creates a new empty gap buffer with default capacity.
func NewEmptyGapBuffer() *GapBuffer {
initialCapacity := 16
return &GapBuffer{
buffer: make([]rune, initialCapacity),
gapStart: 0,
gapEnd: initialCapacity,
}
}
// GapBuffer.String: Converts the gap buffer to a string, excluding the gap.
func (gb *GapBuffer) String() string {
result := make([]rune, 0, gb.Len())
result = append(result, gb.buffer[:gb.gapStart]...)
result = append(result, gb.buffer[gb.gapEnd:]...)
return string(result)
}
// GapBuffer.Len: Returns the length of the text (excluding the gap).
func (gb *GapBuffer) Len() int {
return len(gb.buffer) - (gb.gapEnd - gb.gapStart)
}
// GapBuffer.GapSize: Returns the current size of the gap.
func (gb *GapBuffer) GapSize() int {
return gb.gapEnd - gb.gapStart
}
// GapBuffer.Insert: Inserts a string at the specified position.
// This moves the gap to the position first, then inserts the text.
func (gb *GapBuffer) Insert(pos int, text string) {
if pos < 0 || pos > gb.Len() {
return // Invalid position
}
runes := []rune(text)
if len(runes) == 0 {
return
}
// Move gap to insertion position
gb.moveGap(pos)
// Ensure gap is large enough
if gb.GapSize() < len(runes) {
gb.grow(len(runes))
}
// Insert runes at gap start
copy(gb.buffer[gb.gapStart:], runes)
gb.gapStart += len(runes)
}
// GapBuffer.Delete: Deletes count runes starting at position pos.
func (gb *GapBuffer) Delete(pos, count int) {
if pos < 0 || pos >= gb.Len() || count <= 0 {
return
}
// Clamp count to not exceed buffer length
if pos+count > gb.Len() {
count = gb.Len() - pos
}
// Move gap to deletion position
gb.moveGap(pos)
// Expand gap to absorb deleted characters
gb.gapEnd += count
}
// GapBuffer.RuneAt: Returns the rune at the specified position.
func (gb *GapBuffer) RuneAt(pos int) rune {
if pos < 0 || pos >= gb.Len() {
return 0
}
if pos < gb.gapStart {
return gb.buffer[pos]
}
return gb.buffer[pos+gb.GapSize()]
}
// GapBuffer.Substring: Returns a substring from start to end (exclusive).
func (gb *GapBuffer) Substring(start, end int) string {
if start < 0 {
start = 0
}
if end > gb.Len() {
end = gb.Len()
}
if start >= end {
return ""
}
result := make([]rune, 0, end-start)
for i := start; i < end; i++ {
result = append(result, gb.RuneAt(i))
}
return string(result)
}
// GapBuffer.moveGap: Moves the gap to the specified position.
func (gb *GapBuffer) moveGap(pos int) {
if pos < gb.gapStart {
// Move gap left: shift text from [pos, gapStart) to [gapEnd-delta, gapEnd)
delta := gb.gapStart - pos
copy(gb.buffer[gb.gapEnd-delta:gb.gapEnd], gb.buffer[pos:gb.gapStart])
gb.gapStart = pos
gb.gapEnd -= delta
} else if pos > gb.gapStart {
// Move gap right: shift text from [gapEnd, gapEnd+delta) to [gapStart, gapStart+delta)
delta := pos - gb.gapStart
copy(gb.buffer[gb.gapStart:gb.gapStart+delta], gb.buffer[gb.gapEnd:gb.gapEnd+delta])
gb.gapStart += delta
gb.gapEnd += delta
}
}
// GapBuffer.grow: Expands the buffer to accommodate at least minGapSize additional characters.
func (gb *GapBuffer) grow(minGapSize int) {
oldLen := len(gb.buffer)
newGapSize := minGapSize * 2 // Double the required size for future insertions
newLen := oldLen + newGapSize - gb.GapSize()
newBuffer := make([]rune, newLen)
// Copy text before gap
copy(newBuffer, gb.buffer[:gb.gapStart])
// Copy text after gap to new position
newGapEnd := newLen - (oldLen - gb.gapEnd)
copy(newBuffer[newGapEnd:], gb.buffer[gb.gapEnd:])
gb.buffer = newBuffer
gb.gapEnd = newGapEnd
}
// GapBuffer.Set: Replaces the entire content of the gap buffer.
func (gb *GapBuffer) Set(content string) {
runes := []rune(content)
capacity := len(runes) + 16
gb.buffer = make([]rune, capacity)
copy(gb.buffer, runes)
gb.gapStart = len(runes)
gb.gapEnd = capacity
}
// GapBuffer.Clear: Removes all content from the gap buffer.
func (gb *GapBuffer) Clear() {
gb.gapStart = 0
gb.gapEnd = len(gb.buffer)
}

View File

@ -0,0 +1,455 @@
package core
import "testing"
func TestGapBufferString(t *testing.T) {
t.Run("gapBuffer.String() on empty buffer returns \"\"", func(t *testing.T) {
buf := NewEmptyGapBuffer()
str := buf.String()
if str != "" {
t.Fatalf("buf.String() expected '', got '%s'", str)
}
})
t.Run("gapBuffer.String() on string returns the string", func(t *testing.T) {
buf := NewGapBuffer("Hello world")
str := buf.String()
if str != "Hello world" {
t.Fatalf("buf.String() expected 'Hello world', got '%s'", str)
}
})
t.Run("gapBuffer.String() after moving gap returns the string", func(t *testing.T) {
buf := NewGapBuffer("Hello world")
buf.moveGap(6)
str := buf.String()
if str != "Hello world" {
t.Fatalf("buf.String() expected 'Hello world', got '%s'", str)
}
})
t.Run("gapBuffer.String() after growing gap returns the string", func(t *testing.T) {
buf := NewGapBuffer("Hello world")
buf.grow(16)
str := buf.String()
if str != "Hello world" {
t.Fatalf("buf.String() expected 'Hello world', got '%s'", str)
}
})
t.Run("gapBuffer.String() handles unicode characters", func(t *testing.T) {
buf := NewGapBuffer("Hello 世界 🌍")
str := buf.String()
if str != "Hello 世界 🌍" {
t.Fatalf("buf.String() expected 'Hello 世界 🌍', got '%s'", str)
}
})
}
func TestGapBufferLen(t *testing.T) {
t.Run("empty buffer has length 0", func(t *testing.T) {
buf := NewEmptyGapBuffer()
if buf.Len() != 0 {
t.Fatalf("expected length 0, got %d", buf.Len())
}
})
t.Run("buffer with content returns correct length", func(t *testing.T) {
buf := NewGapBuffer("Hello")
if buf.Len() != 5 {
t.Fatalf("expected length 5, got %d", buf.Len())
}
})
t.Run("length with unicode characters", func(t *testing.T) {
buf := NewGapBuffer("Hi 🌍")
if buf.Len() != 4 {
t.Fatalf("expected length 4, got %d", buf.Len())
}
})
}
func TestGapBufferInsert(t *testing.T) {
t.Run("insert at beginning", func(t *testing.T) {
buf := NewGapBuffer("world")
buf.Insert(0, "Hello ")
if buf.String() != "Hello world" {
t.Fatalf("expected 'Hello world', got '%s'", buf.String())
}
})
t.Run("insert at end", func(t *testing.T) {
buf := NewGapBuffer("Hello")
buf.Insert(5, " world")
if buf.String() != "Hello world" {
t.Fatalf("expected 'Hello world', got '%s'", buf.String())
}
})
t.Run("insert in middle", func(t *testing.T) {
buf := NewGapBuffer("Helloworld")
buf.Insert(5, " ")
if buf.String() != "Hello world" {
t.Fatalf("expected 'Hello world', got '%s'", buf.String())
}
})
t.Run("insert into empty buffer", func(t *testing.T) {
buf := NewEmptyGapBuffer()
buf.Insert(0, "Hello")
if buf.String() != "Hello" {
t.Fatalf("expected 'Hello', got '%s'", buf.String())
}
})
t.Run("insert empty string does nothing", func(t *testing.T) {
buf := NewGapBuffer("Hello")
buf.Insert(2, "")
if buf.String() != "Hello" {
t.Fatalf("expected 'Hello', got '%s'", buf.String())
}
})
t.Run("insert at invalid position does nothing", func(t *testing.T) {
buf := NewGapBuffer("Hello")
buf.Insert(-1, "X")
if buf.String() != "Hello" {
t.Fatalf("expected 'Hello', got '%s'", buf.String())
}
buf.Insert(100, "X")
if buf.String() != "Hello" {
t.Fatalf("expected 'Hello', got '%s'", buf.String())
}
})
t.Run("insert unicode characters", func(t *testing.T) {
buf := NewGapBuffer("Hello")
buf.Insert(5, " 世界")
if buf.String() != "Hello 世界" {
t.Fatalf("expected 'Hello 世界', got '%s'", buf.String())
}
})
t.Run("multiple consecutive insertions", func(t *testing.T) {
buf := NewEmptyGapBuffer()
buf.Insert(0, "a")
buf.Insert(1, "b")
buf.Insert(2, "c")
if buf.String() != "abc" {
t.Fatalf("expected 'abc', got '%s'", buf.String())
}
})
t.Run("insert large text triggers grow", func(t *testing.T) {
buf := NewGapBuffer("Hello")
longText := "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
buf.Insert(5, longText)
expected := "Hello" + longText
if buf.String() != expected {
t.Fatalf("expected '%s', got '%s'", expected, buf.String())
}
})
}
func TestGapBufferDelete(t *testing.T) {
t.Run("delete from beginning", func(t *testing.T) {
buf := NewGapBuffer("Hello world")
buf.Delete(0, 6)
if buf.String() != "world" {
t.Fatalf("expected 'world', got '%s'", buf.String())
}
})
t.Run("delete from end", func(t *testing.T) {
buf := NewGapBuffer("Hello world")
buf.Delete(5, 6)
if buf.String() != "Hello" {
t.Fatalf("expected 'Hello', got '%s'", buf.String())
}
})
t.Run("delete from middle", func(t *testing.T) {
buf := NewGapBuffer("Hello world")
buf.Delete(5, 1)
if buf.String() != "Helloworld" {
t.Fatalf("expected 'Helloworld', got '%s'", buf.String())
}
})
t.Run("delete single character", func(t *testing.T) {
buf := NewGapBuffer("Hello")
buf.Delete(1, 1)
if buf.String() != "Hllo" {
t.Fatalf("expected 'Hllo', got '%s'", buf.String())
}
})
t.Run("delete all content", func(t *testing.T) {
buf := NewGapBuffer("Hello")
buf.Delete(0, 5)
if buf.String() != "" {
t.Fatalf("expected '', got '%s'", buf.String())
}
})
t.Run("delete with count exceeding length", func(t *testing.T) {
buf := NewGapBuffer("Hello")
buf.Delete(2, 100)
if buf.String() != "He" {
t.Fatalf("expected 'He', got '%s'", buf.String())
}
})
t.Run("delete at invalid position does nothing", func(t *testing.T) {
buf := NewGapBuffer("Hello")
buf.Delete(-1, 2)
if buf.String() != "Hello" {
t.Fatalf("expected 'Hello', got '%s'", buf.String())
}
buf.Delete(100, 2)
if buf.String() != "Hello" {
t.Fatalf("expected 'Hello', got '%s'", buf.String())
}
})
t.Run("delete with zero count does nothing", func(t *testing.T) {
buf := NewGapBuffer("Hello")
buf.Delete(2, 0)
if buf.String() != "Hello" {
t.Fatalf("expected 'Hello', got '%s'", buf.String())
}
})
t.Run("delete unicode characters", func(t *testing.T) {
buf := NewGapBuffer("Hello 世界")
buf.Delete(6, 2)
if buf.String() != "Hello " {
t.Fatalf("expected 'Hello ', got '%s'", buf.String())
}
})
}
func TestGapBufferRuneAt(t *testing.T) {
t.Run("get rune at valid position", func(t *testing.T) {
buf := NewGapBuffer("Hello")
if buf.RuneAt(0) != 'H' {
t.Fatalf("expected 'H', got '%c'", buf.RuneAt(0))
}
if buf.RuneAt(4) != 'o' {
t.Fatalf("expected 'o', got '%c'", buf.RuneAt(4))
}
})
t.Run("get rune before gap", func(t *testing.T) {
buf := NewGapBuffer("Hello world")
buf.moveGap(6)
if buf.RuneAt(5) != ' ' {
t.Fatalf("expected ' ', got '%c'", buf.RuneAt(5))
}
})
t.Run("get rune after gap", func(t *testing.T) {
buf := NewGapBuffer("Hello world")
buf.moveGap(6)
if buf.RuneAt(6) != 'w' {
t.Fatalf("expected 'w', got '%c'", buf.RuneAt(6))
}
})
t.Run("get rune at invalid position returns 0", func(t *testing.T) {
buf := NewGapBuffer("Hello")
if buf.RuneAt(-1) != 0 {
t.Fatalf("expected 0, got '%c'", buf.RuneAt(-1))
}
if buf.RuneAt(100) != 0 {
t.Fatalf("expected 0, got '%c'", buf.RuneAt(100))
}
})
t.Run("get unicode rune", func(t *testing.T) {
buf := NewGapBuffer("🌍世界")
if buf.RuneAt(0) != '🌍' {
t.Fatalf("expected '🌍', got '%c'", buf.RuneAt(0))
}
if buf.RuneAt(1) != '世' {
t.Fatalf("expected '世', got '%c'", buf.RuneAt(1))
}
})
}
func TestGapBufferSubstring(t *testing.T) {
t.Run("substring from middle", func(t *testing.T) {
buf := NewGapBuffer("Hello world")
if buf.Substring(0, 5) != "Hello" {
t.Fatalf("expected 'Hello', got '%s'", buf.Substring(0, 5))
}
if buf.Substring(6, 11) != "world" {
t.Fatalf("expected 'world', got '%s'", buf.Substring(6, 11))
}
})
t.Run("substring entire content", func(t *testing.T) {
buf := NewGapBuffer("Hello")
if buf.Substring(0, 5) != "Hello" {
t.Fatalf("expected 'Hello', got '%s'", buf.Substring(0, 5))
}
})
t.Run("substring with start >= end returns empty", func(t *testing.T) {
buf := NewGapBuffer("Hello")
if buf.Substring(3, 3) != "" {
t.Fatalf("expected '', got '%s'", buf.Substring(3, 3))
}
if buf.Substring(3, 2) != "" {
t.Fatalf("expected '', got '%s'", buf.Substring(3, 2))
}
})
t.Run("substring clamps to buffer bounds", func(t *testing.T) {
buf := NewGapBuffer("Hello")
if buf.Substring(-5, 3) != "Hel" {
t.Fatalf("expected 'Hel', got '%s'", buf.Substring(-5, 3))
}
if buf.Substring(2, 100) != "llo" {
t.Fatalf("expected 'llo', got '%s'", buf.Substring(2, 100))
}
})
t.Run("substring with gap in middle", func(t *testing.T) {
buf := NewGapBuffer("Hello world")
buf.moveGap(6)
if buf.Substring(0, 11) != "Hello world" {
t.Fatalf("expected 'Hello world', got '%s'", buf.Substring(0, 11))
}
})
t.Run("substring with unicode", func(t *testing.T) {
buf := NewGapBuffer("Hi 世界")
if buf.Substring(3, 5) != "世界" {
t.Fatalf("expected '世界', got '%s'", buf.Substring(3, 5))
}
})
}
func TestGapBufferSet(t *testing.T) {
t.Run("set replaces content", func(t *testing.T) {
buf := NewGapBuffer("Hello")
buf.Set("Goodbye")
if buf.String() != "Goodbye" {
t.Fatalf("expected 'Goodbye', got '%s'", buf.String())
}
})
t.Run("set to empty string", func(t *testing.T) {
buf := NewGapBuffer("Hello")
buf.Set("")
if buf.String() != "" {
t.Fatalf("expected '', got '%s'", buf.String())
}
})
t.Run("set on empty buffer", func(t *testing.T) {
buf := NewEmptyGapBuffer()
buf.Set("Hello")
if buf.String() != "Hello" {
t.Fatalf("expected 'Hello', got '%s'", buf.String())
}
})
t.Run("set resets gap position", func(t *testing.T) {
buf := NewGapBuffer("Hello")
buf.moveGap(2)
buf.Set("World")
if buf.String() != "World" {
t.Fatalf("expected 'World', got '%s'", buf.String())
}
if buf.gapStart != 5 {
t.Fatalf("expected gap start at 5, got %d", buf.gapStart)
}
})
}
func TestGapBufferClear(t *testing.T) {
t.Run("clear removes all content", func(t *testing.T) {
buf := NewGapBuffer("Hello world")
buf.Clear()
if buf.String() != "" {
t.Fatalf("expected '', got '%s'", buf.String())
}
})
t.Run("clear on empty buffer", func(t *testing.T) {
buf := NewEmptyGapBuffer()
buf.Clear()
if buf.String() != "" {
t.Fatalf("expected '', got '%s'", buf.String())
}
})
t.Run("clear resets gap to start", func(t *testing.T) {
buf := NewGapBuffer("Hello")
buf.Clear()
if buf.gapStart != 0 {
t.Fatalf("expected gap start at 0, got %d", buf.gapStart)
}
if buf.gapEnd != len(buf.buffer) {
t.Fatalf("expected gap end at %d, got %d", len(buf.buffer), buf.gapEnd)
}
})
}
func TestGapBufferGapSize(t *testing.T) {
t.Run("gap size on new buffer", func(t *testing.T) {
buf := NewGapBuffer("Hello")
if buf.GapSize() != 16 {
t.Fatalf("expected gap size 16, got %d", buf.GapSize())
}
})
t.Run("gap size on empty buffer", func(t *testing.T) {
buf := NewEmptyGapBuffer()
if buf.GapSize() != 16 {
t.Fatalf("expected gap size 16, got %d", buf.GapSize())
}
})
t.Run("gap size decreases after insert", func(t *testing.T) {
buf := NewGapBuffer("Hello")
initialGapSize := buf.GapSize()
buf.Insert(5, "XX")
if buf.GapSize() != initialGapSize-2 {
t.Fatalf("expected gap size %d, got %d", initialGapSize-2, buf.GapSize())
}
})
}
func TestGapBufferComplex(t *testing.T) {
t.Run("sequence of operations", func(t *testing.T) {
buf := NewEmptyGapBuffer()
buf.Insert(0, "Hello")
buf.Insert(5, " world")
buf.Delete(5, 1)
buf.Insert(5, ", ")
if buf.String() != "Hello, world" {
t.Fatalf("expected 'Hello, world', got '%s'", buf.String())
}
})
t.Run("insert and delete at different positions", func(t *testing.T) {
buf := NewGapBuffer("abcdefgh")
buf.Delete(2, 4)
buf.Insert(2, "XX")
if buf.String() != "abXXgh" {
t.Fatalf("expected 'abXXgh', got '%s'", buf.String())
}
})
t.Run("editing with gap movement", func(t *testing.T) {
buf := NewGapBuffer("Hello world")
buf.Insert(0, ">> ")
buf.Insert(buf.Len(), " <<")
if buf.String() != ">> Hello world <<" {
t.Fatalf("expected '>> Hello world <<', got '%s'", buf.String())
}
})
}

View File

@ -60,7 +60,7 @@ func (w *Window) ClampCursor() {
}
// Clamp column to valid range [0, lineLen]
lineLen := len(w.Buffer.Lines[w.Cursor.Line])
lineLen := w.Buffer.Lines[w.Cursor.Line].Len()
if w.Cursor.Col < 0 {
w.Cursor.Col = 0
} else if lineLen == 0 {

View File

@ -13,8 +13,8 @@ func TestDeleteChar(t *testing.T) {
sendKeys(tm, "x")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "ello" {
t.Errorf("lines[0] = %q, want 'ello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "ello" {
t.Errorf("lines[0] = %q, want 'ello'", m.ActiveBuffer().Lines[0].String())
}
})
@ -24,8 +24,8 @@ func TestDeleteChar(t *testing.T) {
sendKeys(tm, "x")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "helo" {
t.Errorf("lines[0] = %q, want 'helo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "helo" {
t.Errorf("lines[0] = %q, want 'helo'", m.ActiveBuffer().Lines[0].String())
}
})
@ -35,8 +35,8 @@ func TestDeleteChar(t *testing.T) {
sendKeys(tm, "x")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hell" {
t.Errorf("lines[0] = %q, want 'hell'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hell" {
t.Errorf("lines[0] = %q, want 'hell'", m.ActiveBuffer().Lines[0].String())
}
})
@ -46,8 +46,8 @@ func TestDeleteChar(t *testing.T) {
sendKeys(tm, "x", "x")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "llo" {
t.Errorf("lines[0] = %q, want 'llo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "llo" {
t.Errorf("lines[0] = %q, want 'llo'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -59,8 +59,8 @@ func TestDeleteCharWithCount(t *testing.T) {
sendKeys(tm, "3", "x")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "lo" {
t.Errorf("lines[0] = %q, want 'lo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "lo" {
t.Errorf("lines[0] = %q, want 'lo'", m.ActiveBuffer().Lines[0].String())
}
})
@ -70,8 +70,8 @@ func TestDeleteCharWithCount(t *testing.T) {
sendKeys(tm, "1", "0", "x")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("lines[0] = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("lines[0] = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
})
@ -81,8 +81,8 @@ func TestDeleteCharWithCount(t *testing.T) {
sendKeys(tm, "2", "x")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hlo" {
t.Errorf("lines[0] = %q, want 'hlo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hlo" {
t.Errorf("lines[0] = %q, want 'hlo'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -94,8 +94,8 @@ func TestDeleteCharEdgeCases(t *testing.T) {
sendKeys(tm, "x")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Col != 0 {
t.Errorf("CursorX() = %d, want 0", m.ActiveWindow().Cursor.Col)
@ -108,8 +108,8 @@ func TestDeleteCharEdgeCases(t *testing.T) {
sendKeys(tm, "x")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
})
@ -119,8 +119,8 @@ func TestDeleteCharEdgeCases(t *testing.T) {
sendKeys(tm, "x")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "a" {
t.Errorf("Line(0) = %q, want 'a'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "a" {
t.Errorf("Line(0) = %q, want 'a'", m.ActiveBuffer().Lines[0].String())
}
})
@ -130,8 +130,8 @@ func TestDeleteCharEdgeCases(t *testing.T) {
sendKeys(tm, "x")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "ab c" {
t.Errorf("Line(0) = %q, want 'ab c'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "ab c" {
t.Errorf("Line(0) = %q, want 'ab c'", m.ActiveBuffer().Lines[0].String())
}
})
@ -144,8 +144,8 @@ func TestDeleteCharEdgeCases(t *testing.T) {
if m.ActiveBuffer().LineCount() != 2 {
t.Errorf("LineCount() = %d, want 2", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[1] != "world" {
t.Errorf("Line(1) = %q, want 'world'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "world" {
t.Errorf("Line(1) = %q, want 'world'", m.ActiveBuffer().Lines[1].String())
}
})
@ -155,8 +155,8 @@ func TestDeleteCharEdgeCases(t *testing.T) {
sendKeys(tm, "x", "x", "x")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "lo" {
t.Errorf("Line(0) = %q, want 'lo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "lo" {
t.Errorf("Line(0) = %q, want 'lo'", m.ActiveBuffer().Lines[0].String())
}
})
@ -166,8 +166,8 @@ func TestDeleteCharEdgeCases(t *testing.T) {
sendKeys(tm, "x")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "ab" {
t.Errorf("Line(0) = %q, want 'ab'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "ab" {
t.Errorf("Line(0) = %q, want 'ab'", m.ActiveBuffer().Lines[0].String())
}
})
@ -177,8 +177,8 @@ func TestDeleteCharEdgeCases(t *testing.T) {
sendKeys(tm, "5", "x")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
})
@ -188,8 +188,8 @@ func TestDeleteCharEdgeCases(t *testing.T) {
sendKeys(tm, "x")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "abde" {
t.Errorf("Line(0) = %q, want 'abde'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "abde" {
t.Errorf("Line(0) = %q, want 'abde'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -201,8 +201,8 @@ func TestDeleteCharBackward(t *testing.T) {
sendKeys(tm, "X")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "ello" {
t.Errorf("lines[0] = %q, want 'ello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "ello" {
t.Errorf("lines[0] = %q, want 'ello'", m.ActiveBuffer().Lines[0].String())
}
})
@ -212,8 +212,8 @@ func TestDeleteCharBackward(t *testing.T) {
sendKeys(tm, "X")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "helo" {
t.Errorf("lines[0] = %q, want 'helo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "helo" {
t.Errorf("lines[0] = %q, want 'helo'", m.ActiveBuffer().Lines[0].String())
}
})
@ -223,8 +223,8 @@ func TestDeleteCharBackward(t *testing.T) {
sendKeys(tm, "X")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "helo" {
t.Errorf("lines[0] = %q, want 'helo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "helo" {
t.Errorf("lines[0] = %q, want 'helo'", m.ActiveBuffer().Lines[0].String())
}
})
@ -234,8 +234,8 @@ func TestDeleteCharBackward(t *testing.T) {
sendKeys(tm, "X", "X")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "llo" {
t.Errorf("lines[0] = %q, want 'llo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "llo" {
t.Errorf("lines[0] = %q, want 'llo'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -247,8 +247,8 @@ func TestDeleteCharBackwardWithCount(t *testing.T) {
sendKeys(tm, "3", "X")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "lo" {
t.Errorf("lines[0] = %q, want 'lo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "lo" {
t.Errorf("lines[0] = %q, want 'lo'", m.ActiveBuffer().Lines[0].String())
}
})
@ -258,8 +258,8 @@ func TestDeleteCharBackwardWithCount(t *testing.T) {
sendKeys(tm, "1", "0", "X")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "o" {
t.Errorf("lines[0] = %q, want 'o'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "o" {
t.Errorf("lines[0] = %q, want 'o'", m.ActiveBuffer().Lines[0].String())
}
})
@ -269,8 +269,8 @@ func TestDeleteCharBackwardWithCount(t *testing.T) {
sendKeys(tm, "2", "X")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hlo" {
t.Errorf("lines[0] = %q, want 'hlo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hlo" {
t.Errorf("lines[0] = %q, want 'hlo'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -282,8 +282,8 @@ func TestDeleteCharBackwardEdgeCases(t *testing.T) {
sendKeys(tm, "X")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello" {
t.Errorf("Line(0) = %q, want 'hello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello" {
t.Errorf("Line(0) = %q, want 'hello'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Col != 0 {
t.Errorf("CursorX() = %d, want 0", m.ActiveWindow().Cursor.Col)
@ -296,8 +296,8 @@ func TestDeleteCharBackwardEdgeCases(t *testing.T) {
sendKeys(tm, "X")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Col != 0 {
t.Errorf("CursorX() = %d, want 0", m.ActiveWindow().Cursor.Col)
@ -310,8 +310,8 @@ func TestDeleteCharBackwardEdgeCases(t *testing.T) {
sendKeys(tm, "X")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "a" {
t.Errorf("Line(0) = %q, want 'a'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "a" {
t.Errorf("Line(0) = %q, want 'a'", m.ActiveBuffer().Lines[0].String())
}
})
@ -321,8 +321,8 @@ func TestDeleteCharBackwardEdgeCases(t *testing.T) {
sendKeys(tm, "X")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "b" {
t.Errorf("Line(0) = %q, want 'b'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "b" {
t.Errorf("Line(0) = %q, want 'b'", m.ActiveBuffer().Lines[0].String())
}
})
@ -332,8 +332,8 @@ func TestDeleteCharBackwardEdgeCases(t *testing.T) {
sendKeys(tm, "X")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "ab c" {
t.Errorf("Line(0) = %q, want 'ab c'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "ab c" {
t.Errorf("Line(0) = %q, want 'ab c'", m.ActiveBuffer().Lines[0].String())
}
})
@ -346,8 +346,8 @@ func TestDeleteCharBackwardEdgeCases(t *testing.T) {
if m.ActiveBuffer().LineCount() != 2 {
t.Errorf("LineCount() = %d, want 2", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[1] != "world" {
t.Errorf("Line(1) = %q, want 'world'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "world" {
t.Errorf("Line(1) = %q, want 'world'", m.ActiveBuffer().Lines[1].String())
}
})
@ -357,8 +357,8 @@ func TestDeleteCharBackwardEdgeCases(t *testing.T) {
sendKeys(tm, "X", "X", "X")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "lo" {
t.Errorf("Line(0) = %q, want 'lo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "lo" {
t.Errorf("Line(0) = %q, want 'lo'", m.ActiveBuffer().Lines[0].String())
}
})
@ -368,8 +368,8 @@ func TestDeleteCharBackwardEdgeCases(t *testing.T) {
sendKeys(tm, "X")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "ab" {
t.Errorf("Line(0) = %q, want 'ab'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "ab" {
t.Errorf("Line(0) = %q, want 'ab'", m.ActiveBuffer().Lines[0].String())
}
})
@ -379,8 +379,8 @@ func TestDeleteCharBackwardEdgeCases(t *testing.T) {
sendKeys(tm, "5", "X")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "c" {
t.Errorf("Line(0) = %q, want 'c'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "c" {
t.Errorf("Line(0) = %q, want 'c'", m.ActiveBuffer().Lines[0].String())
}
})
@ -390,8 +390,8 @@ func TestDeleteCharBackwardEdgeCases(t *testing.T) {
sendKeys(tm, "X")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "abde" {
t.Errorf("Line(0) = %q, want 'abde'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "abde" {
t.Errorf("Line(0) = %q, want 'abde'", m.ActiveBuffer().Lines[0].String())
}
})
@ -413,8 +413,8 @@ func TestDeleteCharBackwardEdgeCases(t *testing.T) {
sendKeys(tm, "3", "X")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "ho" {
t.Errorf("Line(0) = %q, want 'ho'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "ho" {
t.Errorf("Line(0) = %q, want 'ho'", m.ActiveBuffer().Lines[0].String())
}
// Cursor should be at position 1 after deleting 3 chars backward from position 4
if m.ActiveWindow().Cursor.Col != 1 {
@ -428,11 +428,11 @@ func TestDeleteCharBackwardEdgeCases(t *testing.T) {
sendKeys(tm, "X")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello" {
t.Errorf("Line(0) = %q, want 'hello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello" {
t.Errorf("Line(0) = %q, want 'hello'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "world" {
t.Errorf("Line(1) = %q, want 'world'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "world" {
t.Errorf("Line(1) = %q, want 'world'", m.ActiveBuffer().Lines[1].String())
}
})
@ -442,8 +442,8 @@ func TestDeleteCharBackwardEdgeCases(t *testing.T) {
sendKeys(tm, "X")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != " " {
t.Errorf("Line(0) = %q, want ' '", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != " " {
t.Errorf("Line(0) = %q, want ' '", m.ActiveBuffer().Lines[0].String())
}
})
@ -453,8 +453,8 @@ func TestDeleteCharBackwardEdgeCases(t *testing.T) {
sendKeys(tm, "X")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "helo" {
t.Errorf("Line(0) = %q, want 'helo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "helo" {
t.Errorf("Line(0) = %q, want 'helo'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Col != 3 {
t.Errorf("CursorX() = %d, want 3", m.ActiveWindow().Cursor.Col)
@ -469,8 +469,8 @@ func TestDeleteToEndOfLine(t *testing.T) {
sendKeys(tm, "D")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello" {
t.Errorf("Line(0) = %q, want 'hello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello" {
t.Errorf("Line(0) = %q, want 'hello'", m.ActiveBuffer().Lines[0].String())
}
})
@ -480,8 +480,8 @@ func TestDeleteToEndOfLine(t *testing.T) {
sendKeys(tm, "D")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
})
@ -491,8 +491,8 @@ func TestDeleteToEndOfLine(t *testing.T) {
sendKeys(tm, "D")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hell" {
t.Errorf("Line(0) = %q, want 'hell'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hell" {
t.Errorf("Line(0) = %q, want 'hell'", m.ActiveBuffer().Lines[0].String())
}
})
@ -514,8 +514,8 @@ func TestDeleteToEndOfLine(t *testing.T) {
sendKeys(tm, "D")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
})
@ -528,11 +528,11 @@ func TestDeleteToEndOfLine(t *testing.T) {
if m.ActiveBuffer().LineCount() != 3 {
t.Errorf("LineCount() = %q, want '3'", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "he" {
t.Errorf("Line(0) = %q, want 'he'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "he" {
t.Errorf("Line(0) = %q, want 'he'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "hi" {
t.Errorf("Line(1) = %q, want 'hi'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "hi" {
t.Errorf("Line(1) = %q, want 'hi'", m.ActiveBuffer().Lines[1].String())
}
})
@ -545,8 +545,8 @@ func TestDeleteToEndOfLine(t *testing.T) {
if m.ActiveBuffer().LineCount() != 1 {
t.Errorf("LineCount() = %q, want '1'", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "he" {
t.Errorf("Line(0) = %q, want 'he'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "he" {
t.Errorf("Line(0) = %q, want 'he'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -558,8 +558,8 @@ func TestDeleteToEndOfLineEdgeCases(t *testing.T) {
sendKeys(tm, "D")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
})
@ -572,8 +572,8 @@ func TestDeleteToEndOfLineEdgeCases(t *testing.T) {
if m.ActiveBuffer().LineCount() != 2 {
t.Errorf("LineCount() = %d, want 2", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[1] != "" {
t.Errorf("Line(1) = %q, want ''", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "" {
t.Errorf("Line(1) = %q, want ''", m.ActiveBuffer().Lines[1].String())
}
})
@ -583,11 +583,11 @@ func TestDeleteToEndOfLineEdgeCases(t *testing.T) {
sendKeys(tm, "D")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[2] != "line 3" {
t.Errorf("Line(2) = %q, want 'line 3'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "line 3" {
t.Errorf("Line(2) = %q, want 'line 3'", m.ActiveBuffer().Lines[2].String())
}
})
@ -597,8 +597,8 @@ func TestDeleteToEndOfLineEdgeCases(t *testing.T) {
sendKeys(tm, "D")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "he" {
t.Errorf("Line(0) = %q, want 'he'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "he" {
t.Errorf("Line(0) = %q, want 'he'", m.ActiveBuffer().Lines[0].String())
}
// Cursor should clamp to last char
if m.ActiveWindow().Cursor.Col != 1 {
@ -612,8 +612,8 @@ func TestDeleteToEndOfLineEdgeCases(t *testing.T) {
sendKeys(tm, "D")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
})
@ -623,8 +623,8 @@ func TestDeleteToEndOfLineEdgeCases(t *testing.T) {
sendKeys(tm, "D")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != " " {
t.Errorf("Line(0) = %q, want ' '", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != " " {
t.Errorf("Line(0) = %q, want ' '", m.ActiveBuffer().Lines[0].String())
}
})
@ -634,8 +634,8 @@ func TestDeleteToEndOfLineEdgeCases(t *testing.T) {
sendKeys(tm, "D")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello" {
t.Errorf("Line(0) = %q, want 'hello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello" {
t.Errorf("Line(0) = %q, want 'hello'", m.ActiveBuffer().Lines[0].String())
}
})
@ -645,8 +645,8 @@ func TestDeleteToEndOfLineEdgeCases(t *testing.T) {
sendKeys(tm, "D")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "a" {
t.Errorf("Line(0) = %q, want 'a'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "a" {
t.Errorf("Line(0) = %q, want 'a'", m.ActiveBuffer().Lines[0].String())
}
})
@ -656,8 +656,8 @@ func TestDeleteToEndOfLineEdgeCases(t *testing.T) {
sendKeys(tm, "D")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[1] != "world" {
t.Errorf("Line(1) = %q, want 'world'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "world" {
t.Errorf("Line(1) = %q, want 'world'", m.ActiveBuffer().Lines[1].String())
}
})
@ -667,8 +667,8 @@ func TestDeleteToEndOfLineEdgeCases(t *testing.T) {
sendKeys(tm, "D")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "first" {
t.Errorf("Line(0) = %q, want 'first'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "first" {
t.Errorf("Line(0) = %q, want 'first'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().LineCount() != 3 {
t.Errorf("LineCount() = %d, want 3", m.ActiveBuffer().LineCount())

View File

@ -25,8 +25,8 @@ func TestEnterInsert(t *testing.T) {
sendKeys(tm, "i", "X", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "Xhello" {
t.Errorf("lines[0] = %q, want 'Xhello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "Xhello" {
t.Errorf("lines[0] = %q, want 'Xhello'", m.ActiveBuffer().Lines[0].String())
}
})
@ -36,8 +36,8 @@ func TestEnterInsert(t *testing.T) {
sendKeys(tm, "i", "X", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "heXllo" {
t.Errorf("lines[0] = %q, want 'heXllo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "heXllo" {
t.Errorf("lines[0] = %q, want 'heXllo'", m.ActiveBuffer().Lines[0].String())
}
})
@ -70,8 +70,8 @@ func TestEnterInsertAfter(t *testing.T) {
sendKeys(tm, "a", "X", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hXello" {
t.Errorf("lines[0] = %q, want 'hXello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hXello" {
t.Errorf("lines[0] = %q, want 'hXello'", m.ActiveBuffer().Lines[0].String())
}
})
@ -81,8 +81,8 @@ func TestEnterInsertAfter(t *testing.T) {
sendKeys(tm, "a", "X", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "helXlo" {
t.Errorf("lines[0] = %q, want 'helXlo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "helXlo" {
t.Errorf("lines[0] = %q, want 'helXlo'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -94,8 +94,8 @@ func TestEnterInsertLineStart(t *testing.T) {
sendKeys(tm, "I", "X", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "Xhello" {
t.Errorf("lines[0] = %q, want 'Xhello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "Xhello" {
t.Errorf("lines[0] = %q, want 'Xhello'", m.ActiveBuffer().Lines[0].String())
}
})
@ -105,8 +105,8 @@ func TestEnterInsertLineStart(t *testing.T) {
sendKeys(tm, "I", "X", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "Xhello" {
t.Errorf("lines[0] = %q, want 'Xhello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "Xhello" {
t.Errorf("lines[0] = %q, want 'Xhello'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -118,8 +118,8 @@ func TestEnterInsertLineEnd(t *testing.T) {
sendKeys(tm, "A", "X", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "helloX" {
t.Errorf("lines[0] = %q, want 'helloX'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "helloX" {
t.Errorf("lines[0] = %q, want 'helloX'", m.ActiveBuffer().Lines[0].String())
}
})
@ -129,8 +129,8 @@ func TestEnterInsertLineEnd(t *testing.T) {
sendKeys(tm, "A", "X", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "helloX" {
t.Errorf("lines[0] = %q, want 'helloX'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "helloX" {
t.Errorf("lines[0] = %q, want 'helloX'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -147,8 +147,8 @@ func TestOpenLineBelow(t *testing.T) {
if m.ActiveBuffer().LineCount() != 3 {
t.Errorf("len(lines) = %d, want 3", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[1] != "new" {
t.Errorf("lines[1] = %q, want 'new'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "new" {
t.Errorf("lines[1] = %q, want 'new'", m.ActiveBuffer().Lines[1].String())
}
})
@ -161,8 +161,8 @@ func TestOpenLineBelow(t *testing.T) {
if m.ActiveBuffer().LineCount() != 4 {
t.Errorf("len(lines) = %d, want 4", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[2] != "new" {
t.Errorf("lines[2] = %q, want 'new'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "new" {
t.Errorf("lines[2] = %q, want 'new'", m.ActiveBuffer().Lines[2].String())
}
})
@ -175,8 +175,8 @@ func TestOpenLineBelow(t *testing.T) {
if m.ActiveBuffer().LineCount() != 3 {
t.Errorf("len(lines) = %d, want 3", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[2] != "new" {
t.Errorf("lines[2] = %q, want 'new'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "new" {
t.Errorf("lines[2] = %q, want 'new'", m.ActiveBuffer().Lines[2].String())
}
})
@ -206,8 +206,8 @@ func TestOpenLineBelowWithCount(t *testing.T) {
t.Errorf("len(lines) = %d, want 4", m.ActiveBuffer().LineCount())
}
for i := 1; i <= 3; i++ {
if m.ActiveBuffer().Lines[i] != "x" {
t.Errorf("lines[%d] = %q, want 'x'", i, m.ActiveBuffer().Lines[i])
if m.ActiveBuffer().Lines[i].String() != "x" {
t.Errorf("lines[%d] = %q, want 'x'", i, m.ActiveBuffer().Lines[i].String())
}
}
})
@ -221,11 +221,11 @@ func TestOpenLineBelowWithCount(t *testing.T) {
if m.ActiveBuffer().LineCount() != 3 {
t.Errorf("len(lines) = %d, want 3", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[1] != "ab" {
t.Errorf("lines[1] = %q, want 'ab'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "ab" {
t.Errorf("lines[1] = %q, want 'ab'", m.ActiveBuffer().Lines[1].String())
}
if m.ActiveBuffer().Lines[2] != "ab" {
t.Errorf("lines[2] = %q, want 'ab'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "ab" {
t.Errorf("lines[2] = %q, want 'ab'", m.ActiveBuffer().Lines[2].String())
}
})
}
@ -240,8 +240,8 @@ func TestOpenLineAbove(t *testing.T) {
if m.ActiveBuffer().LineCount() != 3 {
t.Errorf("len(lines) = %d, want 3", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[1] != "new" {
t.Errorf("lines[1] = %q, want 'new'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "new" {
t.Errorf("lines[1] = %q, want 'new'", m.ActiveBuffer().Lines[1].String())
}
})
@ -254,8 +254,8 @@ func TestOpenLineAbove(t *testing.T) {
if m.ActiveBuffer().LineCount() != 3 {
t.Errorf("len(lines) = %d, want 3", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "new" {
t.Errorf("lines[0] = %q, want 'new'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "new" {
t.Errorf("lines[0] = %q, want 'new'", m.ActiveBuffer().Lines[0].String())
}
})
@ -282,8 +282,8 @@ func TestOpenLineAboveWithCount(t *testing.T) {
t.Errorf("len(lines) = %d, want 4", m.ActiveBuffer().LineCount())
}
for i := 0; i < 3; i++ {
if m.ActiveBuffer().Lines[i] != "x" {
t.Errorf("lines[%d] = %q, want 'x'", i, m.ActiveBuffer().Lines[i])
if m.ActiveBuffer().Lines[i].String() != "x" {
t.Errorf("lines[%d] = %q, want 'x'", i, m.ActiveBuffer().Lines[i].String())
}
}
})
@ -301,11 +301,11 @@ func TestInsertModeEnter(t *testing.T) {
if m.ActiveBuffer().LineCount() != 2 {
t.Errorf("len(lines) = %d, want 2", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "hello" {
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello" {
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != " world" {
t.Errorf("lines[1] = %q, want ' world'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != " world" {
t.Errorf("lines[1] = %q, want ' world'", m.ActiveBuffer().Lines[1].String())
}
})
@ -318,11 +318,11 @@ func TestInsertModeEnter(t *testing.T) {
if m.ActiveBuffer().LineCount() != 2 {
t.Errorf("len(lines) = %d, want 2", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "hello" {
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello" {
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "" {
t.Errorf("lines[1] = %q, want ''", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "" {
t.Errorf("lines[1] = %q, want ''", m.ActiveBuffer().Lines[1].String())
}
})
@ -335,11 +335,11 @@ func TestInsertModeEnter(t *testing.T) {
if m.ActiveBuffer().LineCount() != 2 {
t.Errorf("len(lines) = %d, want 2", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("lines[0] = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("lines[0] = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "hello" {
t.Errorf("lines[1] = %q, want 'hello'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "hello" {
t.Errorf("lines[1] = %q, want 'hello'", m.ActiveBuffer().Lines[1].String())
}
})
}
@ -351,8 +351,8 @@ func TestInsertModeBackspace(t *testing.T) {
sendKeys(tm, "i", "backspace", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "helo" {
t.Errorf("lines[0] = %q, want 'helo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "helo" {
t.Errorf("lines[0] = %q, want 'helo'", m.ActiveBuffer().Lines[0].String())
}
})
@ -365,8 +365,8 @@ func TestInsertModeBackspace(t *testing.T) {
if m.ActiveBuffer().LineCount() != 1 {
t.Errorf("len(lines) = %d, want 1", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "helloworld" {
t.Errorf("lines[0] = %q, want 'helloworld'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "helloworld" {
t.Errorf("lines[0] = %q, want 'helloworld'", m.ActiveBuffer().Lines[0].String())
}
})
@ -376,8 +376,8 @@ func TestInsertModeBackspace(t *testing.T) {
sendKeys(tm, "i", "backspace", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello" {
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello" {
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0].String())
}
})
@ -387,8 +387,8 @@ func TestInsertModeBackspace(t *testing.T) {
sendKeys(tm, "i", "backspace", "backspace", "backspace", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "he" {
t.Errorf("lines[0] = %q, want 'he'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "he" {
t.Errorf("lines[0] = %q, want 'he'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -400,8 +400,8 @@ func TestInsertModeDelete(t *testing.T) {
sendKeys(tm, "i", "delete", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "word" {
t.Errorf("lines[0] = %q, want 'word'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "word" {
t.Errorf("lines[0] = %q, want 'word'", m.ActiveBuffer().Lines[0].String())
}
})
@ -414,8 +414,8 @@ func TestInsertModeDelete(t *testing.T) {
if m.ActiveBuffer().LineCount() != 1 {
t.Errorf("len(lines) = %d, want 1", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "helloworld" {
t.Errorf("lines[0] = %q, want 'helloworld'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "helloworld" {
t.Errorf("lines[0] = %q, want 'helloworld'", m.ActiveBuffer().Lines[0].String())
}
})
@ -428,8 +428,8 @@ func TestInsertModeDelete(t *testing.T) {
if m.ActiveBuffer().LineCount() != 1 {
t.Errorf("len(lines) = %d, want 1", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "world" {
t.Errorf("lines[0] = %q, want 'world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "world" {
t.Errorf("lines[0] = %q, want 'world'", m.ActiveBuffer().Lines[0].String())
}
})
@ -439,8 +439,8 @@ func TestInsertModeDelete(t *testing.T) {
sendKeys(tm, "i", "delete", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello" {
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello" {
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0].String())
}
})
@ -450,8 +450,8 @@ func TestInsertModeDelete(t *testing.T) {
sendKeys(tm, "i", "delete", "delete", "delete", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "ho" {
t.Errorf("lines[0] = %q, want 'he'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "ho" {
t.Errorf("lines[0] = %q, want 'he'", m.ActiveBuffer().Lines[0].String())
}
})
@ -464,8 +464,8 @@ func TestInsertModeArrowKeys(t *testing.T) {
sendKeys(tm, "i", "left", "X", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "heXllo" {
t.Errorf("lines[0] = %q, want 'heXllo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "heXllo" {
t.Errorf("lines[0] = %q, want 'heXllo'", m.ActiveBuffer().Lines[0].String())
}
})
@ -475,8 +475,8 @@ func TestInsertModeArrowKeys(t *testing.T) {
sendKeys(tm, "i", "right", "X", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "heXllo" {
t.Errorf("lines[0] = %q, want 'heXllo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "heXllo" {
t.Errorf("lines[0] = %q, want 'heXllo'", m.ActiveBuffer().Lines[0].String())
}
})
@ -486,11 +486,11 @@ func TestInsertModeArrowKeys(t *testing.T) {
sendKeys(tm, "i", "up", "X", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "heXllo" {
t.Errorf("lines[0] = %q, want 'heXllo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "heXllo" {
t.Errorf("lines[0] = %q, want 'heXllo'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "world" {
t.Errorf("lines[1] = %q, want 'world'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "world" {
t.Errorf("lines[1] = %q, want 'world'", m.ActiveBuffer().Lines[1].String())
}
})
@ -500,11 +500,11 @@ func TestInsertModeArrowKeys(t *testing.T) {
sendKeys(tm, "i", "down", "X", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello" {
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello" {
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "woXrld" {
t.Errorf("lines[1] = %q, want 'woXrld'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "woXrld" {
t.Errorf("lines[1] = %q, want 'woXrld'", m.ActiveBuffer().Lines[1].String())
}
})
@ -514,8 +514,8 @@ func TestInsertModeArrowKeys(t *testing.T) {
sendKeys(tm, "i", "left", "X", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "Xhello" {
t.Errorf("lines[0] = %q, want 'Xhello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "Xhello" {
t.Errorf("lines[0] = %q, want 'Xhello'", m.ActiveBuffer().Lines[0].String())
}
})
@ -525,8 +525,8 @@ func TestInsertModeArrowKeys(t *testing.T) {
sendKeys(tm, "a", "right", "X", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "helloX" {
t.Errorf("lines[0] = %q, want 'helloX'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "helloX" {
t.Errorf("lines[0] = %q, want 'helloX'", m.ActiveBuffer().Lines[0].String())
}
})
@ -536,8 +536,8 @@ func TestInsertModeArrowKeys(t *testing.T) {
sendKeys(tm, "i", "up", "X", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "heXllo" {
t.Errorf("lines[0] = %q, want 'heXllo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "heXllo" {
t.Errorf("lines[0] = %q, want 'heXllo'", m.ActiveBuffer().Lines[0].String())
}
})
@ -547,8 +547,8 @@ func TestInsertModeArrowKeys(t *testing.T) {
sendKeys(tm, "i", "down", "X", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "heXllo" {
t.Errorf("lines[0] = %q, want 'heXllo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "heXllo" {
t.Errorf("lines[0] = %q, want 'heXllo'", m.ActiveBuffer().Lines[0].String())
}
})
@ -558,8 +558,8 @@ func TestInsertModeArrowKeys(t *testing.T) {
sendKeys(tm, "i", "up", "X", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hiX" {
t.Errorf("lines[0] = %q, want 'hiX'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hiX" {
t.Errorf("lines[0] = %q, want 'hiX'", m.ActiveBuffer().Lines[0].String())
}
})
@ -569,8 +569,8 @@ func TestInsertModeArrowKeys(t *testing.T) {
sendKeys(tm, "i", "down", "X", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[1] != "hiX" {
t.Errorf("lines[1] = %q, want 'hiX'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "hiX" {
t.Errorf("lines[1] = %q, want 'hiX'", m.ActiveBuffer().Lines[1].String())
}
})
@ -580,8 +580,8 @@ func TestInsertModeArrowKeys(t *testing.T) {
sendKeys(tm, "i", "right", "right", "down", "X", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[1] != "woXrld" {
t.Errorf("lines[1] = %q, want 'woXrld'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "woXrld" {
t.Errorf("lines[1] = %q, want 'woXrld'", m.ActiveBuffer().Lines[1].String())
}
})
}
@ -593,8 +593,8 @@ func TestInsertModeDeletePreviousWord(t *testing.T) {
sendKeys(tm, "a", "ctrl+w", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello " {
t.Errorf("lines[0] = %q, want 'hello '", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello " {
t.Errorf("lines[0] = %q, want 'hello '", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Col != 5 {
t.Errorf("CursorX() = %d, want '5'", m.ActiveWindow().Cursor.Col)
@ -607,8 +607,8 @@ func TestInsertModeDeletePreviousWord(t *testing.T) {
sendKeys(tm, "a", "ctrl+w", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("lines[0] = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("lines[0] = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Col != 0 {
t.Errorf("CursorX() = %d, want '0'", m.ActiveWindow().Cursor.Col)
@ -621,8 +621,8 @@ func TestInsertModeDeletePreviousWord(t *testing.T) {
sendKeys(tm, "a", "ctrl+w", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello wo" {
t.Errorf("lines[0] = %q, want 'hello wo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello wo" {
t.Errorf("lines[0] = %q, want 'hello wo'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Col != 7 {
t.Errorf("CursorX() = %d, want '7'", m.ActiveWindow().Cursor.Col)
@ -655,8 +655,8 @@ func TestInsertModeDeletePreviousWord(t *testing.T) {
if m.ActiveBuffer().LineCount() != 1 {
t.Errorf("LineCount() = %d, want '1'", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %s, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %s, want ''", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Col != 0 {
t.Errorf("CursorX() = %d, want '0'", m.ActiveWindow().Cursor.Col)
@ -672,8 +672,8 @@ func TestInsertModeDeletePreviousWord(t *testing.T) {
sendKeys(tm, "i", "ctrl+w", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello" {
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello" {
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Col != 0 {
t.Errorf("CursorX() = %d, want 0", m.ActiveWindow().Cursor.Col)
@ -686,8 +686,8 @@ func TestInsertModeDeletePreviousWord(t *testing.T) {
sendKeys(tm, "i", "ctrl+w", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "lo" {
t.Errorf("lines[0] = %q, want 'lo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "lo" {
t.Errorf("lines[0] = %q, want 'lo'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Col != 0 {
t.Errorf("CursorX() = %d, want 0", m.ActiveWindow().Cursor.Col)
@ -700,8 +700,8 @@ func TestInsertModeDeletePreviousWord(t *testing.T) {
sendKeys(tm, "a", "ctrl+w", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "..." {
t.Errorf("lines[0] = %q, want '...'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "..." {
t.Errorf("lines[0] = %q, want '...'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Col != 2 {
t.Errorf("CursorX() = %d, want 2", m.ActiveWindow().Cursor.Col)
@ -714,8 +714,8 @@ func TestInsertModeDeletePreviousWord(t *testing.T) {
sendKeys(tm, "a", "ctrl+w", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello\t" {
t.Errorf("lines[0] = %q, want 'hello\\t'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello\t" {
t.Errorf("lines[0] = %q, want 'hello\\t'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Col != 5 {
t.Errorf("CursorX() = %d, want 5", m.ActiveWindow().Cursor.Col)
@ -731,8 +731,8 @@ func TestInsertModeDeletePreviousWord(t *testing.T) {
if m.ActiveBuffer().LineCount() != 1 {
t.Errorf("LineCount() = %d, want 1", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "helloworld" {
t.Errorf("lines[0] = %q, want 'helloworld'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "helloworld" {
t.Errorf("lines[0] = %q, want 'helloworld'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Col != 4 {
t.Errorf("CursorX() = %d, want 4", m.ActiveWindow().Cursor.Col)
@ -748,8 +748,8 @@ func TestInsertModeDeletePreviousWord(t *testing.T) {
sendKeys(tm, "a", "ctrl+w", "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("lines[0] = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("lines[0] = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Col != 0 {
t.Errorf("CursorX() = %d, want 0", m.ActiveWindow().Cursor.Col)

View File

@ -633,8 +633,8 @@ func TestMoveToColumnWithOperator(t *testing.T) {
// Deletes from column 1 to current position (exclusive), so "hello" deleted
// Result depends on inclusive/exclusive behavior
// In Vim: d| from col 5 deletes chars 0-4, leaving " world"
if m.ActiveBuffer().Lines[0] != " world" {
t.Errorf("Line(0) = %q, want ' world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != " world" {
t.Errorf("Line(0) = %q, want ' world'", m.ActiveBuffer().Lines[0].String())
}
})
@ -646,8 +646,8 @@ func TestMoveToColumnWithOperator(t *testing.T) {
m := getFinalModel(t, tm)
// Deletes from cursor (0) to column 5 (index 4), so "hell" deleted
// Result: "o world"
if m.ActiveBuffer().Lines[0] != "o world" {
t.Errorf("Line(0) = %q, want 'o world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "o world" {
t.Errorf("Line(0) = %q, want 'o world'", m.ActiveBuffer().Lines[0].String())
}
})
@ -720,8 +720,8 @@ func TestMoveToColumnInVisualMode(t *testing.T) {
m := getFinalModel(t, tm)
// Visual selection from 0 to 4 inclusive, delete "hello"
if m.ActiveBuffer().Lines[0] != " world" {
t.Errorf("Line(0) = %q, want ' world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != " world" {
t.Errorf("Line(0) = %q, want ' world'", m.ActiveBuffer().Lines[0].String())
}
})
}

View File

@ -928,8 +928,8 @@ func TestMoveForwardWORDWithOperator(t *testing.T) {
m := getFinalModel(t, tm)
// Should delete "hello.world " (including trailing space)
if m.ActiveBuffer().Lines[0] != "next" {
t.Errorf("Line(0) = %q, want 'next'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "next" {
t.Errorf("Line(0) = %q, want 'next'", m.ActiveBuffer().Lines[0].String())
}
})
@ -946,11 +946,11 @@ func TestMoveForwardWORDWithOperator(t *testing.T) {
sendKeys(tm2, "d", "w")
m2 := getFinalModel(t, tm2)
if m1.ActiveBuffer().Lines[0] != "next" {
t.Errorf("dW: Line(0) = %q, want 'next'", m1.ActiveBuffer().Lines[0])
if m1.ActiveBuffer().Lines[0].String() != "next" {
t.Errorf("dW: Line(0) = %q, want 'next'", m1.ActiveBuffer().Lines[0].String())
}
if m2.ActiveBuffer().Lines[0] != ".world next" {
t.Errorf("dw: Line(0) = %q, want '.world next'", m2.ActiveBuffer().Lines[0])
if m2.ActiveBuffer().Lines[0].String() != ".world next" {
t.Errorf("dw: Line(0) = %q, want '.world next'", m2.ActiveBuffer().Lines[0].String())
}
})
@ -960,8 +960,8 @@ func TestMoveForwardWORDWithOperator(t *testing.T) {
sendKeys(tm, "d", "2", "W")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "three four" {
t.Errorf("Line(0) = %q, want 'three four'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "three four" {
t.Errorf("Line(0) = %q, want 'three four'", m.ActiveBuffer().Lines[0].String())
}
})
@ -1028,8 +1028,8 @@ func TestMoveForwardWORDInVisualMode(t *testing.T) {
m := getFinalModel(t, tm)
// Visual selection from 0 to 12, delete "hello.world "
if m.ActiveBuffer().Lines[0] != "ext" {
t.Errorf("Line(0) = %q, want 'ext'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "ext" {
t.Errorf("Line(0) = %q, want 'ext'", m.ActiveBuffer().Lines[0].String())
}
})
@ -1557,8 +1557,8 @@ func TestMoveForwardWORDEndWithOperator(t *testing.T) {
m := getFinalModel(t, tm)
// Should delete "hello.world" leaving " next"
if m.ActiveBuffer().Lines[0] != " next" {
t.Errorf("Line(0) = %q, want ' next'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != " next" {
t.Errorf("Line(0) = %q, want ' next'", m.ActiveBuffer().Lines[0].String())
}
})
@ -1570,8 +1570,8 @@ func TestMoveForwardWORDEndWithOperator(t *testing.T) {
m1 := getFinalModel(t, tm1)
// 'de' should delete "hello" leaving ".world next"
if m1.ActiveBuffer().Lines[0] != ".world next" {
t.Errorf("'de': Line(0) = %q, want '.world next'", m1.ActiveBuffer().Lines[0])
if m1.ActiveBuffer().Lines[0].String() != ".world next" {
t.Errorf("'de': Line(0) = %q, want '.world next'", m1.ActiveBuffer().Lines[0].String())
}
// Now test 'dE'
@ -1580,8 +1580,8 @@ func TestMoveForwardWORDEndWithOperator(t *testing.T) {
m2 := getFinalModel(t, tm2)
// 'dE' should delete "hello.world" leaving " next"
if m2.ActiveBuffer().Lines[0] != " next" {
t.Errorf("'dE': Line(0) = %q, want ' next'", m2.ActiveBuffer().Lines[0])
if m2.ActiveBuffer().Lines[0].String() != " next" {
t.Errorf("'dE': Line(0) = %q, want ' next'", m2.ActiveBuffer().Lines[0].String())
}
})
@ -1592,8 +1592,8 @@ func TestMoveForwardWORDEndWithOperator(t *testing.T) {
m := getFinalModel(t, tm)
// Should delete "one.a two.b" leaving " three"
if m.ActiveBuffer().Lines[0] != " three" {
t.Errorf("Line(0) = %q, want ' three'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != " three" {
t.Errorf("Line(0) = %q, want ' three'", m.ActiveBuffer().Lines[0].String())
}
})
@ -1653,8 +1653,8 @@ func TestMoveForwardWORDEndInVisualMode(t *testing.T) {
m := getFinalModel(t, tm)
// Should delete "hello.world" leaving " next"
if m.ActiveBuffer().Lines[0] != " next" {
t.Errorf("Line(0) = %q, want ' next'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != " next" {
t.Errorf("Line(0) = %q, want ' next'", m.ActiveBuffer().Lines[0].String())
}
})

View File

@ -26,11 +26,11 @@ func TestChangeLine(t *testing.T) {
t.Errorf("LineCount() = %d, want 2", m.ActiveBuffer().LineCount())
}
// First line should be empty (ready for insert)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "world" {
t.Errorf("Line(1) = %q, want 'world'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "world" {
t.Errorf("Line(1) = %q, want 'world'", m.ActiveBuffer().Lines[1].String())
}
})
@ -45,14 +45,14 @@ func TestChangeLine(t *testing.T) {
if m.Mode() != core.InsertMode {
t.Errorf("Mode() = %v, want InsertMode", m.Mode())
}
if m.ActiveBuffer().Lines[0] != "line one" {
t.Errorf("Line(0) = %q, want 'line one'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line one" {
t.Errorf("Line(0) = %q, want 'line one'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "" {
t.Errorf("Line(1) = %q, want ''", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "" {
t.Errorf("Line(1) = %q, want ''", m.ActiveBuffer().Lines[1].String())
}
if m.ActiveBuffer().Lines[2] != "line three" {
t.Errorf("Line(2) = %q, want 'line three'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "line three" {
t.Errorf("Line(2) = %q, want 'line three'", m.ActiveBuffer().Lines[2].String())
}
})
@ -67,11 +67,11 @@ func TestChangeLine(t *testing.T) {
if m.Mode() != core.InsertMode {
t.Errorf("Mode() = %v, want InsertMode", m.Mode())
}
if m.ActiveBuffer().Lines[0] != "hello" {
t.Errorf("Line(0) = %q, want 'hello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello" {
t.Errorf("Line(0) = %q, want 'hello'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "" {
t.Errorf("Line(1) = %q, want ''", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "" {
t.Errorf("Line(1) = %q, want ''", m.ActiveBuffer().Lines[1].String())
}
})
@ -109,8 +109,8 @@ func TestChangeLine(t *testing.T) {
if m.ActiveBuffer().LineCount() != 1 {
t.Errorf("LineCount() = %d, want 1", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
})
@ -148,11 +148,11 @@ func TestChangeLineWithCount(t *testing.T) {
if m.ActiveBuffer().LineCount() != 3 {
t.Errorf("LineCount() = %d, want 3", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "line three" {
t.Errorf("Line(1) = %q, want 'line three'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "line three" {
t.Errorf("Line(1) = %q, want 'line three'", m.ActiveBuffer().Lines[1].String())
}
})
@ -171,14 +171,14 @@ func TestChangeLineWithCount(t *testing.T) {
if m.ActiveBuffer().LineCount() != 3 {
t.Errorf("LineCount() = %d, want 3", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "one" {
t.Errorf("Line(0) = %q, want 'one'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "one" {
t.Errorf("Line(0) = %q, want 'one'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "" {
t.Errorf("Line(1) = %q, want ''", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "" {
t.Errorf("Line(1) = %q, want ''", m.ActiveBuffer().Lines[1].String())
}
if m.ActiveBuffer().Lines[2] != "five" {
t.Errorf("Line(2) = %q, want 'five'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "five" {
t.Errorf("Line(2) = %q, want 'five'", m.ActiveBuffer().Lines[2].String())
}
})
@ -196,8 +196,8 @@ func TestChangeLineWithCount(t *testing.T) {
if m.ActiveBuffer().LineCount() != 1 {
t.Errorf("LineCount() = %d, want 1", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
})
@ -235,8 +235,8 @@ func TestChangeWithHorizontalMotion(t *testing.T) {
if m.Mode() != core.InsertMode {
t.Errorf("Mode() = %v, want InsertMode", m.Mode())
}
if m.ActiveBuffer().Lines[0] != "ello world" {
t.Errorf("Line(0) = %q, want 'ello world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "ello world" {
t.Errorf("Line(0) = %q, want 'ello world'", m.ActiveBuffer().Lines[0].String())
}
})
@ -251,8 +251,8 @@ func TestChangeWithHorizontalMotion(t *testing.T) {
if m.Mode() != core.InsertMode {
t.Errorf("Mode() = %v, want InsertMode", m.Mode())
}
if m.ActiveBuffer().Lines[0] != "llo world" {
t.Errorf("Line(0) = %q, want 'llo world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "llo world" {
t.Errorf("Line(0) = %q, want 'llo world'", m.ActiveBuffer().Lines[0].String())
}
})
@ -267,8 +267,8 @@ func TestChangeWithHorizontalMotion(t *testing.T) {
if m.Mode() != core.InsertMode {
t.Errorf("Mode() = %v, want InsertMode", m.Mode())
}
if m.ActiveBuffer().Lines[0] != "hell world" {
t.Errorf("Line(0) = %q, want 'hell world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hell world" {
t.Errorf("Line(0) = %q, want 'hell world'", m.ActiveBuffer().Lines[0].String())
}
})
@ -283,8 +283,8 @@ func TestChangeWithHorizontalMotion(t *testing.T) {
if m.Mode() != core.InsertMode {
t.Errorf("Mode() = %v, want InsertMode", m.Mode())
}
if m.ActiveBuffer().Lines[0] != "hello " {
t.Errorf("Line(0) = %q, want 'hello '", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello " {
t.Errorf("Line(0) = %q, want 'hello '", m.ActiveBuffer().Lines[0].String())
}
})
@ -299,8 +299,8 @@ func TestChangeWithHorizontalMotion(t *testing.T) {
if m.Mode() != core.InsertMode {
t.Errorf("Mode() = %v, want InsertMode", m.Mode())
}
if m.ActiveBuffer().Lines[0] != "world" {
t.Errorf("Line(0) = %q, want 'world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "world" {
t.Errorf("Line(0) = %q, want 'world'", m.ActiveBuffer().Lines[0].String())
}
})
@ -317,8 +317,8 @@ func TestChangeWithHorizontalMotion(t *testing.T) {
}
// ^ is exclusive motion, so position 8 (space) is not included
// Delete positions 3-7 ("hello"), leaving " " + " world" = " world"
if m.ActiveBuffer().Lines[0] != " world" {
t.Errorf("Line(0) = %q, want ' world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != " world" {
t.Errorf("Line(0) = %q, want ' world'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -339,8 +339,8 @@ func TestChangeWithWordMotion(t *testing.T) {
if m.Mode() != core.InsertMode {
t.Errorf("Mode() = %v, want InsertMode", m.Mode())
}
if m.ActiveBuffer().Lines[0] != "world" {
t.Errorf("Line(0) = %q, want 'world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "world" {
t.Errorf("Line(0) = %q, want 'world'", m.ActiveBuffer().Lines[0].String())
}
})
@ -355,8 +355,8 @@ func TestChangeWithWordMotion(t *testing.T) {
if m.Mode() != core.InsertMode {
t.Errorf("Mode() = %v, want InsertMode", m.Mode())
}
if m.ActiveBuffer().Lines[0] != "heworld" {
t.Errorf("Line(0) = %q, want 'heworld'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "heworld" {
t.Errorf("Line(0) = %q, want 'heworld'", m.ActiveBuffer().Lines[0].String())
}
})
@ -371,8 +371,8 @@ func TestChangeWithWordMotion(t *testing.T) {
if m.Mode() != core.InsertMode {
t.Errorf("Mode() = %v, want InsertMode", m.Mode())
}
if m.ActiveBuffer().Lines[0] != " world" {
t.Errorf("Line(0) = %q, want ' world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != " world" {
t.Errorf("Line(0) = %q, want ' world'", m.ActiveBuffer().Lines[0].String())
}
})
@ -387,8 +387,8 @@ func TestChangeWithWordMotion(t *testing.T) {
if m.Mode() != core.InsertMode {
t.Errorf("Mode() = %v, want InsertMode", m.Mode())
}
if m.ActiveBuffer().Lines[0] != "world" {
t.Errorf("Line(0) = %q, want 'world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "world" {
t.Errorf("Line(0) = %q, want 'world'", m.ActiveBuffer().Lines[0].String())
}
})
@ -403,8 +403,8 @@ func TestChangeWithWordMotion(t *testing.T) {
if m.Mode() != core.InsertMode {
t.Errorf("Mode() = %v, want InsertMode", m.Mode())
}
if m.ActiveBuffer().Lines[0] != "three four" {
t.Errorf("Line(0) = %q, want 'three four'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "three four" {
t.Errorf("Line(0) = %q, want 'three four'", m.ActiveBuffer().Lines[0].String())
}
})
@ -419,8 +419,8 @@ func TestChangeWithWordMotion(t *testing.T) {
if m.Mode() != core.InsertMode {
t.Errorf("Mode() = %v, want InsertMode", m.Mode())
}
if m.ActiveBuffer().Lines[0] != "next" {
t.Errorf("Line(0) = %q, want 'next'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "next" {
t.Errorf("Line(0) = %q, want 'next'", m.ActiveBuffer().Lines[0].String())
}
})
@ -435,8 +435,8 @@ func TestChangeWithWordMotion(t *testing.T) {
if m.Mode() != core.InsertMode {
t.Errorf("Mode() = %v, want InsertMode", m.Mode())
}
if m.ActiveBuffer().Lines[0] != " next" {
t.Errorf("Line(0) = %q, want ' next'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != " next" {
t.Errorf("Line(0) = %q, want ' next'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -461,11 +461,11 @@ func TestChangeWithVerticalMotion(t *testing.T) {
if m.ActiveBuffer().LineCount() != 2 {
t.Errorf("LineCount() = %d, want 2", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "line three" {
t.Errorf("Line(1) = %q, want 'line three'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "line three" {
t.Errorf("Line(1) = %q, want 'line three'", m.ActiveBuffer().Lines[1].String())
}
})
@ -484,11 +484,11 @@ func TestChangeWithVerticalMotion(t *testing.T) {
if m.ActiveBuffer().LineCount() != 2 {
t.Errorf("LineCount() = %d, want 2", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "line three" {
t.Errorf("Line(1) = %q, want 'line three'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "line three" {
t.Errorf("Line(1) = %q, want 'line three'", m.ActiveBuffer().Lines[1].String())
}
})
@ -507,11 +507,11 @@ func TestChangeWithVerticalMotion(t *testing.T) {
if m.ActiveBuffer().LineCount() != 3 {
t.Errorf("LineCount() = %d, want 3", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "four" {
t.Errorf("Line(1) = %q, want 'four'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "four" {
t.Errorf("Line(1) = %q, want 'four'", m.ActiveBuffer().Lines[1].String())
}
})
}
@ -536,8 +536,8 @@ func TestChangeWithJumpMotion(t *testing.T) {
if m.ActiveBuffer().LineCount() != 1 {
t.Errorf("LineCount() = %d, want 1", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
})
@ -556,8 +556,8 @@ func TestChangeWithJumpMotion(t *testing.T) {
if m.ActiveBuffer().LineCount() != 1 {
t.Errorf("LineCount() = %d, want 1", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
})
@ -576,11 +576,11 @@ func TestChangeWithJumpMotion(t *testing.T) {
if m.ActiveBuffer().LineCount() != 2 {
t.Errorf("LineCount() = %d, want 2", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "line one" {
t.Errorf("Line(0) = %q, want 'line one'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line one" {
t.Errorf("Line(0) = %q, want 'line one'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "" {
t.Errorf("Line(1) = %q, want ''", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "" {
t.Errorf("Line(1) = %q, want ''", m.ActiveBuffer().Lines[1].String())
}
})
}
@ -601,8 +601,8 @@ func TestChangeToEndOfLine(t *testing.T) {
if m.Mode() != core.InsertMode {
t.Errorf("Mode() = %v, want InsertMode", m.Mode())
}
if m.ActiveBuffer().Lines[0] != "hello " {
t.Errorf("Line(0) = %q, want 'hello '", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello " {
t.Errorf("Line(0) = %q, want 'hello '", m.ActiveBuffer().Lines[0].String())
}
})
@ -617,8 +617,8 @@ func TestChangeToEndOfLine(t *testing.T) {
if m.Mode() != core.InsertMode {
t.Errorf("Mode() = %v, want InsertMode", m.Mode())
}
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
})
@ -634,8 +634,8 @@ func TestChangeToEndOfLine(t *testing.T) {
t.Errorf("Mode() = %v, want InsertMode", m.Mode())
}
// Should delete last char
if m.ActiveBuffer().Lines[0] != "hell" {
t.Errorf("Line(0) = %q, want 'hell'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hell" {
t.Errorf("Line(0) = %q, want 'hell'", m.ActiveBuffer().Lines[0].String())
}
})
@ -673,8 +673,8 @@ func TestSubstituteCharacter(t *testing.T) {
if m.Mode() != core.InsertMode {
t.Errorf("Mode() = %v, want InsertMode", m.Mode())
}
if m.ActiveBuffer().Lines[0] != "ello" {
t.Errorf("Line(0) = %q, want 'ello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "ello" {
t.Errorf("Line(0) = %q, want 'ello'", m.ActiveBuffer().Lines[0].String())
}
})
@ -689,8 +689,8 @@ func TestSubstituteCharacter(t *testing.T) {
if m.Mode() != core.InsertMode {
t.Errorf("Mode() = %v, want InsertMode", m.Mode())
}
if m.ActiveBuffer().Lines[0] != "llo" {
t.Errorf("Line(0) = %q, want 'llo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "llo" {
t.Errorf("Line(0) = %q, want 'llo'", m.ActiveBuffer().Lines[0].String())
}
})
@ -705,8 +705,8 @@ func TestSubstituteCharacter(t *testing.T) {
if m.Mode() != core.InsertMode {
t.Errorf("Mode() = %v, want InsertMode", m.Mode())
}
if m.ActiveBuffer().Lines[0] != "hell" {
t.Errorf("Line(0) = %q, want 'hell'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hell" {
t.Errorf("Line(0) = %q, want 'hell'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -727,8 +727,8 @@ func TestSubstituteLine(t *testing.T) {
if m.Mode() != core.InsertMode {
t.Errorf("Mode() = %v, want InsertMode", m.Mode())
}
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
})
@ -740,14 +740,14 @@ func TestSubstituteLine(t *testing.T) {
sendKeys(tm, "S")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "line one" {
t.Errorf("Line(0) = %q, want 'line one'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line one" {
t.Errorf("Line(0) = %q, want 'line one'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "" {
t.Errorf("Line(1) = %q, want ''", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "" {
t.Errorf("Line(1) = %q, want ''", m.ActiveBuffer().Lines[1].String())
}
if m.ActiveBuffer().Lines[2] != "line three" {
t.Errorf("Line(2) = %q, want 'line three'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "line three" {
t.Errorf("Line(2) = %q, want 'line three'", m.ActiveBuffer().Lines[2].String())
}
})
@ -766,11 +766,11 @@ func TestSubstituteLine(t *testing.T) {
if m.ActiveBuffer().LineCount() != 3 {
t.Errorf("LineCount() = %d, want 3", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "three" {
t.Errorf("Line(1) = %q, want 'three'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "three" {
t.Errorf("Line(1) = %q, want 'three'", m.ActiveBuffer().Lines[1].String())
}
})
}
@ -791,8 +791,8 @@ func TestVisualModeChange(t *testing.T) {
if m.Mode() != core.InsertMode {
t.Errorf("Mode() = %v, want InsertMode", m.Mode())
}
if m.ActiveBuffer().Lines[0] != "ello world" {
t.Errorf("Line(0) = %q, want 'ello world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "ello world" {
t.Errorf("Line(0) = %q, want 'ello world'", m.ActiveBuffer().Lines[0].String())
}
})
@ -807,8 +807,8 @@ func TestVisualModeChange(t *testing.T) {
if m.Mode() != core.InsertMode {
t.Errorf("Mode() = %v, want InsertMode", m.Mode())
}
if m.ActiveBuffer().Lines[0] != " world" {
t.Errorf("Line(0) = %q, want ' world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != " world" {
t.Errorf("Line(0) = %q, want ' world'", m.ActiveBuffer().Lines[0].String())
}
})
@ -823,8 +823,8 @@ func TestVisualModeChange(t *testing.T) {
if m.Mode() != core.InsertMode {
t.Errorf("Mode() = %v, want InsertMode", m.Mode())
}
if m.ActiveBuffer().Lines[0] != "hello " {
t.Errorf("Line(0) = %q, want 'hello '", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello " {
t.Errorf("Line(0) = %q, want 'hello '", m.ActiveBuffer().Lines[0].String())
}
})
@ -878,8 +878,8 @@ func TestVisualLineModeChange(t *testing.T) {
if m.ActiveBuffer().LineCount() != 3 {
t.Errorf("LineCount() = %d, want 3", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[1] != "" {
t.Errorf("Line(1) = %q, want ''", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "" {
t.Errorf("Line(1) = %q, want ''", m.ActiveBuffer().Lines[1].String())
}
})
@ -898,14 +898,14 @@ func TestVisualLineModeChange(t *testing.T) {
if m.ActiveBuffer().LineCount() != 3 {
t.Errorf("LineCount() = %d, want 3", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "line one" {
t.Errorf("Line(0) = %q, want 'line one'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line one" {
t.Errorf("Line(0) = %q, want 'line one'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "" {
t.Errorf("Line(1) = %q, want ''", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "" {
t.Errorf("Line(1) = %q, want ''", m.ActiveBuffer().Lines[1].String())
}
if m.ActiveBuffer().Lines[2] != "line four" {
t.Errorf("Line(2) = %q, want 'line four'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "line four" {
t.Errorf("Line(2) = %q, want 'line four'", m.ActiveBuffer().Lines[2].String())
}
})
@ -946,8 +946,8 @@ func TestChangeEdgeCases(t *testing.T) {
if m.Mode() != core.InsertMode {
t.Errorf("Mode() = %v, want InsertMode", m.Mode())
}
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
})
@ -963,8 +963,8 @@ func TestChangeEdgeCases(t *testing.T) {
t.Errorf("Mode() = %v, want InsertMode", m.Mode())
}
// cw on last word should change to end of line
if m.ActiveBuffer().Lines[0] != "hello " {
t.Errorf("Line(0) = %q, want 'hello '", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello " {
t.Errorf("Line(0) = %q, want 'hello '", m.ActiveBuffer().Lines[0].String())
}
})
@ -979,8 +979,8 @@ func TestChangeEdgeCases(t *testing.T) {
if m.Mode() != core.InsertMode {
t.Errorf("Mode() = %v, want InsertMode", m.Mode())
}
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
})

View File

@ -24,8 +24,8 @@ func TestDeleteLine(t *testing.T) {
if m.ActiveWindow().Cursor.Line != 0 {
t.Errorf("CursorY() = %d, want '0'", m.ActiveWindow().Cursor.Line)
}
if m.ActiveBuffer().Lines[0] != "world" {
t.Errorf("Line(0) = %s, want 'world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "world" {
t.Errorf("Line(0) = %s, want 'world'", m.ActiveBuffer().Lines[0].String())
}
})
@ -44,11 +44,11 @@ func TestDeleteLine(t *testing.T) {
if m.ActiveWindow().Cursor.Line != 1 {
t.Errorf("CursorY() = %d, want '1'", m.ActiveWindow().Cursor.Line)
}
if m.ActiveBuffer().Lines[0] != "hello" {
t.Errorf("Line(0) = %s, want 'hello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello" {
t.Errorf("Line(0) = %s, want 'hello'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "testing" {
t.Errorf("Line(1) = %s, want 'testing'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "testing" {
t.Errorf("Line(1) = %s, want 'testing'", m.ActiveBuffer().Lines[1].String())
}
})
@ -67,8 +67,8 @@ func TestDeleteLine(t *testing.T) {
if m.ActiveWindow().Cursor.Line != 0 {
t.Errorf("CursorY() = %d, want '0'", m.ActiveWindow().Cursor.Line)
}
if m.ActiveBuffer().Lines[0] != "hello" {
t.Errorf("Line(0) = %s, want 'hello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello" {
t.Errorf("Line(0) = %s, want 'hello'", m.ActiveBuffer().Lines[0].String())
}
})
@ -87,8 +87,8 @@ func TestDeleteLine(t *testing.T) {
if m.ActiveWindow().Cursor.Line != 0 {
t.Errorf("CursorY() = %d, want '0'", m.ActiveWindow().Cursor.Line)
}
if m.ActiveBuffer().Lines[0] != "world" {
t.Errorf("Line(0) = %s, want 'world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "world" {
t.Errorf("Line(0) = %s, want 'world'", m.ActiveBuffer().Lines[0].String())
}
})
@ -107,12 +107,12 @@ func TestDeleteLine(t *testing.T) {
if m.ActiveWindow().Cursor.Line != 1 {
t.Errorf("CursorY() = %d, want '1'", m.ActiveWindow().Cursor.Line)
}
if m.ActiveBuffer().Lines[0] != "hello" {
t.Errorf("Line(0) = %s, want 'hello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello" {
t.Errorf("Line(0) = %s, want 'hello'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "another line" {
t.Errorf("Line(1) = %s, want 'another line'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "another line" {
t.Errorf("Line(1) = %s, want 'another line'", m.ActiveBuffer().Lines[1].String())
}
})
@ -131,8 +131,8 @@ func TestDeleteLine(t *testing.T) {
if m.ActiveWindow().Cursor.Line != 0 {
t.Errorf("CursorY() = %d, want '0'", m.ActiveWindow().Cursor.Line)
}
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %s, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %s, want ''", m.ActiveBuffer().Lines[0].String())
}
})
@ -151,8 +151,8 @@ func TestDeleteLine(t *testing.T) {
if m.ActiveWindow().Cursor.Line != 0 {
t.Errorf("CursorY() = %d, want '0'", m.ActiveWindow().Cursor.Line)
}
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %s, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %s, want ''", m.ActiveBuffer().Lines[0].String())
}
})
@ -176,8 +176,8 @@ func TestDeleteLine(t *testing.T) {
if m.ActiveBuffer().LineCount() != 1 {
t.Errorf("LineCount() = %d, want 1", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want \"\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want \"\"", m.ActiveBuffer().Lines[0].String())
}
})
@ -190,8 +190,8 @@ func TestDeleteLine(t *testing.T) {
if m.ActiveBuffer().LineCount() != 1 {
t.Errorf("LineCount() = %d, want 1", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "hello" {
t.Errorf("Line(0) = %q, want \"hello\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello" {
t.Errorf("Line(0) = %q, want \"hello\"", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Line != 0 {
t.Errorf("CursorY() = %d, want 0", m.ActiveWindow().Cursor.Line)
@ -210,8 +210,8 @@ func TestDeleteOperatorWithHorozontalMotion(t *testing.T) {
if m.ActiveWindow().Cursor.Col != 0 {
t.Errorf("CursorX() = %d, want '0'", m.ActiveWindow().Cursor.Col)
}
if m.ActiveBuffer().Lines[0] != "ello" {
t.Errorf("Line(0) = %s, want 'ello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "ello" {
t.Errorf("Line(0) = %s, want 'ello'", m.ActiveBuffer().Lines[0].String())
}
})
@ -224,8 +224,8 @@ func TestDeleteOperatorWithHorozontalMotion(t *testing.T) {
if m.ActiveWindow().Cursor.Col != 2 {
t.Errorf("CursorX() = %d, want '2'", m.ActiveWindow().Cursor.Col)
}
if m.ActiveBuffer().Lines[0] != "helo" {
t.Errorf("Line(0) = %s, want 'helo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "helo" {
t.Errorf("Line(0) = %s, want 'helo'", m.ActiveBuffer().Lines[0].String())
}
})
@ -238,8 +238,8 @@ func TestDeleteOperatorWithHorozontalMotion(t *testing.T) {
if m.ActiveWindow().Cursor.Col != 4 {
t.Errorf("CursorX() = %d, want '4'", m.ActiveWindow().Cursor.Col)
}
if m.ActiveBuffer().Lines[0] != "hell" {
t.Errorf("Line(0) = %s, want 'hell'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hell" {
t.Errorf("Line(0) = %s, want 'hell'", m.ActiveBuffer().Lines[0].String())
}
})
@ -252,8 +252,8 @@ func TestDeleteOperatorWithHorozontalMotion(t *testing.T) {
if m.ActiveWindow().Cursor.Col != 0 {
t.Errorf("CursorX() = %d, want '0'", m.ActiveWindow().Cursor.Col)
}
if m.ActiveBuffer().Lines[0] != "hello" {
t.Errorf("Line(0) = %s, want 'hello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello" {
t.Errorf("Line(0) = %s, want 'hello'", m.ActiveBuffer().Lines[0].String())
}
})
@ -267,8 +267,8 @@ func TestDeleteOperatorWithHorozontalMotion(t *testing.T) {
if m.ActiveWindow().Cursor.Col != 1 {
t.Errorf("CursorX() = %d, want 1", m.ActiveWindow().Cursor.Col)
}
if m.ActiveBuffer().Lines[0] != "hllo" {
t.Errorf("Line(0) = %q, want 'hllo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hllo" {
t.Errorf("Line(0) = %q, want 'hllo'", m.ActiveBuffer().Lines[0].String())
}
})
@ -282,8 +282,8 @@ func TestDeleteOperatorWithHorozontalMotion(t *testing.T) {
if m.ActiveWindow().Cursor.Col != 3 {
t.Errorf("CursorX() = %d, want 3", m.ActiveWindow().Cursor.Col)
}
if m.ActiveBuffer().Lines[0] != "helo" {
t.Errorf("Line(0) = %q, want 'helo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "helo" {
t.Errorf("Line(0) = %q, want 'helo'", m.ActiveBuffer().Lines[0].String())
}
})
@ -293,8 +293,8 @@ func TestDeleteOperatorWithHorozontalMotion(t *testing.T) {
sendKeys(tm, "2", "d", "l")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "llo" {
t.Errorf("Line(0) = %q, want 'llo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "llo" {
t.Errorf("Line(0) = %q, want 'llo'", m.ActiveBuffer().Lines[0].String())
}
})
@ -304,8 +304,8 @@ func TestDeleteOperatorWithHorozontalMotion(t *testing.T) {
sendKeys(tm, "d", "2", "l")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "llo" {
t.Errorf("Line(0) = %q, want 'llo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "llo" {
t.Errorf("Line(0) = %q, want 'llo'", m.ActiveBuffer().Lines[0].String())
}
})
@ -315,8 +315,8 @@ func TestDeleteOperatorWithHorozontalMotion(t *testing.T) {
sendKeys(tm, "2", "d", "h")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "heo" {
t.Errorf("Line(0) = %q, want 'heo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "heo" {
t.Errorf("Line(0) = %q, want 'heo'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -331,11 +331,11 @@ func TestDeleteOperatorWithVerticalMotion(t *testing.T) {
if m.ActiveBuffer().LineCount() != 2 {
t.Errorf("LineCount() = %d, want 2", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "line 4" {
t.Errorf("Line(1) = %q, want 'line 4'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "line 4" {
t.Errorf("Line(1) = %q, want 'line 4'", m.ActiveBuffer().Lines[1].String())
}
if m.ActiveWindow().Cursor.Line != 1 {
t.Errorf("CursorY() = %d, want 1", m.ActiveWindow().Cursor.Line)
@ -351,8 +351,8 @@ func TestDeleteOperatorWithVerticalMotion(t *testing.T) {
if m.ActiveBuffer().LineCount() != 1 {
t.Errorf("LineCount() = %d, want 1", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "line 3" {
t.Errorf("Line(0) = %q, want 'line 3'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line 3" {
t.Errorf("Line(0) = %q, want 'line 3'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Line != 0 {
t.Errorf("CursorY() = %d, want 0", m.ActiveWindow().Cursor.Line)
@ -370,11 +370,11 @@ func TestDeleteOperatorWithVerticalMotion(t *testing.T) {
if m.ActiveBuffer().LineCount() != 2 {
t.Errorf("LineCount() = %d, want 2", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "line 2" {
t.Errorf("Line(1) = %q, want 'line 2'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "line 2" {
t.Errorf("Line(1) = %q, want 'line 2'", m.ActiveBuffer().Lines[1].String())
}
})
@ -387,11 +387,11 @@ func TestDeleteOperatorWithVerticalMotion(t *testing.T) {
if m.ActiveBuffer().LineCount() != 2 {
t.Errorf("LineCount() = %d, want 2", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "line 5" {
t.Errorf("Line(1) = %q, want 'line 5'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "line 5" {
t.Errorf("Line(1) = %q, want 'line 5'", m.ActiveBuffer().Lines[1].String())
}
})
@ -404,11 +404,11 @@ func TestDeleteOperatorWithVerticalMotion(t *testing.T) {
if m.ActiveBuffer().LineCount() != 2 {
t.Errorf("LineCount() = %d, want 2", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "line 5" {
t.Errorf("Line(1) = %q, want 'line 5'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "line 5" {
t.Errorf("Line(1) = %q, want 'line 5'", m.ActiveBuffer().Lines[1].String())
}
})
@ -421,11 +421,11 @@ func TestDeleteOperatorWithVerticalMotion(t *testing.T) {
if m.ActiveBuffer().LineCount() != 2 {
t.Errorf("LineCount() = %d, want 2", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "line 4" {
t.Errorf("Line(1) = %q, want 'line 4'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "line 4" {
t.Errorf("Line(1) = %q, want 'line 4'", m.ActiveBuffer().Lines[1].String())
}
if m.ActiveWindow().Cursor.Line != 1 {
t.Errorf("CursorY() = %d, want 1", m.ActiveWindow().Cursor.Line)
@ -443,11 +443,11 @@ func TestDeleteOperatorWithVerticalMotion(t *testing.T) {
if m.ActiveBuffer().LineCount() != 2 {
t.Errorf("LineCount() = %d, want 2", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "line 2" {
t.Errorf("Line(0) = %q, want 'line 2'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line 2" {
t.Errorf("Line(0) = %q, want 'line 2'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "line 3" {
t.Errorf("Line(1) = %q, want 'line 3'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "line 3" {
t.Errorf("Line(1) = %q, want 'line 3'", m.ActiveBuffer().Lines[1].String())
}
})
@ -460,8 +460,8 @@ func TestDeleteOperatorWithVerticalMotion(t *testing.T) {
if m.ActiveBuffer().LineCount() != 1 {
t.Errorf("LineCount() = %d, want 1", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "line 3" {
t.Errorf("Line(0) = %q, want 'line 3'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line 3" {
t.Errorf("Line(0) = %q, want 'line 3'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Line != 0 {
t.Errorf("CursorY() = %d, want 0", m.ActiveWindow().Cursor.Line)
@ -477,11 +477,11 @@ func TestDeleteOperatorWithVerticalMotion(t *testing.T) {
if m.ActiveBuffer().LineCount() != 2 {
t.Errorf("LineCount() = %d, want 2", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "line 5" {
t.Errorf("Line(1) = %q, want 'line 5'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "line 5" {
t.Errorf("Line(1) = %q, want 'line 5'", m.ActiveBuffer().Lines[1].String())
}
})
@ -494,11 +494,11 @@ func TestDeleteOperatorWithVerticalMotion(t *testing.T) {
if m.ActiveBuffer().LineCount() != 2 {
t.Errorf("LineCount() = %d, want 2", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "line 5" {
t.Errorf("Line(1) = %q, want 'line 5'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "line 5" {
t.Errorf("Line(1) = %q, want 'line 5'", m.ActiveBuffer().Lines[1].String())
}
})
@ -512,8 +512,8 @@ func TestDeleteOperatorWithVerticalMotion(t *testing.T) {
if m.ActiveBuffer().LineCount() != 1 {
t.Errorf("LineCount() = %d, want 1", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0].String())
}
})
@ -527,8 +527,8 @@ func TestDeleteOperatorWithVerticalMotion(t *testing.T) {
if m.ActiveBuffer().LineCount() != 1 {
t.Errorf("LineCount() = %d, want 1", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "line 3" {
t.Errorf("Line(0) = %q, want 'line 3'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line 3" {
t.Errorf("Line(0) = %q, want 'line 3'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -541,8 +541,8 @@ func TestDeleteOperatorWithWordMotion(t *testing.T) {
sendKeys(tm, "d", "w")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "world" {
t.Errorf("Line(0) = %q, want \"world\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "world" {
t.Errorf("Line(0) = %q, want \"world\"", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Col != 0 {
t.Errorf("CursorX() = %d, want 0", m.ActiveWindow().Cursor.Col)
@ -555,8 +555,8 @@ func TestDeleteOperatorWithWordMotion(t *testing.T) {
sendKeys(tm, "d", "w")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "heworld" {
t.Errorf("Line(0) = %q, want \"heworld\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "heworld" {
t.Errorf("Line(0) = %q, want \"heworld\"", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Col != 2 {
t.Errorf("CursorX() = %d, want 2", m.ActiveWindow().Cursor.Col)
@ -569,8 +569,8 @@ func TestDeleteOperatorWithWordMotion(t *testing.T) {
sendKeys(tm, "d", "w")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello " {
t.Errorf("Line(0) = %q, want \"hello \"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello " {
t.Errorf("Line(0) = %q, want \"hello \"", m.ActiveBuffer().Lines[0].String())
}
})
@ -580,8 +580,8 @@ func TestDeleteOperatorWithWordMotion(t *testing.T) {
sendKeys(tm, "2", "d", "w")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "three four" {
t.Errorf("Line(0) = %q, want \"three four\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "three four" {
t.Errorf("Line(0) = %q, want \"three four\"", m.ActiveBuffer().Lines[0].String())
}
})
@ -591,8 +591,8 @@ func TestDeleteOperatorWithWordMotion(t *testing.T) {
sendKeys(tm, "d", "2", "w")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "three four" {
t.Errorf("Line(0) = %q, want \"three four\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "three four" {
t.Errorf("Line(0) = %q, want \"three four\"", m.ActiveBuffer().Lines[0].String())
}
})
@ -603,8 +603,8 @@ func TestDeleteOperatorWithWordMotion(t *testing.T) {
m := getFinalModel(t, tm)
// 'w' motion stops at punctuation, so it should delete "hello"
if m.ActiveBuffer().Lines[0] != ", world" {
t.Errorf("Line(0) = %q, want \", world\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != ", world" {
t.Errorf("Line(0) = %q, want \", world\"", m.ActiveBuffer().Lines[0].String())
}
})
@ -616,8 +616,8 @@ func TestDeleteOperatorWithWordMotion(t *testing.T) {
m := getFinalModel(t, tm)
// 'e' is inclusive - deletes "hello" (cols 0-4 inclusive), leaves " world"
if m.ActiveBuffer().Lines[0] != " world" {
t.Errorf("Line(0) = %q, want \" world\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != " world" {
t.Errorf("Line(0) = %q, want \" world\"", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Col != 0 {
t.Errorf("CursorX() = %d, want 0", m.ActiveWindow().Cursor.Col)
@ -631,8 +631,8 @@ func TestDeleteOperatorWithWordMotion(t *testing.T) {
m := getFinalModel(t, tm)
// From 'l' (col 2) to 'o' (col 4) inclusive → deletes "llo"
if m.ActiveBuffer().Lines[0] != "he world" {
t.Errorf("Line(0) = %q, want \"he world\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "he world" {
t.Errorf("Line(0) = %q, want \"he world\"", m.ActiveBuffer().Lines[0].String())
}
})
@ -643,8 +643,8 @@ func TestDeleteOperatorWithWordMotion(t *testing.T) {
m := getFinalModel(t, tm)
// From 'o' of "hello" (col 4) to 'd' of "world" (col 10) inclusive
if m.ActiveBuffer().Lines[0] != "hell" {
t.Errorf("Line(0) = %q, want \"hell\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hell" {
t.Errorf("Line(0) = %q, want \"hell\"", m.ActiveBuffer().Lines[0].String())
}
})
@ -655,8 +655,8 @@ func TestDeleteOperatorWithWordMotion(t *testing.T) {
m := getFinalModel(t, tm)
// Deletes "one" and " two" (to end of second word inclusive)
if m.ActiveBuffer().Lines[0] != " three four" {
t.Errorf("Line(0) = %q, want \" three four\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != " three four" {
t.Errorf("Line(0) = %q, want \" three four\"", m.ActiveBuffer().Lines[0].String())
}
})
@ -667,8 +667,8 @@ func TestDeleteOperatorWithWordMotion(t *testing.T) {
sendKeys(tm, "d", "b")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello world" {
t.Errorf("Line(0) = %q, want \"hello world\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello world" {
t.Errorf("Line(0) = %q, want \"hello world\"", m.ActiveBuffer().Lines[0].String())
}
})
@ -679,8 +679,8 @@ func TestDeleteOperatorWithWordMotion(t *testing.T) {
m := getFinalModel(t, tm)
// cursor at 'r' of "world", db should delete back to start of "world"
if m.ActiveBuffer().Lines[0] != "hello rld" {
t.Errorf("Line(0) = %q, want \"hello rld\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello rld" {
t.Errorf("Line(0) = %q, want \"hello rld\"", m.ActiveBuffer().Lines[0].String())
}
})
@ -691,8 +691,8 @@ func TestDeleteOperatorWithWordMotion(t *testing.T) {
m := getFinalModel(t, tm)
// cursor at 'w', db should delete "hello " back
if m.ActiveBuffer().Lines[0] != "world" {
t.Errorf("Line(0) = %q, want \"world\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "world" {
t.Errorf("Line(0) = %q, want \"world\"", m.ActiveBuffer().Lines[0].String())
}
})
@ -703,8 +703,8 @@ func TestDeleteOperatorWithWordMotion(t *testing.T) {
m := getFinalModel(t, tm)
// cursor at 'f' of "four", 2db should delete "two three "
if m.ActiveBuffer().Lines[0] != "one four" {
t.Errorf("Line(0) = %q, want \"one four\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "one four" {
t.Errorf("Line(0) = %q, want \"one four\"", m.ActiveBuffer().Lines[0].String())
}
})
@ -715,8 +715,8 @@ func TestDeleteOperatorWithWordMotion(t *testing.T) {
m := getFinalModel(t, tm)
// cursor at 'd' (last char), db should delete back to start of "world"
if m.ActiveBuffer().Lines[0] != "hello d" {
t.Errorf("Line(0) = %q, want \"hello d\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello d" {
t.Errorf("Line(0) = %q, want \"hello d\"", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -729,8 +729,8 @@ func TestDeleteOperatorWithLinePositionMotion(t *testing.T) {
sendKeys(tm, "d", "0")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello world" {
t.Errorf("Line(0) = %q, want \"hello world\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello world" {
t.Errorf("Line(0) = %q, want \"hello world\"", m.ActiveBuffer().Lines[0].String())
}
})
@ -740,8 +740,8 @@ func TestDeleteOperatorWithLinePositionMotion(t *testing.T) {
sendKeys(tm, "d", "0")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "world" {
t.Errorf("Line(0) = %q, want \"world\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "world" {
t.Errorf("Line(0) = %q, want \"world\"", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Col != 0 {
t.Errorf("CursorX() = %d, want 0", m.ActiveWindow().Cursor.Col)
@ -754,8 +754,8 @@ func TestDeleteOperatorWithLinePositionMotion(t *testing.T) {
sendKeys(tm, "d", "0")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "d" {
t.Errorf("Line(0) = %q, want \"d\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "d" {
t.Errorf("Line(0) = %q, want \"d\"", m.ActiveBuffer().Lines[0].String())
}
})
@ -765,8 +765,8 @@ func TestDeleteOperatorWithLinePositionMotion(t *testing.T) {
sendKeys(tm, "d", "0")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "lo world" {
t.Errorf("Line(0) = %q, want \"lo world\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "lo world" {
t.Errorf("Line(0) = %q, want \"lo world\"", m.ActiveBuffer().Lines[0].String())
}
})
@ -777,8 +777,8 @@ func TestDeleteOperatorWithLinePositionMotion(t *testing.T) {
sendKeys(tm, "d", "$")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want \"\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want \"\"", m.ActiveBuffer().Lines[0].String())
}
})
@ -788,8 +788,8 @@ func TestDeleteOperatorWithLinePositionMotion(t *testing.T) {
sendKeys(tm, "d", "$")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello " {
t.Errorf("Line(0) = %q, want \"hello \"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello " {
t.Errorf("Line(0) = %q, want \"hello \"", m.ActiveBuffer().Lines[0].String())
}
})
@ -799,8 +799,8 @@ func TestDeleteOperatorWithLinePositionMotion(t *testing.T) {
sendKeys(tm, "d", "$")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello worl" {
t.Errorf("Line(0) = %q, want \"hello worl\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello worl" {
t.Errorf("Line(0) = %q, want \"hello worl\"", m.ActiveBuffer().Lines[0].String())
}
})
@ -810,11 +810,11 @@ func TestDeleteOperatorWithLinePositionMotion(t *testing.T) {
sendKeys(tm, "d", "$")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello " {
t.Errorf("Line(0) = %q, want \"hello \"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello " {
t.Errorf("Line(0) = %q, want \"hello \"", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "second line" {
t.Errorf("Line(1) = %q, want \"second line\"", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "second line" {
t.Errorf("Line(1) = %q, want \"second line\"", m.ActiveBuffer().Lines[1].String())
}
if m.ActiveBuffer().LineCount() != 2 {
t.Errorf("LineCount() = %d, want 2", m.ActiveBuffer().LineCount())
@ -827,8 +827,8 @@ func TestDeleteOperatorWithLinePositionMotion(t *testing.T) {
sendKeys(tm, "d", "$")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want \"\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want \"\"", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().LineCount() != 2 {
t.Errorf("LineCount() = %d, want 2", m.ActiveBuffer().LineCount())
@ -843,8 +843,8 @@ func TestDeleteOperatorWithLinePositionMotion(t *testing.T) {
m := getFinalModel(t, tm)
// From col 0 to first non-whitespace (col 3, 'h') - deletes leading spaces
if m.ActiveBuffer().Lines[0] != "hello world" {
t.Errorf("Line(0) = %q, want \"hello world\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello world" {
t.Errorf("Line(0) = %q, want \"hello world\"", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Col != 0 {
t.Errorf("CursorX() = %d, want 0", m.ActiveWindow().Cursor.Col)
@ -858,8 +858,8 @@ func TestDeleteOperatorWithLinePositionMotion(t *testing.T) {
m := getFinalModel(t, tm)
// From col 1 to first non-whitespace (col 3, 'h') - deletes cols 1-2
if m.ActiveBuffer().Lines[0] != " hello world" {
t.Errorf("Line(0) = %q, want \" hello world\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != " hello world" {
t.Errorf("Line(0) = %q, want \" hello world\"", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Col != 1 {
t.Errorf("CursorX() = %d, want 1", m.ActiveWindow().Cursor.Col)
@ -874,8 +874,8 @@ func TestDeleteOperatorWithLinePositionMotion(t *testing.T) {
m := getFinalModel(t, tm)
// From col 6 ('l') back to col 3 ('h')
// Should delete "hel" leaving " lo world"
if m.ActiveBuffer().Lines[0] != " lo world" {
t.Errorf("Line(0) = %q, want \" lo world\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != " lo world" {
t.Errorf("Line(0) = %q, want \" lo world\"", m.ActiveBuffer().Lines[0].String())
}
})
@ -887,8 +887,8 @@ func TestDeleteOperatorWithLinePositionMotion(t *testing.T) {
m := getFinalModel(t, tm)
// From col 5 (' ') back to col 0 ('h')
// Should delete "hello" leaving " world"
if m.ActiveBuffer().Lines[0] != " world" {
t.Errorf("Line(0) = %q, want \" world\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != " world" {
t.Errorf("Line(0) = %q, want \" world\"", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -903,11 +903,11 @@ func TestDeleteOperatorWithJumpMotion(t *testing.T) {
if m.ActiveBuffer().LineCount() != 2 {
t.Errorf("LineCount() = %d, want 2", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "line 2" {
t.Errorf("Line(1) = %q, want 'line 2'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "line 2" {
t.Errorf("Line(1) = %q, want 'line 2'", m.ActiveBuffer().Lines[1].String())
}
})
@ -920,8 +920,8 @@ func TestDeleteOperatorWithJumpMotion(t *testing.T) {
if m.ActiveBuffer().LineCount() != 1 {
t.Errorf("LineCount() = %d, want 1", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
})
@ -934,11 +934,11 @@ func TestDeleteOperatorWithJumpMotion(t *testing.T) {
if m.ActiveBuffer().LineCount() != 2 {
t.Errorf("LineCount() = %d, want 2", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "line 2" {
t.Errorf("Line(1) = %q, want 'line 2'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "line 2" {
t.Errorf("Line(1) = %q, want 'line 2'", m.ActiveBuffer().Lines[1].String())
}
})
@ -962,11 +962,11 @@ func TestDeleteOperatorWithJumpMotion(t *testing.T) {
if m.ActiveBuffer().LineCount() != 2 {
t.Errorf("LineCount() = %d, want 2", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "line 4" {
t.Errorf("Line(0) = %q, want 'line 4'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line 4" {
t.Errorf("Line(0) = %q, want 'line 4'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "line 5" {
t.Errorf("Line(1) = %q, want 'line 5'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "line 5" {
t.Errorf("Line(1) = %q, want 'line 5'", m.ActiveBuffer().Lines[1].String())
}
})
@ -979,8 +979,8 @@ func TestDeleteOperatorWithJumpMotion(t *testing.T) {
if m.ActiveBuffer().LineCount() != 1 {
t.Errorf("LineCount() = %d, want 1", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
})
@ -993,11 +993,11 @@ func TestDeleteOperatorWithJumpMotion(t *testing.T) {
if m.ActiveBuffer().LineCount() != 2 {
t.Errorf("LineCount() = %d, want 2", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "line 2" {
t.Errorf("Line(0) = %q, want 'line 2'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line 2" {
t.Errorf("Line(0) = %q, want 'line 2'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "line 3" {
t.Errorf("Line(1) = %q, want 'line 3'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "line 3" {
t.Errorf("Line(1) = %q, want 'line 3'", m.ActiveBuffer().Lines[1].String())
}
})
@ -1021,8 +1021,8 @@ func TestDeleteOperatorWithJumpMotion(t *testing.T) {
if m.ActiveBuffer().LineCount() != 1 {
t.Errorf("LineCount() = %d, want 1", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
})
@ -1035,8 +1035,8 @@ func TestDeleteOperatorWithJumpMotion(t *testing.T) {
if m.ActiveBuffer().LineCount() != 1 {
t.Errorf("LineCount() = %d, want 1", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
})

View File

@ -19,14 +19,14 @@ func TestPasteLinewiseBasic(t *testing.T) {
if m.ActiveBuffer().LineCount() != 3 {
t.Errorf("LineCount() = %d, want 3", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "inserted" {
t.Errorf("Line(1) = %q, want 'inserted'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "inserted" {
t.Errorf("Line(1) = %q, want 'inserted'", m.ActiveBuffer().Lines[1].String())
}
if m.ActiveBuffer().Lines[2] != "line 2" {
t.Errorf("Line(2) = %q, want 'line 2'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "line 2" {
t.Errorf("Line(2) = %q, want 'line 2'", m.ActiveBuffer().Lines[2].String())
}
})
@ -56,8 +56,8 @@ func TestPasteLinewiseBasic(t *testing.T) {
if m.ActiveBuffer().LineCount() != 4 {
t.Errorf("LineCount() = %d, want 4", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[2] != "inserted" {
t.Errorf("Line(2) = %q, want 'inserted'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "inserted" {
t.Errorf("Line(2) = %q, want 'inserted'", m.ActiveBuffer().Lines[2].String())
}
if m.ActiveWindow().Cursor.Line != 2 {
t.Errorf("CursorY() = %d, want 2", m.ActiveWindow().Cursor.Line)
@ -76,8 +76,8 @@ func TestPasteLinewiseBasic(t *testing.T) {
if m.ActiveBuffer().LineCount() != 3 {
t.Errorf("LineCount() = %d, want 3", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[2] != "inserted" {
t.Errorf("Line(2) = %q, want 'inserted'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "inserted" {
t.Errorf("Line(2) = %q, want 'inserted'", m.ActiveBuffer().Lines[2].String())
}
})
}
@ -95,20 +95,20 @@ func TestPasteLinewiseMultipleLines(t *testing.T) {
if m.ActiveBuffer().LineCount() != 5 {
t.Errorf("LineCount() = %d, want 5", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "first" {
t.Errorf("Line(1) = %q, want 'first'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "first" {
t.Errorf("Line(1) = %q, want 'first'", m.ActiveBuffer().Lines[1].String())
}
if m.ActiveBuffer().Lines[2] != "second" {
t.Errorf("Line(2) = %q, want 'second'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "second" {
t.Errorf("Line(2) = %q, want 'second'", m.ActiveBuffer().Lines[2].String())
}
if m.ActiveBuffer().Lines[3] != "third" {
t.Errorf("Line(3) = %q, want 'third'", m.ActiveBuffer().Lines[3])
if m.ActiveBuffer().Lines[3].String() != "third" {
t.Errorf("Line(3) = %q, want 'third'", m.ActiveBuffer().Lines[3].String())
}
if m.ActiveBuffer().Lines[4] != "line 2" {
t.Errorf("Line(4) = %q, want 'line 2'", m.ActiveBuffer().Lines[4])
if m.ActiveBuffer().Lines[4].String() != "line 2" {
t.Errorf("Line(4) = %q, want 'line 2'", m.ActiveBuffer().Lines[4].String())
}
})
@ -141,14 +141,14 @@ func TestPasteLinewiseWithCount(t *testing.T) {
t.Errorf("LineCount() = %d, want 4", m.ActiveBuffer().LineCount())
}
// Both "inserted" lines should appear after line 1
if m.ActiveBuffer().Lines[1] != "inserted" {
t.Errorf("Line(1) = %q, want 'inserted'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "inserted" {
t.Errorf("Line(1) = %q, want 'inserted'", m.ActiveBuffer().Lines[1].String())
}
if m.ActiveBuffer().Lines[2] != "inserted" {
t.Errorf("Line(2) = %q, want 'inserted'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "inserted" {
t.Errorf("Line(2) = %q, want 'inserted'", m.ActiveBuffer().Lines[2].String())
}
if m.ActiveBuffer().Lines[3] != "line 2" {
t.Errorf("Line(3) = %q, want 'line 2'", m.ActiveBuffer().Lines[3])
if m.ActiveBuffer().Lines[3].String() != "line 2" {
t.Errorf("Line(3) = %q, want 'line 2'", m.ActiveBuffer().Lines[3].String())
}
})
@ -165,8 +165,8 @@ func TestPasteLinewiseWithCount(t *testing.T) {
t.Errorf("LineCount() = %d, want 4", m.ActiveBuffer().LineCount())
}
for i := 1; i <= 3; i++ {
if m.ActiveBuffer().Lines[i] != "pasted" {
t.Errorf("Line(%d) = %q, want 'pasted'", i, m.ActiveBuffer().Lines[i])
if m.ActiveBuffer().Lines[i].String() != "pasted" {
t.Errorf("Line(%d) = %q, want 'pasted'", i, m.ActiveBuffer().Lines[i].String())
}
}
})
@ -184,20 +184,20 @@ func TestPasteLinewiseWithCount(t *testing.T) {
if m.ActiveBuffer().LineCount() != 5 {
t.Errorf("LineCount() = %d, want 5", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "original" {
t.Errorf("Line(0) = %q, want 'original'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "original" {
t.Errorf("Line(0) = %q, want 'original'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "first" {
t.Errorf("Line(1) = %q, want 'first'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "first" {
t.Errorf("Line(1) = %q, want 'first'", m.ActiveBuffer().Lines[1].String())
}
if m.ActiveBuffer().Lines[2] != "second" {
t.Errorf("Line(2) = %q, want 'second'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "second" {
t.Errorf("Line(2) = %q, want 'second'", m.ActiveBuffer().Lines[2].String())
}
if m.ActiveBuffer().Lines[3] != "first" {
t.Errorf("Line(3) = %q, want 'first'", m.ActiveBuffer().Lines[3])
if m.ActiveBuffer().Lines[3].String() != "first" {
t.Errorf("Line(3) = %q, want 'first'", m.ActiveBuffer().Lines[3].String())
}
if m.ActiveBuffer().Lines[4] != "second" {
t.Errorf("Line(4) = %q, want 'second'", m.ActiveBuffer().Lines[4])
if m.ActiveBuffer().Lines[4].String() != "second" {
t.Errorf("Line(4) = %q, want 'second'", m.ActiveBuffer().Lines[4].String())
}
})
@ -231,14 +231,14 @@ func TestPasteBeforeLinewiseBasic(t *testing.T) {
if m.ActiveBuffer().LineCount() != 3 {
t.Errorf("LineCount() = %d, want 3", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "inserted" {
t.Errorf("Line(1) = %q, want 'inserted'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "inserted" {
t.Errorf("Line(1) = %q, want 'inserted'", m.ActiveBuffer().Lines[1].String())
}
if m.ActiveBuffer().Lines[2] != "line 2" {
t.Errorf("Line(2) = %q, want 'line 2'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "line 2" {
t.Errorf("Line(2) = %q, want 'line 2'", m.ActiveBuffer().Lines[2].String())
}
})
@ -268,11 +268,11 @@ func TestPasteBeforeLinewiseBasic(t *testing.T) {
if m.ActiveBuffer().LineCount() != 3 {
t.Errorf("LineCount() = %d, want 3", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "inserted" {
t.Errorf("Line(0) = %q, want 'inserted'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "inserted" {
t.Errorf("Line(0) = %q, want 'inserted'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "line 1" {
t.Errorf("Line(1) = %q, want 'line 1'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "line 1" {
t.Errorf("Line(1) = %q, want 'line 1'", m.ActiveBuffer().Lines[1].String())
}
if m.ActiveWindow().Cursor.Line != 0 {
t.Errorf("CursorY() = %d, want 0", m.ActiveWindow().Cursor.Line)
@ -291,11 +291,11 @@ func TestPasteBeforeLinewiseBasic(t *testing.T) {
if m.ActiveBuffer().LineCount() != 4 {
t.Errorf("LineCount() = %d, want 4", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[1] != "inserted" {
t.Errorf("Line(1) = %q, want 'inserted'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "inserted" {
t.Errorf("Line(1) = %q, want 'inserted'", m.ActiveBuffer().Lines[1].String())
}
if m.ActiveBuffer().Lines[2] != "line 2" {
t.Errorf("Line(2) = %q, want 'line 2'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "line 2" {
t.Errorf("Line(2) = %q, want 'line 2'", m.ActiveBuffer().Lines[2].String())
}
})
}
@ -313,20 +313,20 @@ func TestPasteBeforeLinewiseMultipleLines(t *testing.T) {
if m.ActiveBuffer().LineCount() != 5 {
t.Errorf("LineCount() = %d, want 5", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "first" {
t.Errorf("Line(1) = %q, want 'first'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "first" {
t.Errorf("Line(1) = %q, want 'first'", m.ActiveBuffer().Lines[1].String())
}
if m.ActiveBuffer().Lines[2] != "second" {
t.Errorf("Line(2) = %q, want 'second'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "second" {
t.Errorf("Line(2) = %q, want 'second'", m.ActiveBuffer().Lines[2].String())
}
if m.ActiveBuffer().Lines[3] != "third" {
t.Errorf("Line(3) = %q, want 'third'", m.ActiveBuffer().Lines[3])
if m.ActiveBuffer().Lines[3].String() != "third" {
t.Errorf("Line(3) = %q, want 'third'", m.ActiveBuffer().Lines[3].String())
}
if m.ActiveBuffer().Lines[4] != "line 2" {
t.Errorf("Line(4) = %q, want 'line 2'", m.ActiveBuffer().Lines[4])
if m.ActiveBuffer().Lines[4].String() != "line 2" {
t.Errorf("Line(4) = %q, want 'line 2'", m.ActiveBuffer().Lines[4].String())
}
})
@ -359,14 +359,14 @@ func TestPasteBeforeLinewiseWithCount(t *testing.T) {
t.Errorf("LineCount() = %d, want 4", m.ActiveBuffer().LineCount())
}
// Both "inserted" lines should appear before line 2
if m.ActiveBuffer().Lines[1] != "inserted" {
t.Errorf("Line(1) = %q, want 'inserted'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "inserted" {
t.Errorf("Line(1) = %q, want 'inserted'", m.ActiveBuffer().Lines[1].String())
}
if m.ActiveBuffer().Lines[2] != "inserted" {
t.Errorf("Line(2) = %q, want 'inserted'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "inserted" {
t.Errorf("Line(2) = %q, want 'inserted'", m.ActiveBuffer().Lines[2].String())
}
if m.ActiveBuffer().Lines[3] != "line 2" {
t.Errorf("Line(3) = %q, want 'line 2'", m.ActiveBuffer().Lines[3])
if m.ActiveBuffer().Lines[3].String() != "line 2" {
t.Errorf("Line(3) = %q, want 'line 2'", m.ActiveBuffer().Lines[3].String())
}
})
@ -383,12 +383,12 @@ func TestPasteBeforeLinewiseWithCount(t *testing.T) {
t.Errorf("LineCount() = %d, want 4", m.ActiveBuffer().LineCount())
}
for i := 0; i < 3; i++ {
if m.ActiveBuffer().Lines[i] != "pasted" {
t.Errorf("Line(%d) = %q, want 'pasted'", i, m.ActiveBuffer().Lines[i])
if m.ActiveBuffer().Lines[i].String() != "pasted" {
t.Errorf("Line(%d) = %q, want 'pasted'", i, m.ActiveBuffer().Lines[i].String())
}
}
if m.ActiveBuffer().Lines[3] != "original" {
t.Errorf("Line(3) = %q, want 'original'", m.ActiveBuffer().Lines[3])
if m.ActiveBuffer().Lines[3].String() != "original" {
t.Errorf("Line(3) = %q, want 'original'", m.ActiveBuffer().Lines[3].String())
}
})
@ -405,20 +405,20 @@ func TestPasteBeforeLinewiseWithCount(t *testing.T) {
if m.ActiveBuffer().LineCount() != 5 {
t.Errorf("LineCount() = %d, want 5", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "first" {
t.Errorf("Line(0) = %q, want 'first'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "first" {
t.Errorf("Line(0) = %q, want 'first'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "second" {
t.Errorf("Line(1) = %q, want 'second'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "second" {
t.Errorf("Line(1) = %q, want 'second'", m.ActiveBuffer().Lines[1].String())
}
if m.ActiveBuffer().Lines[2] != "first" {
t.Errorf("Line(2) = %q, want 'first'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "first" {
t.Errorf("Line(2) = %q, want 'first'", m.ActiveBuffer().Lines[2].String())
}
if m.ActiveBuffer().Lines[3] != "second" {
t.Errorf("Line(3) = %q, want 'second'", m.ActiveBuffer().Lines[3])
if m.ActiveBuffer().Lines[3].String() != "second" {
t.Errorf("Line(3) = %q, want 'second'", m.ActiveBuffer().Lines[3].String())
}
if m.ActiveBuffer().Lines[4] != "original" {
t.Errorf("Line(4) = %q, want 'original'", m.ActiveBuffer().Lines[4])
if m.ActiveBuffer().Lines[4].String() != "original" {
t.Errorf("Line(4) = %q, want 'original'", m.ActiveBuffer().Lines[4].String())
}
})
@ -450,11 +450,11 @@ func TestPasteBeforeLinewiseEdgeCases(t *testing.T) {
if m.ActiveBuffer().LineCount() != 2 {
t.Errorf("LineCount() = %d, want 2", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "inserted" {
t.Errorf("Line(0) = %q, want 'inserted'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "inserted" {
t.Errorf("Line(0) = %q, want 'inserted'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "only line" {
t.Errorf("Line(1) = %q, want 'only line'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "only line" {
t.Errorf("Line(1) = %q, want 'only line'", m.ActiveBuffer().Lines[1].String())
}
})
@ -481,11 +481,11 @@ func TestPasteBeforeLinewiseEdgeCases(t *testing.T) {
sendKeys(tm, "P")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != " indented" {
t.Errorf("Line(0) = %q, want ' indented'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != " indented" {
t.Errorf("Line(0) = %q, want ' indented'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "\ttabbed" {
t.Errorf("Line(1) = %q, want '\\ttabbed'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "\ttabbed" {
t.Errorf("Line(1) = %q, want '\\ttabbed'", m.ActiveBuffer().Lines[1].String())
}
})
@ -502,8 +502,8 @@ func TestPasteBeforeLinewiseEdgeCases(t *testing.T) {
t.Errorf("LineCount() = %d, want 11", m.ActiveBuffer().LineCount())
}
// Original should be at the end
if m.ActiveBuffer().Lines[10] != "original" {
t.Errorf("Line(10) = %q, want 'original'", m.ActiveBuffer().Lines[10])
if m.ActiveBuffer().Lines[10].String() != "original" {
t.Errorf("Line(10) = %q, want 'original'", m.ActiveBuffer().Lines[10].String())
}
})
}
@ -521,11 +521,11 @@ func TestPasteLinewiseEdgeCases(t *testing.T) {
if m.ActiveBuffer().LineCount() != 2 {
t.Errorf("LineCount() = %d, want 2", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "only line" {
t.Errorf("Line(0) = %q, want 'only line'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "only line" {
t.Errorf("Line(0) = %q, want 'only line'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "inserted" {
t.Errorf("Line(1) = %q, want 'inserted'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "inserted" {
t.Errorf("Line(1) = %q, want 'inserted'", m.ActiveBuffer().Lines[1].String())
}
})
@ -552,11 +552,11 @@ func TestPasteLinewiseEdgeCases(t *testing.T) {
sendKeys(tm, "p")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[1] != " indented" {
t.Errorf("Line(1) = %q, want ' indented'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != " indented" {
t.Errorf("Line(1) = %q, want ' indented'", m.ActiveBuffer().Lines[1].String())
}
if m.ActiveBuffer().Lines[2] != "\ttabbed" {
t.Errorf("Line(2) = %q, want '\\ttabbed'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "\ttabbed" {
t.Errorf("Line(2) = %q, want '\\ttabbed'", m.ActiveBuffer().Lines[2].String())
}
})
@ -590,8 +590,8 @@ func TestPasteCharwiseBasic(t *testing.T) {
m := getFinalModel(t, tm)
// Should insert after 'o': "helloXYZ world"
if m.ActiveBuffer().Lines[0] != "helloXYZ world" {
t.Errorf("Line(0) = %q, want 'helloXYZ world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "helloXYZ world" {
t.Errorf("Line(0) = %q, want 'helloXYZ world'", m.ActiveBuffer().Lines[0].String())
}
})
@ -604,8 +604,8 @@ func TestPasteCharwiseBasic(t *testing.T) {
sendKeys(tm, "p")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hXello" {
t.Errorf("Line(0) = %q, want 'hXello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hXello" {
t.Errorf("Line(0) = %q, want 'hXello'", m.ActiveBuffer().Lines[0].String())
}
})
@ -618,8 +618,8 @@ func TestPasteCharwiseBasic(t *testing.T) {
sendKeys(tm, "p")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello!" {
t.Errorf("Line(0) = %q, want 'hello!'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello!" {
t.Errorf("Line(0) = %q, want 'hello!'", m.ActiveBuffer().Lines[0].String())
}
})
@ -632,8 +632,8 @@ func TestPasteCharwiseBasic(t *testing.T) {
sendKeys(tm, "p")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "text" {
t.Errorf("Line(0) = %q, want 'text'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "text" {
t.Errorf("Line(0) = %q, want 'text'", m.ActiveBuffer().Lines[0].String())
}
})
@ -662,8 +662,8 @@ func TestPasteCharwiseWithCount(t *testing.T) {
sendKeys(tm, "2", "p")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hXXello" {
t.Errorf("Line(0) = %q, want 'hXXello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hXXello" {
t.Errorf("Line(0) = %q, want 'hXXello'", m.ActiveBuffer().Lines[0].String())
}
})
@ -676,8 +676,8 @@ func TestPasteCharwiseWithCount(t *testing.T) {
sendKeys(tm, "3", "p")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "start--- end" {
t.Errorf("Line(0) = %q, want 'start--- end'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "start--- end" {
t.Errorf("Line(0) = %q, want 'start--- end'", m.ActiveBuffer().Lines[0].String())
}
})
@ -690,8 +690,8 @@ func TestPasteCharwiseWithCount(t *testing.T) {
sendKeys(tm, "2", "p")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "aXYXYb" {
t.Errorf("Line(0) = %q, want 'aXYXYb'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "aXYXYb" {
t.Errorf("Line(0) = %q, want 'aXYXYb'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -742,8 +742,8 @@ func TestPasteBeforeCharwiseBasic(t *testing.T) {
m := getFinalModel(t, tm)
// Should insert before space: "helloXYZ world"
if m.ActiveBuffer().Lines[0] != "helloXYZ world" {
t.Errorf("Line(0) = %q, want 'helloXYZ world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "helloXYZ world" {
t.Errorf("Line(0) = %q, want 'helloXYZ world'", m.ActiveBuffer().Lines[0].String())
}
})
@ -756,8 +756,8 @@ func TestPasteBeforeCharwiseBasic(t *testing.T) {
sendKeys(tm, "P")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "Xhello" {
t.Errorf("Line(0) = %q, want 'Xhello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "Xhello" {
t.Errorf("Line(0) = %q, want 'Xhello'", m.ActiveBuffer().Lines[0].String())
}
})
@ -770,8 +770,8 @@ func TestPasteBeforeCharwiseBasic(t *testing.T) {
sendKeys(tm, "P")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hellXo" {
t.Errorf("Line(0) = %q, want 'hellXo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hellXo" {
t.Errorf("Line(0) = %q, want 'hellXo'", m.ActiveBuffer().Lines[0].String())
}
})
@ -784,8 +784,8 @@ func TestPasteBeforeCharwiseBasic(t *testing.T) {
sendKeys(tm, "P")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "text" {
t.Errorf("Line(0) = %q, want 'text'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "text" {
t.Errorf("Line(0) = %q, want 'text'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -800,8 +800,8 @@ func TestPasteBeforeCharwiseWithCount(t *testing.T) {
sendKeys(tm, "2", "P")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "heXXllo" {
t.Errorf("Line(0) = %q, want 'heXXllo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "heXXllo" {
t.Errorf("Line(0) = %q, want 'heXXllo'", m.ActiveBuffer().Lines[0].String())
}
})
@ -814,8 +814,8 @@ func TestPasteBeforeCharwiseWithCount(t *testing.T) {
sendKeys(tm, "3", "P")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "a---b" {
t.Errorf("Line(0) = %q, want 'a---b'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "a---b" {
t.Errorf("Line(0) = %q, want 'a---b'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -838,11 +838,11 @@ func TestPasteCharwiseMultiLine(t *testing.T) {
if m.ActiveBuffer().LineCount() != 2 {
t.Errorf("LineCount() = %d, want 2", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "heAAA" {
t.Errorf("Line(0) = %q, want 'heAAA'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "heAAA" {
t.Errorf("Line(0) = %q, want 'heAAA'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "BBBllo" {
t.Errorf("Line(1) = %q, want 'BBBllo'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "BBBllo" {
t.Errorf("Line(1) = %q, want 'BBBllo'", m.ActiveBuffer().Lines[1].String())
}
})
@ -859,14 +859,14 @@ func TestPasteCharwiseMultiLine(t *testing.T) {
if m.ActiveBuffer().LineCount() != 3 {
t.Errorf("LineCount() = %d, want 3", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "teAAA" {
t.Errorf("Line(0) = %q, want 'teAAA'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "teAAA" {
t.Errorf("Line(0) = %q, want 'teAAA'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "BBB" {
t.Errorf("Line(1) = %q, want 'BBB'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "BBB" {
t.Errorf("Line(1) = %q, want 'BBB'", m.ActiveBuffer().Lines[1].String())
}
if m.ActiveBuffer().Lines[2] != "CCCst" {
t.Errorf("Line(2) = %q, want 'CCCst'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "CCCst" {
t.Errorf("Line(2) = %q, want 'CCCst'", m.ActiveBuffer().Lines[2].String())
}
})
@ -880,11 +880,11 @@ func TestPasteCharwiseMultiLine(t *testing.T) {
m := getFinalModel(t, tm)
// After 'h': "hX\nYello"
if m.ActiveBuffer().Lines[0] != "hX" {
t.Errorf("Line(0) = %q, want 'hX'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hX" {
t.Errorf("Line(0) = %q, want 'hX'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "Yello" {
t.Errorf("Line(1) = %q, want 'Yello'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "Yello" {
t.Errorf("Line(1) = %q, want 'Yello'", m.ActiveBuffer().Lines[1].String())
}
})
@ -898,11 +898,11 @@ func TestPasteCharwiseMultiLine(t *testing.T) {
m := getFinalModel(t, tm)
// After 'o': "helloX\nY"
if m.ActiveBuffer().Lines[0] != "helloX" {
t.Errorf("Line(0) = %q, want 'helloX'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "helloX" {
t.Errorf("Line(0) = %q, want 'helloX'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "Y" {
t.Errorf("Line(1) = %q, want 'Y'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "Y" {
t.Errorf("Line(1) = %q, want 'Y'", m.ActiveBuffer().Lines[1].String())
}
})
@ -915,11 +915,11 @@ func TestPasteCharwiseMultiLine(t *testing.T) {
sendKeys(tm, "p")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "AAA" {
t.Errorf("Line(0) = %q, want 'AAA'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "AAA" {
t.Errorf("Line(0) = %q, want 'AAA'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "BBB" {
t.Errorf("Line(1) = %q, want 'BBB'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "BBB" {
t.Errorf("Line(1) = %q, want 'BBB'", m.ActiveBuffer().Lines[1].String())
}
})
@ -933,11 +933,11 @@ func TestPasteCharwiseMultiLine(t *testing.T) {
m := getFinalModel(t, tm)
// Before 'l': "heX\nYllo"
if m.ActiveBuffer().Lines[0] != "heX" {
t.Errorf("Line(0) = %q, want 'heX'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "heX" {
t.Errorf("Line(0) = %q, want 'heX'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "Yllo" {
t.Errorf("Line(1) = %q, want 'Yllo'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "Yllo" {
t.Errorf("Line(1) = %q, want 'Yllo'", m.ActiveBuffer().Lines[1].String())
}
})
@ -951,11 +951,11 @@ func TestPasteCharwiseMultiLine(t *testing.T) {
m := getFinalModel(t, tm)
// Before 'h': "X\nYhello"
if m.ActiveBuffer().Lines[0] != "X" {
t.Errorf("Line(0) = %q, want 'X'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "X" {
t.Errorf("Line(0) = %q, want 'X'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "Yhello" {
t.Errorf("Line(1) = %q, want 'Yhello'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "Yhello" {
t.Errorf("Line(1) = %q, want 'Yhello'", m.ActiveBuffer().Lines[1].String())
}
})
@ -972,14 +972,14 @@ func TestPasteCharwiseMultiLine(t *testing.T) {
if m.ActiveBuffer().LineCount() != 3 {
t.Errorf("LineCount() = %d, want 3", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "teA" {
t.Errorf("Line(0) = %q, want 'teA'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "teA" {
t.Errorf("Line(0) = %q, want 'teA'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "BA" {
t.Errorf("Line(1) = %q, want 'BA'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "BA" {
t.Errorf("Line(1) = %q, want 'BA'", m.ActiveBuffer().Lines[1].String())
}
if m.ActiveBuffer().Lines[2] != "Bst" {
t.Errorf("Line(2) = %q, want 'Bst'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "Bst" {
t.Errorf("Line(2) = %q, want 'Bst'", m.ActiveBuffer().Lines[2].String())
}
})
@ -1030,8 +1030,8 @@ func TestPasteBlockwiseBasic(t *testing.T) {
m := getFinalModel(t, tm)
// Current implementation errors - lines should be unchanged
if m.ActiveBuffer().Lines[0] != "aaaa" {
t.Errorf("Line(0) = %q, want 'aaaa' (unchanged due to error)", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "aaaa" {
t.Errorf("Line(0) = %q, want 'aaaa' (unchanged due to error)", m.ActiveBuffer().Lines[0].String())
}
})
@ -1045,8 +1045,8 @@ func TestPasteBlockwiseBasic(t *testing.T) {
m := getFinalModel(t, tm)
// Current implementation errors - lines should be unchanged
if m.ActiveBuffer().Lines[0] != "aaaa" {
t.Errorf("Line(0) = %q, want 'aaaa' (unchanged due to error)", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "aaaa" {
t.Errorf("Line(0) = %q, want 'aaaa' (unchanged due to error)", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -1065,8 +1065,8 @@ func TestPasteCharwiseEdgeCases(t *testing.T) {
sendKeys(tm, "p")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello" {
t.Errorf("Line(0) = %q, want 'hello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello" {
t.Errorf("Line(0) = %q, want 'hello'", m.ActiveBuffer().Lines[0].String())
}
})
@ -1079,8 +1079,8 @@ func TestPasteCharwiseEdgeCases(t *testing.T) {
sendKeys(tm, "p")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello" {
t.Errorf("Line(0) = %q, want 'hello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello" {
t.Errorf("Line(0) = %q, want 'hello'", m.ActiveBuffer().Lines[0].String())
}
})
@ -1093,8 +1093,8 @@ func TestPasteCharwiseEdgeCases(t *testing.T) {
sendKeys(tm, "p")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "a\tb" {
t.Errorf("Line(0) = %q, want 'a\\tb'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "a\tb" {
t.Errorf("Line(0) = %q, want 'a\\tb'", m.ActiveBuffer().Lines[0].String())
}
})
@ -1107,8 +1107,8 @@ func TestPasteCharwiseEdgeCases(t *testing.T) {
sendKeys(tm, "p")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "a b" {
t.Errorf("Line(0) = %q, want 'a b'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "a b" {
t.Errorf("Line(0) = %q, want 'a b'", m.ActiveBuffer().Lines[0].String())
}
})
@ -1121,8 +1121,8 @@ func TestPasteCharwiseEdgeCases(t *testing.T) {
sendKeys(tm, "p")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != " X " {
t.Errorf("Line(0) = %q, want ' X '", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != " X " {
t.Errorf("Line(0) = %q, want ' X '", m.ActiveBuffer().Lines[0].String())
}
})
@ -1135,8 +1135,8 @@ func TestPasteCharwiseEdgeCases(t *testing.T) {
sendKeys(tm, "P")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello" {
t.Errorf("Line(0) = %q, want 'hello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello" {
t.Errorf("Line(0) = %q, want 'hello'", m.ActiveBuffer().Lines[0].String())
}
})
@ -1149,8 +1149,8 @@ func TestPasteCharwiseEdgeCases(t *testing.T) {
sendKeys(tm, "1", "0", "p") // 10p
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "aXXXXXXXXXXb" {
t.Errorf("Line(0) = %q, want 'aXXXXXXXXXXb'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "aXXXXXXXXXXb" {
t.Errorf("Line(0) = %q, want 'aXXXXXXXXXXb'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -1170,8 +1170,8 @@ func TestYankThenPasteCharwise(t *testing.T) {
sendKeys(tm, "p") // paste
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello worldhello " {
t.Errorf("Line(0) = %q, want 'hello worldhello '", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello worldhello " {
t.Errorf("Line(0) = %q, want 'hello worldhello '", m.ActiveBuffer().Lines[0].String())
}
})
@ -1185,8 +1185,8 @@ func TestYankThenPasteCharwise(t *testing.T) {
sendKeys(tm, "p") // paste
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello worldhello" {
t.Errorf("Line(0) = %q, want 'hello worldhello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello worldhello" {
t.Errorf("Line(0) = %q, want 'hello worldhello'", m.ActiveBuffer().Lines[0].String())
}
})
@ -1200,8 +1200,8 @@ func TestYankThenPasteCharwise(t *testing.T) {
sendKeys(tm, "p") // paste
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello worldhel" {
t.Errorf("Line(0) = %q, want 'hello worldhel'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello worldhel" {
t.Errorf("Line(0) = %q, want 'hello worldhel'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -1226,8 +1226,8 @@ func TestVisualModePasteCharwise(t *testing.T) {
sendKeys(tm, "v", "l", "l", "l", "l", "p") // select "hello", paste
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "REPLACED world" {
t.Errorf("Line(0) = %q, want 'REPLACED world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "REPLACED world" {
t.Errorf("Line(0) = %q, want 'REPLACED world'", m.ActiveBuffer().Lines[0].String())
}
})
@ -1240,8 +1240,8 @@ func TestVisualModePasteCharwise(t *testing.T) {
sendKeys(tm, "v", "p") // select "h", paste
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "Xello world" {
t.Errorf("Line(0) = %q, want 'Xello world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "Xello world" {
t.Errorf("Line(0) = %q, want 'Xello world'", m.ActiveBuffer().Lines[0].String())
}
})
@ -1254,8 +1254,8 @@ func TestVisualModePasteCharwise(t *testing.T) {
sendKeys(tm, "v", "e", "p") // select "world", paste
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello EARTH goodbye" {
t.Errorf("Line(0) = %q, want 'hello EARTH goodbye'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello EARTH goodbye" {
t.Errorf("Line(0) = %q, want 'hello EARTH goodbye'", m.ActiveBuffer().Lines[0].String())
}
})
@ -1268,8 +1268,8 @@ func TestVisualModePasteCharwise(t *testing.T) {
sendKeys(tm, "v", "$", "p") // select "world", paste
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello universe" {
t.Errorf("Line(0) = %q, want 'hello universe'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello universe" {
t.Errorf("Line(0) = %q, want 'hello universe'", m.ActiveBuffer().Lines[0].String())
}
})
@ -1282,8 +1282,8 @@ func TestVisualModePasteCharwise(t *testing.T) {
sendKeys(tm, "v", "l", "l", "l", "l", "p") // select "hello", paste empty
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != " world" {
t.Errorf("Line(0) = %q, want ' world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != " world" {
t.Errorf("Line(0) = %q, want ' world'", m.ActiveBuffer().Lines[0].String())
}
})
@ -1303,8 +1303,8 @@ func TestVisualModePasteCharwise(t *testing.T) {
m := getFinalModel(t, tm)
// Should join: "line " + "REPLACED" + "two"
if m.ActiveBuffer().Lines[0] != "line REPLACEDtwo" {
t.Errorf("Line(0) = %q, want 'line REPLACEDtwo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line REPLACEDtwo" {
t.Errorf("Line(0) = %q, want 'line REPLACEDtwo'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().LineCount() != 2 {
t.Errorf("LineCount() = %d, want 2", m.ActiveBuffer().LineCount())
@ -1359,8 +1359,8 @@ func TestVisualModePasteCharwise(t *testing.T) {
m := getFinalModel(t, tm)
// Linewise register content is pasted inline replacing the selection
if m.ActiveBuffer().Lines[0] != "NEW LINE world" {
t.Errorf("Line(0) = %q, want 'NEW LINE world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "NEW LINE world" {
t.Errorf("Line(0) = %q, want 'NEW LINE world'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -1382,8 +1382,8 @@ func TestVisualLinePaste(t *testing.T) {
if m.ActiveBuffer().LineCount() != 3 {
t.Errorf("LineCount() = %d, want 3", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[1] != "REPLACED" {
t.Errorf("Line(1) = %q, want 'REPLACED'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "REPLACED" {
t.Errorf("Line(1) = %q, want 'REPLACED'", m.ActiveBuffer().Lines[1].String())
}
})
@ -1399,8 +1399,8 @@ func TestVisualLinePaste(t *testing.T) {
if m.ActiveBuffer().LineCount() != 3 {
t.Errorf("LineCount() = %d, want 3", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[1] != "NEW LINE" {
t.Errorf("Line(1) = %q, want 'NEW LINE'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "NEW LINE" {
t.Errorf("Line(1) = %q, want 'NEW LINE'", m.ActiveBuffer().Lines[1].String())
}
})
@ -1416,14 +1416,14 @@ func TestVisualLinePaste(t *testing.T) {
if m.ActiveBuffer().LineCount() != 3 {
t.Errorf("LineCount() = %d, want 3", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "line one" {
t.Errorf("Line(0) = %q, want 'line one'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line one" {
t.Errorf("Line(0) = %q, want 'line one'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "REPLACED" {
t.Errorf("Line(1) = %q, want 'REPLACED'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "REPLACED" {
t.Errorf("Line(1) = %q, want 'REPLACED'", m.ActiveBuffer().Lines[1].String())
}
if m.ActiveBuffer().Lines[2] != "line four" {
t.Errorf("Line(2) = %q, want 'line four'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "line four" {
t.Errorf("Line(2) = %q, want 'line four'", m.ActiveBuffer().Lines[2].String())
}
})
@ -1439,17 +1439,17 @@ func TestVisualLinePaste(t *testing.T) {
if m.ActiveBuffer().LineCount() != 4 {
t.Errorf("LineCount() = %d, want 4", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "line one" {
t.Errorf("Line(0) = %q, want 'line one'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line one" {
t.Errorf("Line(0) = %q, want 'line one'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "NEW A" {
t.Errorf("Line(1) = %q, want 'NEW A'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "NEW A" {
t.Errorf("Line(1) = %q, want 'NEW A'", m.ActiveBuffer().Lines[1].String())
}
if m.ActiveBuffer().Lines[2] != "NEW B" {
t.Errorf("Line(2) = %q, want 'NEW B'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "NEW B" {
t.Errorf("Line(2) = %q, want 'NEW B'", m.ActiveBuffer().Lines[2].String())
}
if m.ActiveBuffer().Lines[3] != "line four" {
t.Errorf("Line(3) = %q, want 'line four'", m.ActiveBuffer().Lines[3])
if m.ActiveBuffer().Lines[3].String() != "line four" {
t.Errorf("Line(3) = %q, want 'line four'", m.ActiveBuffer().Lines[3].String())
}
})
@ -1465,11 +1465,11 @@ func TestVisualLinePaste(t *testing.T) {
if m.ActiveBuffer().LineCount() != 2 {
t.Errorf("LineCount() = %d, want 2", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "FIRST" {
t.Errorf("Line(0) = %q, want 'FIRST'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "FIRST" {
t.Errorf("Line(0) = %q, want 'FIRST'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "line two" {
t.Errorf("Line(1) = %q, want 'line two'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "line two" {
t.Errorf("Line(1) = %q, want 'line two'", m.ActiveBuffer().Lines[1].String())
}
})
@ -1485,11 +1485,11 @@ func TestVisualLinePaste(t *testing.T) {
if m.ActiveBuffer().LineCount() != 2 {
t.Errorf("LineCount() = %d, want 2", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "line one" {
t.Errorf("Line(0) = %q, want 'line one'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line one" {
t.Errorf("Line(0) = %q, want 'line one'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "LAST" {
t.Errorf("Line(1) = %q, want 'LAST'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "LAST" {
t.Errorf("Line(1) = %q, want 'LAST'", m.ActiveBuffer().Lines[1].String())
}
})
@ -1552,6 +1552,46 @@ func TestVisualPasteRegisterBehavior(t *testing.T) {
t.Errorf("register type = %v, want LinewiseRegister", reg.Type)
}
})
t.Run("vP does not put deleted text into register", func(t *testing.T) {
tm := newTestModel(t,
WithLines([]string{"hello world"}),
WithCursorPos(core.Position{Line: 0, Col: 0}),
WithRegister('"', core.CharwiseRegister, []string{"NEW"}),
)
sendKeys(tm, "v", "l", "l", "l", "l", "P") // select "hello", paste "NEW"
m := getFinalModel(t, tm)
// After visual paste, the deleted "hello" should be in the register
reg, ok := m.GetRegister('"')
if !ok {
t.Fatal("unnamed register not found")
}
if len(reg.Content) != 1 || reg.Content[0] != "NEW" {
t.Errorf("register content = %q, want 'NEW'", reg.Content)
}
})
t.Run("VP does not put deleted line into register", func(t *testing.T) {
tm := newTestModel(t,
WithLines([]string{"line one", "line two"}),
WithCursorPos(core.Position{Line: 0, Col: 0}),
WithRegister('"', core.LinewiseRegister, []string{"REPLACED"}),
)
sendKeys(tm, "V", "P")
m := getFinalModel(t, tm)
reg, ok := m.GetRegister('"')
if !ok {
t.Fatal("unnamed register not found")
}
if len(reg.Content) != 1 || reg.Content[0] != "REPLACED" {
t.Errorf("register content = %q, want 'REPLACED'", reg.Content)
}
if reg.Type != core.LinewiseRegister {
t.Errorf("register type = %v, want LinewiseRegister", reg.Type)
}
})
}
func TestVisualPasteEdgeCases(t *testing.T) {
@ -1568,8 +1608,8 @@ func TestVisualPasteEdgeCases(t *testing.T) {
sendKeys(tm, "v", "p")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "NEW" {
t.Errorf("Line(0) = %q, want 'NEW'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "NEW" {
t.Errorf("Line(0) = %q, want 'NEW'", m.ActiveBuffer().Lines[0].String())
}
})
@ -1582,8 +1622,8 @@ func TestVisualPasteEdgeCases(t *testing.T) {
sendKeys(tm, "v", "$", "p") // select entire "hello"
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "REPLACED" {
t.Errorf("Line(0) = %q, want 'REPLACED'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "REPLACED" {
t.Errorf("Line(0) = %q, want 'REPLACED'", m.ActiveBuffer().Lines[0].String())
}
})
@ -1596,8 +1636,8 @@ func TestVisualPasteEdgeCases(t *testing.T) {
sendKeys(tm, "v", "h", "h", "h", "h", "h", "p") // select backwards "hello ", paste
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "Xworld" {
t.Errorf("Line(0) = %q, want 'Xworld'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "Xworld" {
t.Errorf("Line(0) = %q, want 'Xworld'", m.ActiveBuffer().Lines[0].String())
}
})
@ -1610,8 +1650,8 @@ func TestVisualPasteEdgeCases(t *testing.T) {
sendKeys(tm, "v", "p")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "XYZ" {
t.Errorf("Line(0) = %q, want 'XYZ'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "XYZ" {
t.Errorf("Line(0) = %q, want 'XYZ'", m.ActiveBuffer().Lines[0].String())
}
})
@ -1627,8 +1667,8 @@ func TestVisualPasteEdgeCases(t *testing.T) {
if m.ActiveBuffer().LineCount() != 1 {
t.Errorf("LineCount() = %d, want 1", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "REPLACED" {
t.Errorf("Line(0) = %q, want 'REPLACED'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "REPLACED" {
t.Errorf("Line(0) = %q, want 'REPLACED'", m.ActiveBuffer().Lines[0].String())
}
})
}

View File

@ -256,8 +256,8 @@ func TestHalfPageScrollDown(t *testing.T) {
if m.ActiveWindow().Cursor.Line != 22 {
t.Errorf("CursorY() = %d, want 22", m.ActiveWindow().Cursor.Line)
}
if m.ActiveWindow().Cursor.Col > len(m.ActiveBuffer().Lines[m.ActiveWindow().Cursor.Line]) {
t.Errorf("CursorX() = %d exceeds line length %d", m.ActiveWindow().Cursor.Col, len(m.ActiveBuffer().Lines[m.ActiveWindow().Cursor.Line]))
if m.ActiveWindow().Cursor.Col > m.ActiveBuffer().Lines[m.ActiveWindow().Cursor.Line].Len() {
t.Errorf("CursorX() = %d exceeds line length %d", m.ActiveWindow().Cursor.Col, m.ActiveBuffer().Lines[m.ActiveWindow().Cursor.Line].Len())
}
})

View File

@ -33,8 +33,8 @@ func TestTextObjectInnerWord(t *testing.T) {
sendKeys(tm, "d", "i", "w")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != " world" {
t.Errorf("lines[0] = %q, want ' world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != " world" {
t.Errorf("lines[0] = %q, want ' world'", m.ActiveBuffer().Lines[0].String())
}
})
@ -44,8 +44,8 @@ func TestTextObjectInnerWord(t *testing.T) {
sendKeys(tm, "c", "i", "w")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != " world" {
t.Errorf("lines[0] = %q, want ' world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != " world" {
t.Errorf("lines[0] = %q, want ' world'", m.ActiveBuffer().Lines[0].String())
}
if m.Mode() != core.InsertMode {
t.Errorf("Expected insert mode after ciw")
@ -138,8 +138,8 @@ func TestTextObjectAroundWord(t *testing.T) {
sendKeys(tm, "d", "a", "w")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "world" {
t.Errorf("lines[0] = %q, want 'world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "world" {
t.Errorf("lines[0] = %q, want 'world'", m.ActiveBuffer().Lines[0].String())
}
})
@ -149,8 +149,8 @@ func TestTextObjectAroundWord(t *testing.T) {
sendKeys(tm, "d", "a", "w")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello " {
t.Errorf("lines[0] = %q, want 'hello '", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello " {
t.Errorf("lines[0] = %q, want 'hello '", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -179,8 +179,8 @@ func TestTextObjectInnerWORD(t *testing.T) {
sendKeys(tm, "d", "i", "W")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != " test" {
t.Errorf("lines[0] = %q, want ' test'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != " test" {
t.Errorf("lines[0] = %q, want ' test'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -205,8 +205,8 @@ func TestTextObjectAroundWORD(t *testing.T) {
sendKeys(tm, "d", "a", "W")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "baz" {
t.Errorf("lines[0] = %q, want 'baz'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "baz" {
t.Errorf("lines[0] = %q, want 'baz'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -248,8 +248,8 @@ func TestTextObjectAngleBrackets(t *testing.T) {
sendKeys(tm, "d", "i", "<")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "<>" {
t.Errorf("lines[0] = %q, want '<>'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "<>" {
t.Errorf("lines[0] = %q, want '<>'", m.ActiveBuffer().Lines[0].String())
}
})
@ -259,8 +259,8 @@ func TestTextObjectAngleBrackets(t *testing.T) {
sendKeys(tm, "d", "a", "<")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("lines[0] = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("lines[0] = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
})
@ -271,8 +271,8 @@ func TestTextObjectAngleBrackets(t *testing.T) {
m := getFinalModel(t, tm)
// Should remain unchanged
if m.ActiveBuffer().Lines[0] != "<>" {
t.Errorf("lines[0] = %q, want '<>'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "<>" {
t.Errorf("lines[0] = %q, want '<>'", m.ActiveBuffer().Lines[0].String())
}
})
@ -321,8 +321,8 @@ func TestTextObjectParentheses(t *testing.T) {
sendKeys(tm, "d", "i", "(")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "func()" {
t.Errorf("lines[0] = %q, want 'func()'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "func()" {
t.Errorf("lines[0] = %q, want 'func()'", m.ActiveBuffer().Lines[0].String())
}
})
@ -332,8 +332,8 @@ func TestTextObjectParentheses(t *testing.T) {
sendKeys(tm, "d", "a", "(")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "func" {
t.Errorf("lines[0] = %q, want 'func'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "func" {
t.Errorf("lines[0] = %q, want 'func'", m.ActiveBuffer().Lines[0].String())
}
})
@ -343,8 +343,8 @@ func TestTextObjectParentheses(t *testing.T) {
sendKeys(tm, "d", "i", "(")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "()" {
t.Errorf("lines[0] = %q, want '()'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "()" {
t.Errorf("lines[0] = %q, want '()'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -368,8 +368,8 @@ func TestTextObjectBraces(t *testing.T) {
sendKeys(tm, "d", "i", "{")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "{}" {
t.Errorf("lines[0] = %q, want '{}'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "{}" {
t.Errorf("lines[0] = %q, want '{}'", m.ActiveBuffer().Lines[0].String())
}
})
@ -379,8 +379,8 @@ func TestTextObjectBraces(t *testing.T) {
sendKeys(tm, "d", "a", "{")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("lines[0] = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("lines[0] = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -404,8 +404,8 @@ func TestTextObjectBrackets(t *testing.T) {
sendKeys(tm, "d", "i", "[")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "[]" {
t.Errorf("lines[0] = %q, want '[]'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "[]" {
t.Errorf("lines[0] = %q, want '[]'", m.ActiveBuffer().Lines[0].String())
}
})
@ -415,8 +415,8 @@ func TestTextObjectBrackets(t *testing.T) {
sendKeys(tm, "d", "a", "[")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("lines[0] = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("lines[0] = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -440,8 +440,8 @@ func TestTextObjectDoubleQuotes(t *testing.T) {
sendKeys(tm, "d", "i", `"`)
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != `""` {
t.Errorf("lines[0] = %q, want '\"\"'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != `""` {
t.Errorf("lines[0] = %q, want '\"\"'", m.ActiveBuffer().Lines[0].String())
}
})
@ -451,8 +451,8 @@ func TestTextObjectDoubleQuotes(t *testing.T) {
sendKeys(tm, "d", "a", `"`)
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("lines[0] = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("lines[0] = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
})
@ -462,8 +462,8 @@ func TestTextObjectDoubleQuotes(t *testing.T) {
sendKeys(tm, "d", "i", `"`)
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != `""` {
t.Errorf("lines[0] = %q, want '\"\"'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != `""` {
t.Errorf("lines[0] = %q, want '\"\"'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -487,8 +487,8 @@ func TestTextObjectSingleQuotes(t *testing.T) {
sendKeys(tm, "d", "i", "'")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "''" {
t.Errorf("lines[0] = %q, want \"''\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "''" {
t.Errorf("lines[0] = %q, want \"''\"", m.ActiveBuffer().Lines[0].String())
}
})
@ -498,8 +498,8 @@ func TestTextObjectSingleQuotes(t *testing.T) {
sendKeys(tm, "d", "a", "'")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("lines[0] = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("lines[0] = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -523,8 +523,8 @@ func TestTextObjectBackticks(t *testing.T) {
sendKeys(tm, "d", "i", "`")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "``" {
t.Errorf("lines[0] = %q, want '``'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "``" {
t.Errorf("lines[0] = %q, want '``'", m.ActiveBuffer().Lines[0].String())
}
})
@ -534,8 +534,8 @@ func TestTextObjectBackticks(t *testing.T) {
sendKeys(tm, "d", "a", "`")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("lines[0] = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("lines[0] = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -551,8 +551,8 @@ func TestTextObjectEdgeCases(t *testing.T) {
sendKeys(tm, "d", "i", "w")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != " b c" {
t.Errorf("lines[0] = %q, want ' b c'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != " b c" {
t.Errorf("lines[0] = %q, want ' b c'", m.ActiveBuffer().Lines[0].String())
}
})
@ -564,8 +564,8 @@ func TestTextObjectEdgeCases(t *testing.T) {
sendKeys(tm, "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "<world>" {
t.Errorf("lines[0] = %q, want '<world>'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "<world>" {
t.Errorf("lines[0] = %q, want '<world>'", m.ActiveBuffer().Lines[0].String())
}
})
@ -577,8 +577,8 @@ func TestTextObjectEdgeCases(t *testing.T) {
m := getFinalModel(t, tm)
// 'p' pastes after cursor, so "arg" is pasted after 't' -> "testarg"
if m.ActiveBuffer().Lines[1] != "testarg" {
t.Errorf("lines[1] = %q, want 'testarg'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "testarg" {
t.Errorf("lines[1] = %q, want 'testarg'", m.ActiveBuffer().Lines[1].String())
}
})
@ -589,8 +589,8 @@ func TestTextObjectEdgeCases(t *testing.T) {
m := getFinalModel(t, tm)
// Should remain unchanged since cursor is not inside parens
if m.ActiveBuffer().Lines[0] != "before (hello) after" {
t.Errorf("lines[0] = %q, want 'before (hello) after'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "before (hello) after" {
t.Errorf("lines[0] = %q, want 'before (hello) after'", m.ActiveBuffer().Lines[0].String())
}
})
@ -600,8 +600,8 @@ func TestTextObjectEdgeCases(t *testing.T) {
sendKeys(tm, "d", "i", "(")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "before () after" {
t.Errorf("lines[0] = %q, want 'before () after'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "before () after" {
t.Errorf("lines[0] = %q, want 'before () after'", m.ActiveBuffer().Lines[0].String())
}
})
@ -612,8 +612,8 @@ func TestTextObjectEdgeCases(t *testing.T) {
m := getFinalModel(t, tm)
// 'a' should delete including the delimiters
if m.ActiveBuffer().Lines[0] != "before after" {
t.Errorf("lines[0] = %q, want 'before after'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "before after" {
t.Errorf("lines[0] = %q, want 'before after'", m.ActiveBuffer().Lines[0].String())
}
})
@ -624,8 +624,8 @@ func TestTextObjectEdgeCases(t *testing.T) {
m := getFinalModel(t, tm)
// Cursor on '(' at position 5, should still select inside
if m.ActiveBuffer().Lines[0] != "text () more" {
t.Errorf("lines[0] = %q, want 'text () more'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "text () more" {
t.Errorf("lines[0] = %q, want 'text () more'", m.ActiveBuffer().Lines[0].String())
}
})
@ -638,8 +638,8 @@ func TestTextObjectEdgeCases(t *testing.T) {
m := getFinalModel(t, tm)
// Cursor on ')', should still select inside
if m.ActiveBuffer().Lines[0] != "text () more" {
t.Errorf("lines[0] = %q, want 'text () more'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "text () more" {
t.Errorf("lines[0] = %q, want 'text () more'", m.ActiveBuffer().Lines[0].String())
}
})
@ -650,8 +650,8 @@ func TestTextObjectEdgeCases(t *testing.T) {
m := getFinalModel(t, tm)
// Should select the first pair it finds
if m.ActiveBuffer().Lines[0] != "() bar (baz)" {
t.Errorf("lines[0] = %q, want '() bar (baz)'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "() bar (baz)" {
t.Errorf("lines[0] = %q, want '() bar (baz)'", m.ActiveBuffer().Lines[0].String())
}
})
@ -663,8 +663,8 @@ func TestTextObjectEdgeCases(t *testing.T) {
m := getFinalModel(t, tm)
// Should search forward and find the second pair
if m.ActiveBuffer().Lines[0] != "(foo) bar ()" {
t.Errorf("lines[0] = %q, want '(foo) bar ()'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "(foo) bar ()" {
t.Errorf("lines[0] = %q, want '(foo) bar ()'", m.ActiveBuffer().Lines[0].String())
}
})
@ -676,8 +676,8 @@ func TestTextObjectEdgeCases(t *testing.T) {
m := getFinalModel(t, tm)
// Should select the first pair since cursor is inside it
if m.ActiveBuffer().Lines[0] != "() bar (baz)" {
t.Errorf("lines[0] = %q, want '() bar (baz)'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "() bar (baz)" {
t.Errorf("lines[0] = %q, want '() bar (baz)'", m.ActiveBuffer().Lines[0].String())
}
})
@ -688,8 +688,8 @@ func TestTextObjectEdgeCases(t *testing.T) {
m := getFinalModel(t, tm)
// Should find and select first quoted string
if m.ActiveBuffer().Lines[0] != `foo "" baz "qux"` {
t.Errorf("lines[0] = %q, want 'foo \"\" baz \"qux\"'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != `foo "" baz "qux"` {
t.Errorf("lines[0] = %q, want 'foo \"\" baz \"qux\"'", m.ActiveBuffer().Lines[0].String())
}
})
@ -701,8 +701,8 @@ func TestTextObjectEdgeCases(t *testing.T) {
m := getFinalModel(t, tm)
// Should search forward and find second string
if m.ActiveBuffer().Lines[0] != `"foo" bar ""` {
t.Errorf("lines[0] = %q, want '\"foo\" bar \"\"'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != `"foo" bar ""` {
t.Errorf("lines[0] = %q, want '\"foo\" bar \"\"'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -727,8 +727,8 @@ func TestTextObjectMultiLineDelimiters(t *testing.T) {
"func test() {",
"}",
}
if !slicesEqual(m.ActiveBuffer().Lines, expected) {
t.Errorf("lines = %v, want %v", m.ActiveBuffer().Lines, expected)
if !slicesEqual(bufferLinesToStrings(m.ActiveBuffer()), expected) {
t.Errorf("lines = %v, want %v", bufferLinesToStrings(m.ActiveBuffer()), expected)
}
})
@ -746,8 +746,8 @@ func TestTextObjectMultiLineDelimiters(t *testing.T) {
expected := []string{
"func test() ",
}
if !slicesEqual(m.ActiveBuffer().Lines, expected) {
t.Errorf("lines = %v, want %v", m.ActiveBuffer().Lines, expected)
if !slicesEqual(bufferLinesToStrings(m.ActiveBuffer()), expected) {
t.Errorf("lines = %v, want %v", bufferLinesToStrings(m.ActiveBuffer()), expected)
}
})
@ -792,8 +792,8 @@ func TestTextObjectMultiLineDelimiters(t *testing.T) {
"function(",
")",
}
if !slicesEqual(m.ActiveBuffer().Lines, expected) {
t.Errorf("lines = %v, want %v", m.ActiveBuffer().Lines, expected)
if !slicesEqual(bufferLinesToStrings(m.ActiveBuffer()), expected) {
t.Errorf("lines = %v, want %v", bufferLinesToStrings(m.ActiveBuffer()), expected)
}
})
@ -815,8 +815,8 @@ func TestTextObjectMultiLineDelimiters(t *testing.T) {
"outer {",
"}",
}
if !slicesEqual(m.ActiveBuffer().Lines, expected) {
t.Errorf("lines = %v, want %v", m.ActiveBuffer().Lines, expected)
if !slicesEqual(bufferLinesToStrings(m.ActiveBuffer()), expected) {
t.Errorf("lines = %v, want %v", bufferLinesToStrings(m.ActiveBuffer()), expected)
}
})
@ -841,8 +841,8 @@ func TestTextObjectMultiLineDelimiters(t *testing.T) {
" more",
"}",
}
if !slicesEqual(m.ActiveBuffer().Lines, expected) {
t.Errorf("lines = %v, want %v", m.ActiveBuffer().Lines, expected)
if !slicesEqual(bufferLinesToStrings(m.ActiveBuffer()), expected) {
t.Errorf("lines = %v, want %v", bufferLinesToStrings(m.ActiveBuffer()), expected)
}
})
@ -869,8 +869,8 @@ func TestTextObjectMultiLineDelimiters(t *testing.T) {
" }",
"}",
}
if !slicesEqual(m.ActiveBuffer().Lines, expected) {
t.Errorf("lines = %v, want %v", m.ActiveBuffer().Lines, expected)
if !slicesEqual(bufferLinesToStrings(m.ActiveBuffer()), expected) {
t.Errorf("lines = %v, want %v", bufferLinesToStrings(m.ActiveBuffer()), expected)
}
})
@ -889,8 +889,8 @@ func TestTextObjectMultiLineDelimiters(t *testing.T) {
"function(arg) {",
"}",
}
if !slicesEqual(m.ActiveBuffer().Lines, expected) {
t.Errorf("lines = %v, want %v", m.ActiveBuffer().Lines, expected)
if !slicesEqual(bufferLinesToStrings(m.ActiveBuffer()), expected) {
t.Errorf("lines = %v, want %v", bufferLinesToStrings(m.ActiveBuffer()), expected)
}
})
@ -909,8 +909,8 @@ func TestTextObjectMultiLineDelimiters(t *testing.T) {
"function(arg) {",
"}",
}
if !slicesEqual(m.ActiveBuffer().Lines, expected) {
t.Errorf("lines = %v, want %v", m.ActiveBuffer().Lines, expected)
if !slicesEqual(bufferLinesToStrings(m.ActiveBuffer()), expected) {
t.Errorf("lines = %v, want %v", bufferLinesToStrings(m.ActiveBuffer()), expected)
}
})
@ -933,8 +933,8 @@ func TestTextObjectMultiLineDelimiters(t *testing.T) {
"}",
"after",
}
if !slicesEqual(m.ActiveBuffer().Lines, expected) {
t.Errorf("lines = %v, want %v", m.ActiveBuffer().Lines, expected)
if !slicesEqual(bufferLinesToStrings(m.ActiveBuffer()), expected) {
t.Errorf("lines = %v, want %v", bufferLinesToStrings(m.ActiveBuffer()), expected)
}
})
@ -959,12 +959,21 @@ func TestTextObjectMultiLineDelimiters(t *testing.T) {
" more",
")",
}
if !slicesEqual(m.ActiveBuffer().Lines, expected) {
t.Errorf("lines = %v, want %v", m.ActiveBuffer().Lines, expected)
if !slicesEqual(bufferLinesToStrings(m.ActiveBuffer()), expected) {
t.Errorf("lines = %v, want %v", bufferLinesToStrings(m.ActiveBuffer()), expected)
}
})
}
// Helper function to get buffer lines as strings
func bufferLinesToStrings(buf *core.Buffer) []string {
result := make([]string, buf.LineCount())
for i := 0; i < buf.LineCount(); i++ {
result[i] = buf.Line(i)
}
return result
}
// Helper function to compare slices
func slicesEqual(a, b []string) bool {
if len(a) != len(b) {

View File

@ -31,8 +31,8 @@ func TestUndoBasicOperations(t *testing.T) {
sendKeys(tm, "u") // Undo
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello" {
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello" {
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0].String())
}
// Verify undo stack is empty
@ -49,8 +49,8 @@ func TestUndoBasicOperations(t *testing.T) {
sendKeys(tm, "ctrl+r") // Redo
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "ello" {
t.Errorf("lines[0] = %q, want 'ello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "ello" {
t.Errorf("lines[0] = %q, want 'ello'", m.ActiveBuffer().Lines[0].String())
}
// Verify redo stack is empty
@ -70,8 +70,8 @@ func TestUndoBasicOperations(t *testing.T) {
sendKeys(tm, "u") // Undo first x -> "hello"
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello" {
t.Errorf("After 3 undos: lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello" {
t.Errorf("After 3 undos: lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0].String())
}
// Verify undo stack is empty
@ -87,8 +87,8 @@ func TestUndoBasicOperations(t *testing.T) {
sendKeys(tm, "u") // Undo
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello" {
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello" {
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -104,8 +104,8 @@ func TestUndoCursorRestoration(t *testing.T) {
if m.ActiveWindow().Cursor.Col != 6 {
t.Errorf("cursor col = %d, want 6", m.ActiveWindow().Cursor.Col)
}
if m.ActiveBuffer().Lines[0] != "hello world" {
t.Errorf("lines[0] = %q, want 'hello world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello world" {
t.Errorf("lines[0] = %q, want 'hello world'", m.ActiveBuffer().Lines[0].String())
}
})
@ -137,8 +137,8 @@ func TestUndoInsertMode(t *testing.T) {
sendKeys(tm, "u") // Undo once
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("lines[0] = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("lines[0] = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
// Verify only one undo was needed
@ -167,8 +167,8 @@ func TestUndoInsertMode(t *testing.T) {
sendKeys(tm, "u")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("After 2 undos: lines[0] = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("After 2 undos: lines[0] = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
// Verify undo stack is empty
@ -191,7 +191,7 @@ func TestUndoInsertMode(t *testing.T) {
sendKeys(tm, "u")
m := getFinalModel(t, tm)
if len(m.ActiveBuffer().Lines) != 1 || m.ActiveBuffer().Lines[0] != "" {
if len(m.ActiveBuffer().Lines) != 1 || m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("After undo: got %d lines with content %q, want 1 empty line",
len(m.ActiveBuffer().Lines), m.ActiveBuffer().Lines)
}
@ -209,8 +209,8 @@ func TestUndoInsertMode(t *testing.T) {
sendKeys(tm, "u")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("After undo: lines[0] = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("After undo: lines[0] = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -230,8 +230,8 @@ func TestUndoDeleteOperator(t *testing.T) {
if len(m.ActiveBuffer().Lines) != 3 {
t.Errorf("line count = %d, want 3", len(m.ActiveBuffer().Lines))
}
if m.ActiveBuffer().Lines[0] != "line1" {
t.Errorf("lines[0] = %q, want 'line1'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line1" {
t.Errorf("lines[0] = %q, want 'line1'", m.ActiveBuffer().Lines[0].String())
}
})
@ -245,11 +245,11 @@ func TestUndoDeleteOperator(t *testing.T) {
if len(m.ActiveBuffer().Lines) != 4 {
t.Errorf("line count = %d, want 4", len(m.ActiveBuffer().Lines))
}
if m.ActiveBuffer().Lines[0] != "line1" {
t.Errorf("lines[0] = %q, want 'line1'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line1" {
t.Errorf("lines[0] = %q, want 'line1'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[2] != "line3" {
t.Errorf("lines[2] = %q, want 'line3'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "line3" {
t.Errorf("lines[2] = %q, want 'line3'", m.ActiveBuffer().Lines[2].String())
}
})
@ -260,8 +260,8 @@ func TestUndoDeleteOperator(t *testing.T) {
sendKeys(tm, "u") // Undo
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello world foo" {
t.Errorf("lines[0] = %q, want 'hello world foo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello world foo" {
t.Errorf("lines[0] = %q, want 'hello world foo'", m.ActiveBuffer().Lines[0].String())
}
})
@ -272,8 +272,8 @@ func TestUndoDeleteOperator(t *testing.T) {
sendKeys(tm, "u") // Undo
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello world" {
t.Errorf("lines[0] = %q, want 'hello world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello world" {
t.Errorf("lines[0] = %q, want 'hello world'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Col != 6 {
t.Errorf("cursor col = %d, want 6", m.ActiveWindow().Cursor.Col)
@ -291,8 +291,8 @@ func TestUndoChangeOperator(t *testing.T) {
sendKeys(tm, "u") // Undo
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "original line" {
t.Errorf("lines[0] = %q, want 'original line'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "original line" {
t.Errorf("lines[0] = %q, want 'original line'", m.ActiveBuffer().Lines[0].String())
}
})
@ -305,8 +305,8 @@ func TestUndoChangeOperator(t *testing.T) {
sendKeys(tm, "u")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello world" {
t.Errorf("lines[0] = %q, want 'hello world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello world" {
t.Errorf("lines[0] = %q, want 'hello world'", m.ActiveBuffer().Lines[0].String())
}
})
@ -319,8 +319,8 @@ func TestUndoChangeOperator(t *testing.T) {
sendKeys(tm, "u")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello" {
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello" {
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0].String())
}
})
@ -333,8 +333,8 @@ func TestUndoChangeOperator(t *testing.T) {
sendKeys(tm, "u")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "original" {
t.Errorf("lines[0] = %q, want 'original'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "original" {
t.Errorf("lines[0] = %q, want 'original'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -353,8 +353,8 @@ func TestUndoVisualMode(t *testing.T) {
sendKeys(tm, "u") // Undo
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello world" {
t.Errorf("lines[0] = %q, want 'hello world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello world" {
t.Errorf("lines[0] = %q, want 'hello world'", m.ActiveBuffer().Lines[0].String())
}
})
@ -370,8 +370,8 @@ func TestUndoVisualMode(t *testing.T) {
if len(m.ActiveBuffer().Lines) != 3 {
t.Errorf("line count = %d, want 3", len(m.ActiveBuffer().Lines))
}
if m.ActiveBuffer().Lines[0] != "line1" {
t.Errorf("lines[0] = %q, want 'line1'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line1" {
t.Errorf("lines[0] = %q, want 'line1'", m.ActiveBuffer().Lines[0].String())
}
})
@ -385,11 +385,11 @@ func TestUndoVisualMode(t *testing.T) {
sendKeys(tm, "u") // Undo
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello" {
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello" {
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "world" {
t.Errorf("lines[1] = %q, want 'world'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "world" {
t.Errorf("lines[1] = %q, want 'world'", m.ActiveBuffer().Lines[1].String())
}
})
@ -404,8 +404,8 @@ func TestUndoVisualMode(t *testing.T) {
sendKeys(tm, "u") // Undo
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello world" {
t.Errorf("lines[0] = %q, want 'hello world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello world" {
t.Errorf("lines[0] = %q, want 'hello world'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -422,8 +422,8 @@ func TestUndoTextObjects(t *testing.T) {
sendKeys(tm, "u") // Undo
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello world foo" {
t.Errorf("lines[0] = %q, want 'hello world foo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello world foo" {
t.Errorf("lines[0] = %q, want 'hello world foo'", m.ActiveBuffer().Lines[0].String())
}
})
@ -434,8 +434,8 @@ func TestUndoTextObjects(t *testing.T) {
sendKeys(tm, "u") // Undo
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello world foo" {
t.Errorf("lines[0] = %q, want 'hello world foo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello world foo" {
t.Errorf("lines[0] = %q, want 'hello world foo'", m.ActiveBuffer().Lines[0].String())
}
})
@ -448,8 +448,8 @@ func TestUndoTextObjects(t *testing.T) {
sendKeys(tm, "u") // Undo
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "before (hello) after" {
t.Errorf("lines[0] = %q, want 'before (hello) after'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "before (hello) after" {
t.Errorf("lines[0] = %q, want 'before (hello) after'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -470,8 +470,8 @@ func TestUndoRedoSequences(t *testing.T) {
sendKeys(tm, "ctrl+r", "ctrl+r")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "llo" {
t.Errorf("After 2 redos: lines[0] = %q, want 'llo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "llo" {
t.Errorf("After 2 redos: lines[0] = %q, want 'llo'", m.ActiveBuffer().Lines[0].String())
}
})
@ -490,8 +490,8 @@ func TestUndoRedoSequences(t *testing.T) {
}
// Verify content
if m.ActiveBuffer().Lines[0] != "llo" {
t.Errorf("lines[0] = %q, want 'llo'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "llo" {
t.Errorf("lines[0] = %q, want 'llo'", m.ActiveBuffer().Lines[0].String())
}
})
@ -512,8 +512,8 @@ func TestUndoRedoSequences(t *testing.T) {
sendKeys(tm, "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "newline3" {
t.Errorf("After insert: lines[0] = %q, want 'newline3'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "newline3" {
t.Errorf("After insert: lines[0] = %q, want 'newline3'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -529,8 +529,8 @@ func TestUndoEdgeCases(t *testing.T) {
sendKeys(tm, "u") // Undo when nothing to undo
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello" {
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello" {
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0].String())
}
})
@ -540,8 +540,8 @@ func TestUndoEdgeCases(t *testing.T) {
sendKeys(tm, "ctrl+r") // Redo when nothing to redo
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello" {
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello" {
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0].String())
}
})
@ -554,8 +554,8 @@ func TestUndoEdgeCases(t *testing.T) {
sendKeys(tm, "ctrl+r") // Try redo again (should do nothing)
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "ello" {
t.Errorf("lines[0] = %q, want 'ello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "ello" {
t.Errorf("lines[0] = %q, want 'ello'", m.ActiveBuffer().Lines[0].String())
}
})
@ -569,8 +569,8 @@ func TestUndoEdgeCases(t *testing.T) {
if len(m.ActiveBuffer().Lines) != 1 {
t.Errorf("line count = %d, want 1", len(m.ActiveBuffer().Lines))
}
if m.ActiveBuffer().Lines[0] != "only line" {
t.Errorf("lines[0] = %q, want 'only line'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "only line" {
t.Errorf("lines[0] = %q, want 'only line'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -594,8 +594,8 @@ func TestUndoMultiLineOperations(t *testing.T) {
}
for i := 0; i < 5; i++ {
expected := "line" + string(rune('1'+i))
if m.ActiveBuffer().Lines[i] != expected {
t.Errorf("lines[%d] = %q, want %q", i, m.ActiveBuffer().Lines[i], expected)
if m.ActiveBuffer().Lines[i].String() != expected {
t.Errorf("lines[%d] = %q, want %q", i, m.ActiveBuffer().Lines[i].String(), expected)
}
}
})
@ -610,8 +610,8 @@ func TestUndoMultiLineOperations(t *testing.T) {
if len(m.ActiveBuffer().Lines) != 3 {
t.Errorf("line count = %d, want 3", len(m.ActiveBuffer().Lines))
}
if m.ActiveBuffer().Lines[0] != "line1" {
t.Errorf("lines[0] = %q, want 'line1'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line1" {
t.Errorf("lines[0] = %q, want 'line1'", m.ActiveBuffer().Lines[0].String())
}
})
@ -627,8 +627,8 @@ func TestUndoMultiLineOperations(t *testing.T) {
if len(m.ActiveBuffer().Lines) != 2 {
t.Errorf("line count = %d, want 2", len(m.ActiveBuffer().Lines))
}
if m.ActiveBuffer().Lines[0] != "line1" {
t.Errorf("lines[0] = %q, want 'line1'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line1" {
t.Errorf("lines[0] = %q, want 'line1'", m.ActiveBuffer().Lines[0].String())
}
})
@ -644,8 +644,8 @@ func TestUndoMultiLineOperations(t *testing.T) {
if len(m.ActiveBuffer().Lines) != 2 {
t.Errorf("line count = %d, want 2", len(m.ActiveBuffer().Lines))
}
if m.ActiveBuffer().Lines[1] != "line2" {
t.Errorf("lines[1] = %q, want 'line2'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "line2" {
t.Errorf("lines[1] = %q, want 'line2'", m.ActiveBuffer().Lines[1].String())
}
})
}
@ -688,8 +688,8 @@ func TestUndoStackStructure(t *testing.T) {
sendKeys(tm, "u")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("After undo: lines[0] = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("After undo: lines[0] = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().UndoStack.CanUndo() {
t.Error("Expected empty undo stack after single undo")
@ -755,8 +755,8 @@ func TestUndoComplexScenarios(t *testing.T) {
sendKeys(tm, "x") // Delete 'a' -> "bc"
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "bc" {
t.Errorf("lines[0] = %q, want 'bc'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "bc" {
t.Errorf("lines[0] = %q, want 'bc'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -781,8 +781,8 @@ func TestUndoPasteOperations(t *testing.T) {
t.Errorf("len(Lines) = %d, want %d", len(m.ActiveBuffer().Lines), len(expected))
}
for i, exp := range expected {
if m.ActiveBuffer().Lines[i] != exp {
t.Errorf("Lines[%d] = %q, want %q", i, m.ActiveBuffer().Lines[i], exp)
if m.ActiveBuffer().Lines[i].String() != exp {
t.Errorf("Lines[%d] = %q, want %q", i, m.ActiveBuffer().Lines[i].String(), exp)
}
}
// Cursor should be back at line2
@ -806,8 +806,8 @@ func TestUndoPasteOperations(t *testing.T) {
t.Errorf("len(Lines) = %d, want %d", len(m.ActiveBuffer().Lines), len(expected))
}
for i, exp := range expected {
if m.ActiveBuffer().Lines[i] != exp {
t.Errorf("Lines[%d] = %q, want %q", i, m.ActiveBuffer().Lines[i], exp)
if m.ActiveBuffer().Lines[i].String() != exp {
t.Errorf("Lines[%d] = %q, want %q", i, m.ActiveBuffer().Lines[i].String(), exp)
}
}
// Cursor should be back at line2
@ -827,7 +827,7 @@ func TestUndoPasteOperations(t *testing.T) {
m := getFinalModel(t, tm)
expected := []string{"hello world"}
if !equalStringSlices(m.ActiveBuffer().Lines, expected) {
if !equalStringSlices(bufferLinesToStrings(m.ActiveBuffer()), expected) {
t.Errorf("Lines = %v, want %v", m.ActiveBuffer().Lines, expected)
}
})
@ -848,8 +848,8 @@ func TestUndoPasteOperations(t *testing.T) {
t.Errorf("len(Lines) = %d, want %d", len(m.ActiveBuffer().Lines), len(expected))
}
for i, exp := range expected {
if m.ActiveBuffer().Lines[i] != exp {
t.Errorf("Lines[%d] = %q, want %q", i, m.ActiveBuffer().Lines[i], exp)
if m.ActiveBuffer().Lines[i].String() != exp {
t.Errorf("Lines[%d] = %q, want %q", i, m.ActiveBuffer().Lines[i].String(), exp)
}
}
})
@ -865,7 +865,7 @@ func TestUndoPasteOperations(t *testing.T) {
m := getFinalModel(t, tm)
expected := []string{"base"}
if !equalStringSlices(m.ActiveBuffer().Lines, expected) {
if !equalStringSlices(bufferLinesToStrings(m.ActiveBuffer()), expected) {
t.Errorf("Lines = %v, want %v", m.ActiveBuffer().Lines, expected)
}
})
@ -879,7 +879,7 @@ func TestUndoPasteOperations(t *testing.T) {
m := getFinalModel(t, tm)
expected := []string{"test"}
if !equalStringSlices(m.ActiveBuffer().Lines, expected) {
if !equalStringSlices(bufferLinesToStrings(m.ActiveBuffer()), expected) {
t.Errorf("Lines = %v, want %v", m.ActiveBuffer().Lines, expected)
}
})
@ -899,7 +899,7 @@ func TestUndoComplexCountOperations(t *testing.T) {
m := getFinalModel(t, tm)
expected := []string{"1", "2", "3", "4", "5", "6", "7"}
if !equalStringSlices(m.ActiveBuffer().Lines, expected) {
if !equalStringSlices(bufferLinesToStrings(m.ActiveBuffer()), expected) {
t.Errorf("Lines = %v, want %v", m.ActiveBuffer().Lines, expected)
}
// Cursor should be back at line 3 (index 2)
@ -918,7 +918,7 @@ func TestUndoComplexCountOperations(t *testing.T) {
m := getFinalModel(t, tm)
expected := []string{"one two three four five"}
if !equalStringSlices(m.ActiveBuffer().Lines, expected) {
if !equalStringSlices(bufferLinesToStrings(m.ActiveBuffer()), expected) {
t.Errorf("Lines = %v, want %v", m.ActiveBuffer().Lines, expected)
}
})
@ -932,7 +932,7 @@ func TestUndoComplexCountOperations(t *testing.T) {
m := getFinalModel(t, tm)
expected := []string{"abcdefghijklmnopqrstuvwxyz"}
if !equalStringSlices(m.ActiveBuffer().Lines, expected) {
if !equalStringSlices(bufferLinesToStrings(m.ActiveBuffer()), expected) {
t.Errorf("Lines = %v, want %v", m.ActiveBuffer().Lines, expected)
}
// Cursor should be back at column 4 (index of 'e', 0-based)
@ -952,7 +952,7 @@ func TestUndoComplexCountOperations(t *testing.T) {
m := getFinalModel(t, tm)
expected := []string{"line1", "line2", "line3", "line4"}
if !equalStringSlices(m.ActiveBuffer().Lines, expected) {
if !equalStringSlices(bufferLinesToStrings(m.ActiveBuffer()), expected) {
t.Errorf("Lines = %v, want %v", m.ActiveBuffer().Lines, expected)
}
})
@ -966,7 +966,7 @@ func TestUndoComplexCountOperations(t *testing.T) {
m := getFinalModel(t, tm)
expected := []string{"word1 word2 word3 word4 word5"}
if !equalStringSlices(m.ActiveBuffer().Lines, expected) {
if !equalStringSlices(bufferLinesToStrings(m.ActiveBuffer()), expected) {
t.Errorf("Lines = %v, want %v", m.ActiveBuffer().Lines, expected)
}
})
@ -981,7 +981,7 @@ func TestUndoComplexCountOperations(t *testing.T) {
m := getFinalModel(t, tm)
expected := []string{"A", "B", "C", "D"}
if !equalStringSlices(m.ActiveBuffer().Lines, expected) {
if !equalStringSlices(bufferLinesToStrings(m.ActiveBuffer()), expected) {
t.Errorf("Lines = %v, want %v", m.ActiveBuffer().Lines, expected)
}
// Cursor should be back at line C (index 2)

View File

@ -125,8 +125,8 @@ func TestVisualModeDelete(t *testing.T) {
sendKeys(tm, "v", "d")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "ello" {
t.Errorf("Line(0) = %q, want \"ello\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "ello" {
t.Errorf("Line(0) = %q, want \"ello\"", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Col != 0 {
t.Errorf("CursorX() = %d, want 0", m.ActiveWindow().Cursor.Col)
@ -139,8 +139,8 @@ func TestVisualModeDelete(t *testing.T) {
sendKeys(tm, "v", "l", "l", "l", "d")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "o world" {
t.Errorf("Line(0) = %q, want \"o world\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "o world" {
t.Errorf("Line(0) = %q, want \"o world\"", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Col != 0 {
t.Errorf("CursorX() = %d, want 0", m.ActiveWindow().Cursor.Col)
@ -154,8 +154,8 @@ func TestVisualModeDelete(t *testing.T) {
// anchor=3, cursor=1 → normalized start=1, end=3 → delete "ell" → "ho"
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "ho" {
t.Errorf("Line(0) = %q, want \"ho\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "ho" {
t.Errorf("Line(0) = %q, want \"ho\"", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Col != 1 {
t.Errorf("CursorX() = %d, want 1", m.ActiveWindow().Cursor.Col)
@ -172,8 +172,8 @@ func TestVisualModeDelete(t *testing.T) {
if m.ActiveBuffer().LineCount() != 1 {
t.Errorf("LineCount() = %d, want 1", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "held" {
t.Errorf("Line(0) = %q, want \"held\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "held" {
t.Errorf("Line(0) = %q, want \"held\"", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Col != 2 {
t.Errorf("CursorX() = %d, want 2", m.ActiveWindow().Cursor.Col)
@ -192,8 +192,8 @@ func TestVisualModeDelete(t *testing.T) {
if m.ActiveBuffer().LineCount() != 1 {
t.Errorf("LineCount() = %d, want 1", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "world" {
t.Errorf("Line(0) = %q, want \"world\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "world" {
t.Errorf("Line(0) = %q, want \"world\"", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Line != 0 {
t.Errorf("CursorY() = %d, want 0", m.ActiveWindow().Cursor.Line)
@ -209,8 +209,8 @@ func TestVisualModeDelete(t *testing.T) {
if m.ActiveBuffer().LineCount() != 1 {
t.Errorf("LineCount() = %d, want 1", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "testing" {
t.Errorf("Line(0) = %q, want \"testing\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "testing" {
t.Errorf("Line(0) = %q, want \"testing\"", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveWindow().Cursor.Line != 0 {
t.Errorf("CursorY() = %d, want 0", m.ActiveWindow().Cursor.Line)
@ -227,8 +227,8 @@ func TestVisualModeDelete(t *testing.T) {
if m.ActiveBuffer().LineCount() != 1 {
t.Errorf("LineCount() = %d, want 1", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "hello" {
t.Errorf("Line(0) = %q, want \"hello\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello" {
t.Errorf("Line(0) = %q, want \"hello\"", m.ActiveBuffer().Lines[0].String())
}
})
@ -241,11 +241,11 @@ func TestVisualModeDelete(t *testing.T) {
// "hello"[:0]+"hello"[2:] = "llo"
// "world"[:0]+"world"[2:] = "rld"
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "llo" {
t.Errorf("Line(0) = %q, want \"llo\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "llo" {
t.Errorf("Line(0) = %q, want \"llo\"", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "rld" {
t.Errorf("Line(1) = %q, want \"rld\"", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "rld" {
t.Errorf("Line(1) = %q, want \"rld\"", m.ActiveBuffer().Lines[1].String())
}
if m.ActiveWindow().Cursor.Col != 0 {
t.Errorf("CursorX() = %d, want 0", m.ActiveWindow().Cursor.Col)
@ -264,11 +264,11 @@ func TestVisualModeDelete(t *testing.T) {
// "hello"[:1]+"hello"[4:] = "h"+"o" = "ho"
// "world"[:1]+"world"[4:] = "w"+"d" = "wd"
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "ho" {
t.Errorf("Line(0) = %q, want \"ho\"", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "ho" {
t.Errorf("Line(0) = %q, want \"ho\"", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "wd" {
t.Errorf("Line(1) = %q, want \"wd\"", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "wd" {
t.Errorf("Line(1) = %q, want \"wd\"", m.ActiveBuffer().Lines[1].String())
}
})
}
@ -302,8 +302,8 @@ func TestVisualModeWordMotions(t *testing.T) {
m := getFinalModel(t, tm)
// Deletes from 0 to 6 inclusive = "hello w", leaves "orld"
if m.ActiveBuffer().Lines[0] != "orld" {
t.Errorf("Line(0) = %q, want 'orld'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "orld" {
t.Errorf("Line(0) = %q, want 'orld'", m.ActiveBuffer().Lines[0].String())
}
})
@ -333,8 +333,8 @@ func TestVisualModeWordMotions(t *testing.T) {
m := getFinalModel(t, tm)
// Deletes "hello"
if m.ActiveBuffer().Lines[0] != " world" {
t.Errorf("Line(0) = %q, want ' world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != " world" {
t.Errorf("Line(0) = %q, want ' world'", m.ActiveBuffer().Lines[0].String())
}
})
@ -364,8 +364,8 @@ func TestVisualModeWordMotions(t *testing.T) {
m := getFinalModel(t, tm)
// Deletes from "h" (0) to "w" (6) inclusive
if m.ActiveBuffer().Lines[0] != "orld" {
t.Errorf("Line(0) = %q, want 'orld'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "orld" {
t.Errorf("Line(0) = %q, want 'orld'", m.ActiveBuffer().Lines[0].String())
}
})
@ -412,8 +412,8 @@ func TestVisualModeJumpMotions(t *testing.T) {
sendKeys(tm, "v", "$", "d")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello " {
t.Errorf("Line(0) = %q, want 'hello '", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello " {
t.Errorf("Line(0) = %q, want 'hello '", m.ActiveBuffer().Lines[0].String())
}
})
@ -442,8 +442,8 @@ func TestVisualModeJumpMotions(t *testing.T) {
m := getFinalModel(t, tm)
// Deletes from 'h' (0) to 'w' (6) inclusive
if m.ActiveBuffer().Lines[0] != "orld" {
t.Errorf("Line(0) = %q, want 'orld'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "orld" {
t.Errorf("Line(0) = %q, want 'orld'", m.ActiveBuffer().Lines[0].String())
}
})
@ -493,8 +493,8 @@ func TestVisualModeJumpMotions(t *testing.T) {
if m.ActiveBuffer().LineCount() != 1 {
t.Errorf("LineCount() = %d, want 1", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "lin 3" {
t.Errorf("Line(0) = %q, want 'lin 3'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "lin 3" {
t.Errorf("Line(0) = %q, want 'lin 3'", m.ActiveBuffer().Lines[0].String())
}
})
@ -527,8 +527,8 @@ func TestVisualModeJumpMotions(t *testing.T) {
if m.ActiveBuffer().LineCount() != 1 {
t.Errorf("LineCount() = %d, want 1", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "lin 3" {
t.Errorf("Line(0) = %q, want 'lin 3'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "lin 3" {
t.Errorf("Line(0) = %q, want 'lin 3'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -564,8 +564,8 @@ func TestVisualLineModeJumpMotions(t *testing.T) {
if m.ActiveBuffer().LineCount() != 1 {
t.Errorf("LineCount() = %d, want 1", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "" {
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0].String())
}
})

View File

@ -46,14 +46,14 @@ func TestYankLineBasic(t *testing.T) {
if m.ActiveBuffer().LineCount() != 3 {
t.Errorf("LineCount() = %d, want 3", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line 1" {
t.Errorf("Line(0) = %q, want 'line 1'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "line 2" {
t.Errorf("Line(1) = %q, want 'line 2'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "line 2" {
t.Errorf("Line(1) = %q, want 'line 2'", m.ActiveBuffer().Lines[1].String())
}
if m.ActiveBuffer().Lines[2] != "line 3" {
t.Errorf("Line(2) = %q, want 'line 3'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "line 3" {
t.Errorf("Line(2) = %q, want 'line 3'", m.ActiveBuffer().Lines[2].String())
}
})
@ -583,8 +583,8 @@ func TestYankWithCharwiseMotions(t *testing.T) {
sendKeys(tm, "y", "w")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello world" {
t.Errorf("Line(0) = %q, want 'hello world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello world" {
t.Errorf("Line(0) = %q, want 'hello world'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -659,8 +659,8 @@ func TestYankVisualCharwise(t *testing.T) {
sendKeys(tm, "v", "l", "l", "l", "l", "y")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello world" {
t.Errorf("Line(0) = %q, want 'hello world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello world" {
t.Errorf("Line(0) = %q, want 'hello world'", m.ActiveBuffer().Lines[0].String())
}
})
}
@ -904,8 +904,8 @@ func TestYankRegisterBehavior(t *testing.T) {
if m.ActiveBuffer().LineCount() != 3 {
t.Errorf("LineCount() = %d, want 3", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[1] != "to copy" {
t.Errorf("Line(1) = %q, want 'to copy'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "to copy" {
t.Errorf("Line(1) = %q, want 'to copy'", m.ActiveBuffer().Lines[1].String())
}
})
}
@ -1053,8 +1053,8 @@ func TestVisualYankPasteRoundTrip(t *testing.T) {
sendKeys(tm, "v", "l", "l", "l", "l", "y", "$", "p")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello worldhello" {
t.Errorf("Line(0) = %q, want 'hello worldhello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello worldhello" {
t.Errorf("Line(0) = %q, want 'hello worldhello'", m.ActiveBuffer().Lines[0].String())
}
})
@ -1067,8 +1067,8 @@ func TestVisualYankPasteRoundTrip(t *testing.T) {
sendKeys(tm, "v", "$", "y", "0", "P")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "worldhello world" {
t.Errorf("Line(0) = %q, want 'worldhello world'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "worldhello world" {
t.Errorf("Line(0) = %q, want 'worldhello world'", m.ActiveBuffer().Lines[0].String())
}
})
@ -1084,8 +1084,8 @@ func TestVisualYankPasteRoundTrip(t *testing.T) {
if m.ActiveBuffer().LineCount() != 4 {
t.Errorf("LineCount() = %d, want 4", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[2] != "line 1" {
t.Errorf("Line(2) = %q, want 'line 1'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "line 1" {
t.Errorf("Line(2) = %q, want 'line 1'", m.ActiveBuffer().Lines[2].String())
}
})
@ -1101,11 +1101,11 @@ func TestVisualYankPasteRoundTrip(t *testing.T) {
if m.ActiveBuffer().LineCount() != 6 {
t.Errorf("LineCount() = %d, want 6", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[4] != "line 1" {
t.Errorf("Line(4) = %q, want 'line 1'", m.ActiveBuffer().Lines[4])
if m.ActiveBuffer().Lines[4].String() != "line 1" {
t.Errorf("Line(4) = %q, want 'line 1'", m.ActiveBuffer().Lines[4].String())
}
if m.ActiveBuffer().Lines[5] != "line 2" {
t.Errorf("Line(5) = %q, want 'line 2'", m.ActiveBuffer().Lines[5])
if m.ActiveBuffer().Lines[5].String() != "line 2" {
t.Errorf("Line(5) = %q, want 'line 2'", m.ActiveBuffer().Lines[5].String())
}
})
@ -1121,11 +1121,11 @@ func TestVisualYankPasteRoundTrip(t *testing.T) {
if m.ActiveBuffer().LineCount() != 4 {
t.Errorf("LineCount() = %d, want 4", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "line 3" {
t.Errorf("Line(0) = %q, want 'line 3'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line 3" {
t.Errorf("Line(0) = %q, want 'line 3'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "line 1" {
t.Errorf("Line(1) = %q, want 'line 1'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "line 1" {
t.Errorf("Line(1) = %q, want 'line 1'", m.ActiveBuffer().Lines[1].String())
}
})
@ -1140,14 +1140,14 @@ func TestVisualYankPasteRoundTrip(t *testing.T) {
if m.ActiveBuffer().LineCount() != 3 {
t.Errorf("LineCount() = %d, want 3", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "original" {
t.Errorf("Line(0) = %q, want 'original'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "original" {
t.Errorf("Line(0) = %q, want 'original'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "original" {
t.Errorf("Line(1) = %q, want 'original'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "original" {
t.Errorf("Line(1) = %q, want 'original'", m.ActiveBuffer().Lines[1].String())
}
if m.ActiveBuffer().Lines[2] != "other" {
t.Errorf("Line(2) = %q, want 'other'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "other" {
t.Errorf("Line(2) = %q, want 'other'", m.ActiveBuffer().Lines[2].String())
}
})
@ -1162,14 +1162,14 @@ func TestVisualYankPasteRoundTrip(t *testing.T) {
if m.ActiveBuffer().LineCount() != 3 {
t.Errorf("LineCount() = %d, want 3", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "original" {
t.Errorf("Line(0) = %q, want 'original'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "original" {
t.Errorf("Line(0) = %q, want 'original'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "other" {
t.Errorf("Line(1) = %q, want 'other'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "other" {
t.Errorf("Line(1) = %q, want 'other'", m.ActiveBuffer().Lines[1].String())
}
if m.ActiveBuffer().Lines[2] != "other" {
t.Errorf("Line(2) = %q, want 'other'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "other" {
t.Errorf("Line(2) = %q, want 'other'", m.ActiveBuffer().Lines[2].String())
}
})
@ -1182,8 +1182,8 @@ func TestVisualYankPasteRoundTrip(t *testing.T) {
sendKeys(tm, "y", "w", "$", "p")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello worldhello " {
t.Errorf("Line(0) = %q, want 'hello worldhello '", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello worldhello " {
t.Errorf("Line(0) = %q, want 'hello worldhello '", m.ActiveBuffer().Lines[0].String())
}
})
@ -1196,8 +1196,8 @@ func TestVisualYankPasteRoundTrip(t *testing.T) {
sendKeys(tm, "y", "e", "$", "p")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello worldhello" {
t.Errorf("Line(0) = %q, want 'hello worldhello'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "hello worldhello" {
t.Errorf("Line(0) = %q, want 'hello worldhello'", m.ActiveBuffer().Lines[0].String())
}
})
@ -1210,8 +1210,8 @@ func TestVisualYankPasteRoundTrip(t *testing.T) {
sendKeys(tm, "v", "l", "l", "y", "$", "p")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "abcdefghcde" {
t.Errorf("Line(0) = %q, want 'abcdefghcde'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "abcdefghcde" {
t.Errorf("Line(0) = %q, want 'abcdefghcde'", m.ActiveBuffer().Lines[0].String())
}
})
@ -1246,14 +1246,14 @@ func TestVisualYankPasteRoundTrip(t *testing.T) {
if m.ActiveBuffer().LineCount() != 3 {
t.Errorf("LineCount() = %d, want 3", m.ActiveBuffer().LineCount())
}
if m.ActiveBuffer().Lines[0] != "line 2" {
t.Errorf("Line(0) = %q, want 'line 2'", m.ActiveBuffer().Lines[0])
if m.ActiveBuffer().Lines[0].String() != "line 2" {
t.Errorf("Line(0) = %q, want 'line 2'", m.ActiveBuffer().Lines[0].String())
}
if m.ActiveBuffer().Lines[1] != "line 1" {
t.Errorf("Line(1) = %q, want 'line 1'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "line 1" {
t.Errorf("Line(1) = %q, want 'line 1'", m.ActiveBuffer().Lines[1].String())
}
if m.ActiveBuffer().Lines[2] != "line 3" {
t.Errorf("Line(2) = %q, want 'line 3'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "line 3" {
t.Errorf("Line(2) = %q, want 'line 3'", m.ActiveBuffer().Lines[2].String())
}
})
@ -1270,17 +1270,17 @@ func TestVisualYankPasteRoundTrip(t *testing.T) {
t.Errorf("LineCount() = %d, want 7", m.ActiveBuffer().LineCount())
}
// Original + 2 copies of 2 lines = 3 + 4 = 7
if m.ActiveBuffer().Lines[1] != "line 1" {
t.Errorf("Line(1) = %q, want 'line 1'", m.ActiveBuffer().Lines[1])
if m.ActiveBuffer().Lines[1].String() != "line 1" {
t.Errorf("Line(1) = %q, want 'line 1'", m.ActiveBuffer().Lines[1].String())
}
if m.ActiveBuffer().Lines[2] != "line 2" {
t.Errorf("Line(2) = %q, want 'line 2'", m.ActiveBuffer().Lines[2])
if m.ActiveBuffer().Lines[2].String() != "line 2" {
t.Errorf("Line(2) = %q, want 'line 2'", m.ActiveBuffer().Lines[2].String())
}
if m.ActiveBuffer().Lines[3] != "line 1" {
t.Errorf("Line(3) = %q, want 'line 1'", m.ActiveBuffer().Lines[3])
if m.ActiveBuffer().Lines[3].String() != "line 1" {
t.Errorf("Line(3) = %q, want 'line 1'", m.ActiveBuffer().Lines[3].String())
}
if m.ActiveBuffer().Lines[4] != "line 2" {
t.Errorf("Line(4) = %q, want 'line 2'", m.ActiveBuffer().Lines[4])
if m.ActiveBuffer().Lines[4].String() != "line 2" {
t.Errorf("Line(4) = %q, want 'line 2'", m.ActiveBuffer().Lines[4].String())
}
})
}

View File

@ -6,8 +6,6 @@ import (
"git.gophernest.net/azpect/TextEditor/internal/core"
"git.gophernest.net/azpect/TextEditor/internal/style"
"github.com/alecthomas/chroma/v2"
"github.com/alecthomas/chroma/v2/lexers"
"github.com/charmbracelet/lipgloss"
)
@ -52,12 +50,7 @@ func viewWindow(w *core.Window, styles style.Styles, options core.WinOptions, mo
end := w.ScrollY + w.ViewportHeight()
// Chroma stuff
name := strings.ReplaceAll(buf.Filetype, ".", "")
lexer := lexers.Get(name)
if lexer == nil {
lexer = lexers.Fallback
}
lexer = chroma.Coalesce(lexer) // Merge tokens together
lexer := style.GetLexer(buf)
// Draw buffer lines
for lineNum := start; lineNum < end; lineNum++ {

View File

@ -134,7 +134,8 @@ func NewVisualKeymap() *Keymap {
"c": operator.ChangeOperator{},
},
actions: map[string]action.Action{
"p": action.VisualPaste{Count: 1},
"p": action.VisualPaste{Count: 1, Replace: true},
"P": action.VisualPaste{Count: 1, Replace: false},
".": action.Repeat{Count: 1},
// ":": action.EnterComandMode{}, // Different OP
},

View File

@ -80,7 +80,7 @@ type MoveRight struct {
func (a MoveRight) Execute(m action.Model) tea.Cmd {
win := m.ActiveWindow()
buf := m.ActiveBuffer()
lineLen := len(buf.Lines[win.Cursor.Line])
lineLen := buf.Lines[win.Cursor.Line].Len()
for i := 0; i < a.Count && win.Cursor.Col <= lineLen; i++ {
win.SetCursorCol(win.Cursor.Col + 1)
}

View File

@ -50,7 +50,7 @@ type MoveToLineEnd struct{}
func (a MoveToLineEnd) Execute(m action.Model) tea.Cmd {
win := m.ActiveWindow()
buf := m.ActiveBuffer()
win.SetCursorCol(len(buf.Lines[win.Cursor.Line]))
win.SetCursorCol(buf.Lines[win.Cursor.Line].Len())
return nil
}
@ -65,7 +65,7 @@ func (a MoveToLineContentStart) Execute(m action.Model) tea.Cmd {
win := m.ActiveWindow()
buf := m.ActiveBuffer()
line := buf.Lines[win.Cursor.Line]
line := buf.Line(win.Cursor.Line)
x := 0
for x < len(line) {
ch := line[x]
@ -96,7 +96,7 @@ func (a MoveToColumn) Execute(m action.Model) tea.Cmd {
win := m.ActiveWindow()
buf := m.ActiveBuffer()
line := buf.Lines[win.Cursor.Line]
line := buf.Line(win.Cursor.Line)
col := min(a.Count-1, len(line)-1)
win.SetCursorCol(col)

View File

@ -24,7 +24,7 @@ func isWordPunctuation(c byte) bool {
// nextWordStart: Finds the start of the next word from position (x,y), handling
// word boundaries and line crossing.
func nextWordStart(buf *core.Buffer, x, y int) (int, int) {
line := buf.Lines[y]
line := buf.Line(y)
// Skip current class
if x < len(line) {
@ -59,7 +59,7 @@ func nextWordStart(buf *core.Buffer, x, y int) (int, int) {
// Move to first char of next line
y++
line = buf.Lines[y]
line = buf.Line(y)
x = 0
// If the first char of the new line is no whitespace, stay here!
@ -74,7 +74,7 @@ func nextWordStart(buf *core.Buffer, x, y int) (int, int) {
// nextWORDStart: Finds the start of the next WORD from position (x,y), treating
// all non-whitespace as a single class.
func nextWORDStart(buf *core.Buffer, x, y int) (int, int) {
line := buf.Lines[y]
line := buf.Line(y)
// Skip current WORD (all non-whitespace is one class for W)
for x < len(line) && line[x] != ' ' && line[x] != '\t' {
@ -100,7 +100,7 @@ func nextWORDStart(buf *core.Buffer, x, y int) (int, int) {
// Move to first char of next line
y++
line = buf.Lines[y]
line = buf.Line(y)
x = 0
// If the first char of the new line is no whitespace, stay here!
@ -115,7 +115,7 @@ func nextWORDStart(buf *core.Buffer, x, y int) (int, int) {
// nextWordEnd: Finds the end of the next word from position (x,y), respecting
// word character classes.
func nextWordEnd(buf *core.Buffer, x, y int) (int, int) {
line := buf.Lines[y]
line := buf.Line(y)
// Advance once to avoid being stuck on the current end
x++
@ -128,7 +128,7 @@ func nextWordEnd(buf *core.Buffer, x, y int) (int, int) {
// Otherwise, move to next line
y++
x = 0
line = buf.Lines[y]
line = buf.Line(y)
}
// Skip whitespace and cross lines if needed
@ -150,7 +150,7 @@ func nextWordEnd(buf *core.Buffer, x, y int) (int, int) {
// Move to first char of next line
y++
line = buf.Lines[y]
line = buf.Line(y)
x = 0
}
@ -174,7 +174,7 @@ func nextWordEnd(buf *core.Buffer, x, y int) (int, int) {
// nextWORDEnd: Finds the end of the next WORD from position (x,y), treating
// all non-whitespace as a single class.
func nextWORDEnd(buf *core.Buffer, x, y int) (int, int) {
line := buf.Lines[y]
line := buf.Line(y)
// Advance once to avoid being stuck on the current end
x++
@ -187,7 +187,7 @@ func nextWORDEnd(buf *core.Buffer, x, y int) (int, int) {
// Otherwise, move to next line
y++
x = 0
line = buf.Lines[y]
line = buf.Line(y)
}
// Skip whitespace and cross lines if needed
@ -209,7 +209,7 @@ func nextWORDEnd(buf *core.Buffer, x, y int) (int, int) {
// Move to first char of next line
y++
line = buf.Lines[y]
line = buf.Line(y)
x = 0
}
@ -224,7 +224,7 @@ func nextWORDEnd(buf *core.Buffer, x, y int) (int, int) {
// prevWordStart: Finds the start of the previous word from position (x,y),
// moving backward through character classes.
func prevWordStart(buf *core.Buffer, x, y int) (int, int) {
line := buf.Lines[y]
line := buf.Line(y)
// Back one to avoid being stuck on the current start
x--
@ -233,7 +233,7 @@ func prevWordStart(buf *core.Buffer, x, y int) (int, int) {
return 0, 0 // beginning of file, stay put
}
y--
line = buf.Lines[y]
line = buf.Line(y)
x = len(line) - 1
if x < 0 {
return 0, y // landed on an empty line
@ -252,7 +252,7 @@ func prevWordStart(buf *core.Buffer, x, y int) (int, int) {
return 0, 0
}
y--
line = buf.Lines[y]
line = buf.Line(y)
x = len(line) - 1
if len(line) == 0 {
return 0, y // empty line acts as a word boundary

View File

@ -68,18 +68,18 @@ func changeCharSelection(m action.Model, start, end core.Position) {
var deletedText string
if start.Line == end.Line {
line := buf.Lines[start.Line]
line := buf.Line(start.Line)
endCol := min(end.Col+1, len(line))
deletedText = line[start.Col:endCol]
buf.SetLine(start.Line, line[:start.Col]+line[endCol:])
} else {
startLine := buf.Lines[start.Line]
endLine := buf.Lines[end.Line]
startLine := buf.Line(start.Line)
endLine := buf.Line(end.Line)
// Extract deleted text
deletedText = startLine[start.Col:] + "\n"
for y := start.Line + 1; y < end.Line; y++ {
deletedText += buf.Lines[y] + "\n"
deletedText += buf.Line(y) + "\n"
}
endCol := min(end.Col+1, len(endLine))
deletedText += endLine[:endCol]
@ -113,7 +113,7 @@ func changeLineSelection(m action.Model, start, end core.Position) {
var lines []string
for i := end.Line; i >= start.Line; i-- {
lines = append([]string{buf.Lines[i]}, lines...)
lines = append([]string{buf.Line(i)}, lines...)
buf.DeleteLine(i)
}
@ -138,7 +138,7 @@ func changeBlockSelection(m action.Model, start, end core.Position) {
endCol := max(start.Col, end.Col)
for y := start.Line; y <= end.Line; y++ {
line := buf.Lines[y]
line := buf.Line(y)
if startCol >= len(line) {
continue
}
@ -168,7 +168,7 @@ func (o ChangeOperator) DoublePress(m action.Model, count int) tea.Cmd {
// Collect lines to delete (always delete at startY since lines shift up)
for range opCount {
lines = append(lines, buf.Lines[startY])
lines = append(lines, buf.Line(startY))
buf.DeleteLine(startY)
}

View File

@ -39,7 +39,7 @@ func (o DeleteOperator) DoublePress(m action.Model, count int) tea.Cmd {
for range opCount {
y := win.Cursor.Line
lines = append(lines, buf.Lines[y])
lines = append(lines, buf.Line(y))
buf.DeleteLine(y)
@ -99,12 +99,12 @@ func deleteCharSelection(m action.Model, start, end core.Position) {
buf := m.ActiveBuffer()
if start.Line == end.Line {
line := buf.Lines[start.Line]
line := buf.Line(start.Line)
endCol := min(end.Col+1, len(line))
buf.SetLine(start.Line, line[:start.Col]+line[endCol:])
} else {
startLine := buf.Lines[start.Line]
endLine := buf.Lines[end.Line]
startLine := buf.Line(start.Line)
endLine := buf.Line(end.Line)
prefix := startLine[:start.Col]
suffix := ""
@ -131,7 +131,7 @@ func deleteLineSelection(m action.Model, start, end core.Position) {
var lines []string
for i := end.Line; i >= start.Line; i-- {
lines = append(lines, buf.Lines[i])
lines = append(lines, buf.Line(i))
buf.DeleteLine(i)
}
@ -159,7 +159,7 @@ func deleteBlockSelection(m action.Model, start, end core.Position) {
endCol := max(start.Col, end.Col)
for y := start.Line; y <= end.Line; y++ {
line := buf.Lines[y]
line := buf.Line(y)
if startCol >= len(line) {
continue
}

View File

@ -51,7 +51,7 @@ func (o YankOperator) DoublePress(m action.Model, count int) tea.Cmd {
var lines []string
for i := range opCount {
lines = append(lines, buf.Lines[y+i])
lines = append(lines, buf.Line(y+i))
}
// Put her in the register!
@ -76,7 +76,7 @@ func yankNormalMode(m action.Model, start, end core.Position, mtype core.MotionT
// return
// }
line := buf.Lines[start.Line]
line := buf.Line(start.Line)
startX := min(start.Col, end.Col)
endX := max(start.Col, end.Col)
@ -106,7 +106,10 @@ func yankNormalMode(m action.Model, start, end core.Position, mtype core.MotionT
startY := min(start.Line, end.Line)
endY := max(start.Line, end.Line)
cnt := buf.Lines[startY : endY+1]
var cnt []string
for i := startY; i <= endY; i++ {
cnt = append(cnt, buf.Line(i))
}
m.UpdateDefaultRegister(core.LinewiseRegister, cnt)
}
}
@ -122,7 +125,7 @@ func yankVisualMode(m action.Model, start, end core.Position) {
// Single line selection
if start.Line == end.Line {
line := buf.Lines[start.Line]
line := buf.Line(start.Line)
endCol := min(end.Col+1, len(line)) // +1 because visual selection is inclusive
startCol := min(start.Col, len(line))
cnt := line[startCol:endCol]
@ -134,17 +137,17 @@ func yankVisualMode(m action.Model, start, end core.Position) {
var content []string
// First line: from start.Col to end of line
firstLine := buf.Lines[start.Line]
firstLine := buf.Line(start.Line)
startCol := min(start.Col, len(firstLine))
content = append(content, firstLine[startCol:])
// Middle lines: entire lines
for y := start.Line + 1; y < end.Line; y++ {
content = append(content, buf.Lines[y])
content = append(content, buf.Line(y))
}
// Last line: from beginning to end.Col (inclusive)
lastLine := buf.Lines[end.Line]
lastLine := buf.Line(end.Line)
endCol := min(end.Col+1, len(lastLine))
content = append(content, lastLine[:endCol])
@ -169,7 +172,10 @@ func yankVisualLineMode(m action.Model, start, end core.Position) {
startY := min(start.Line, end.Line)
endY := max(start.Line, end.Line)
cnt := buf.Lines[startY : endY+1]
var cnt []string
for i := startY; i <= endY; i++ {
cnt = append(cnt, buf.Line(i))
}
m.UpdateDefaultRegister(core.LinewiseRegister, cnt)
}
@ -187,7 +193,7 @@ func yankVisualBlockMode(m action.Model, start, end core.Position) {
var content []string
for y := startY; y <= endY; y++ {
line := buf.Lines[y]
line := buf.Line(y)
// Handle lines shorter than the block selection
if startX >= len(line) {

View File

@ -1,8 +1,11 @@
package style
import (
"strings"
"git.gophernest.net/azpect/TextEditor/internal/core"
"github.com/alecthomas/chroma/v2"
"github.com/alecthomas/chroma/v2/lexers"
"github.com/charmbracelet/lipgloss"
)
@ -233,3 +236,33 @@ func darkenColor(c chroma.Colour, factor float64) chroma.Colour {
b := uint8(float64(c.Blue()) * factor)
return chroma.NewColour(r, g, b)
}
// GetLexer: Uses buffer meta data or content to pick a lexer for use in applying
// highlights.
func GetLexer(buf *core.Buffer) chroma.Lexer {
var lexer chroma.Lexer
if buf.Filetype != "" {
lexer = lexers.Get(strings.TrimPrefix(buf.Filetype, "."))
}
if lexer == nil && buf.Filename != "" {
lexer = lexers.Match(buf.Filename)
}
if lexer == nil && len(buf.Lines) > 0 {
// Get first few lines for content analysis
var content strings.Builder
for i := 0; i < min(len(buf.Lines), 10); i++ {
content.WriteString(buf.Lines[i].String() + "\n")
}
lexer = lexers.Analyse(content.String())
}
if lexer == nil {
lexer = lexers.Fallback
}
lexer = chroma.Coalesce(lexer) // Merge tokens together
return lexer
}

View File

@ -75,8 +75,14 @@ func (to Delimiter) GetRange(m action.Model, cursor core.Position, modifier stri
return cursor, cursor, core.CharwiseExclusive
}
// Convert buffer lines to strings for delimiter finding
var lines []string
for i := 0; i < buf.LineCount(); i++ {
lines = append(lines, buf.Line(i))
}
// Use multi-line delimiter pair finding
start, end, found := findMultiLineDelimiterPair(buf.Lines, startDelim, endDelim, cursor, modifier == "a")
start, end, found := findMultiLineDelimiterPair(lines, startDelim, endDelim, cursor, modifier == "a")
if !found {
return cursor, cursor, core.CharwiseExclusive

View File

@ -10,7 +10,7 @@ type Word struct{}
func (to Word) GetRange(m action.Model, cursor core.Position, modifier string) (core.Position, core.Position, core.MotionType) {
buf := m.ActiveBuffer()
line := buf.Lines[cursor.Line]
line := buf.Line(cursor.Line)
// Find word boundaries
start := findWordStart(line, cursor.Col)
@ -28,7 +28,7 @@ type WORD struct{}
func (to WORD) GetRange(m action.Model, cursor core.Position, modifier string) (core.Position, core.Position, core.MotionType) {
buf := m.ActiveBuffer()
line := buf.Lines[cursor.Line]
line := buf.Line(cursor.Line)
// Find word boundaries
start := findWORDStart(line, cursor.Col)