U45XPF3YKPXXRJ4MN24T2RV7GOL4FZKQSWX5P5I7WT4HC5XF4FHAC winBuf := winBuf ++ st.config.statusBarStyle ++ statusStr.trimAscii ++ Terminal.clearLineStr ++ st.config.resetStyle
winBuf := winBuf.push st.config.statusBarStylewinBuf := winBuf.push statusStr.trimAscii.toStringwinBuf := winBuf.push Terminal.clearLineStrwinBuf := winBuf.push st.config.resetStyle
-- Simple prepend and filter to keep it fresh. In a real editor we might want to cap the size.let newMap := (r, s) :: (c.lineMap.filter (fun (row, _) => row != r)){ lineMap := if newMap.length > 200 then newMap.take 200 else newMap }
{ lineMap := c.lineMap.insert r s }
/-- Insert text at offset -/
/--Insert text at the specified offset.params:- offset: The byte offset where insertion begins.- text: The string content to insert.- cursorOffset: The cursor position *after* this insertion, stored in the undo stackto restore cursor position when undoing this operation.-/
/-- Delete range [offset, offset + length) -/
/--Delete a range of text.params:- offset: The starting byte offset of the range to delete.- length: The number of bytes to delete.- cursorOffset: The cursor position *after* this deletion, stored in the undo stackto restore cursor position when undoing this operation.-/
def PieceTable.length (pt : PieceTable) : Nat := pt.tree.length/-- Check if the piece table buffer ends with a newline character.Optimized to avoid converting the entire buffer to string. -/def PieceTable.endsWithNewline (pt : PieceTable) : Bool :=let len := pt.lengthif len == 0 then falseelselet s := PieceTree.getSubstring pt.tree (len - 1) len pts == "\n"
def main : IO Unit := dotest
import ViE.Typesimport ViE.Buffer.Contentimport ViE.State.Layoutimport ViE.State.Movementnamespace Test.Utils/-- Assert condition is true, throw error if false -/def assert (msg : String) (cond : Bool) : IO Unit := doif cond thenIO.println s!"[PASS] {msg}"elseIO.println s!"[FAIL] {msg}"throw (IO.userError s!"Assertion failed: {msg}")/-- Assert equality with debug output -/def assertEqual [Repr α] [BEq α] (msg : String) (expected actual : α) : IO Unit := doif expected == actual thenIO.println s!"[PASS] {msg}"elseIO.println s!"[FAIL] {msg}"IO.println s!" Expected: {repr expected}"IO.println s!" Actual: {repr actual}"throw (IO.userError s!"Assertion failed: {msg}")/-- Assert EditorState buffer content matches expected string -/def assertBuffer (msg : String) (est : ViE.EditorState) (expected : String) : IO Unit := dolet actual := est.getActiveBuffer.table.toStringif actual == expected thenIO.println s!"[PASS] {msg}"elseIO.println s!"[FAIL] {msg}"IO.println s!" Expected: '{expected}'"IO.println s!" Actual: '{actual}'"throw (IO.userError s!"Buffer content assertion failed: {msg}")/-- Assert EditorState cursor position matches expected row/col -/def assertCursor (msg : String) (est : ViE.EditorState) (r c : Nat) : IO Unit := dolet cursor := est.getCursorif cursor.row.val == r && cursor.col.val == c thenIO.println s!"[PASS] {msg}"elseIO.println s!"[FAIL] {msg}"IO.println s!" Expected: ({r}, {c})"IO.println s!" Actual: ({cursor.row.val}, {cursor.col.val})"throw (IO.userError s!"Cursor assertion failed: {msg}")end Test.Utils
import ViE.Data.PieceTableimport Test.Utilsopen ViEnamespace Test.PieceTable.UndoRedoopen Test.Utilsdef testUndoRedo : IO Unit := doIO.println "testUndoRedo..."let pt := PieceTable.fromString ""-- Insert "A" at 0let pt1 := pt.insert 0 "A" 0-- Insert "B" at 0 (Prepend) -> "BA"let pt2 := pt1.insert 0 "B" 0assertEqual "Initial state" "BA" pt2.toString-- Undo B (restores to "A")let (pt3, _) := pt2.undo 0assertEqual "After Undo 1" "A" pt3.toString-- Undo Alet (pt4, _) := pt3.undo 0assertEqual "After Undo 2" "" pt4.toString-- Redo Alet (pt5, _) := pt4.redo 0assertEqual "After Redo 1" "A" pt5.toString-- Redo Blet (pt6, _) := pt5.redo 0assertEqual "After Redo 2" "BA" pt6.toStringdef testComplexUndo : IO Unit := doIO.println "testComplexUndo..."let pt := PieceTable.fromString "Base"let pt1 := pt.insert 4 "1" 4 -- Base1let pt1 := pt1.commit -- Prevent mergelet pt2 := pt1.insert 5 "2" 5 -- Base12let pt3 := pt2.delete 5 1 5 -- Base1let pt4 := pt3.insert 5 "3" 5 -- Base13assertEqual "State before undo" "Base13" pt4.toString-- Undo insert "3" -> Base1let (u1, _) := pt4.undo 0assertEqual "Undo 3" "Base1" u1.toString-- Undo delete "2" -> Base12let (u2, _) := u1.undo 0assertEqual "Undo delete 2" "Base12" u2.toString-- Undo insert "2" -> Base1let (u3, _) := u2.undo 0assertEqual "Undo insert 2" "Base1" u3.toString-- Undo insert "1" -> Baselet (u4, _) := u3.undo 0assertEqual "Undo insert 1" "Base" u4.toStringdef test : IO Unit := doIO.println "Starting PieceTable Undo/Redo Test..."testUndoRedotestComplexUndoIO.println "PieceTable Undo/Redo Test passed!"end Test.PieceTable.UndoRedo
import ViE.Data.PieceTableimport Test.Utilsopen ViEnamespace Test.PieceTable.Stressopen Test.Utils/-- Naive string manipulation for verification -/def naiveInsert (s : String) (idx : Nat) (content : String) : String :=let lst := s.toListlet pre := lst.take idxlet post := lst.drop idxString.ofList (pre ++ content.toList ++ post)def naiveDelete (s : String) (idx : Nat) (len : Nat) : String :=let lst := s.toListlet pre := lst.take idxlet post := lst.drop (idx + len)String.ofList (pre ++ post)def testConsistency : IO Unit := doIO.println "testConsistency (Small Stress)..."let mut pt := PieceTable.fromString ""let mut mirror := ""-- 1. Insert Hellopt := pt.insert 0 "Hello" 0mirror := naiveInsert mirror 0 "Hello"assertEqual "Step 1" mirror pt.toString-- 2. Insert Worldpt := pt.insert 5 " World" 5mirror := naiveInsert mirror 5 " World"assertEqual "Step 2" mirror pt.toString-- 3. Delete space at 5-- "Hello World" -> "HelloWorld"pt := pt.delete 5 1 5mirror := naiveDelete mirror 5 1assertEqual "Step 3" mirror pt.toString-- 4. Insert comma at 5-- "HelloWorld" -> "Hello,World"pt := pt.insert 5 "," 5mirror := naiveInsert mirror 5 ","assertEqual "Step 4" mirror pt.toStringdef test : IO Unit := doIO.println "Starting PieceTable Stress Test..."testConsistencyIO.println "PieceTable Stress Test passed!"end Test.PieceTable.Stress
import ViE.Data.PieceTableimport Test.Utilsopen ViEnamespace Test.PieceTable.Basicopen Test.Utilsdef testInsert : IO Unit := doIO.println "testInsert..."let pt := PieceTable.fromString "Hello"-- Insert at endlet pt1 := pt.insert 5 " World" 5assertEqual "Insert at end" "Hello World" pt1.toString-- Insert at middlelet pt2 := pt1.insert 5 "," 5assertEqual "Insert at middle" "Hello, World" pt2.toString-- Insert at startlet pt3 := pt2.insert 0 "Say: " 0assertEqual "Insert at start" "Say: Hello, World" pt3.toStringdef testDelete : IO Unit := doIO.println "testDelete..."let pt := PieceTable.fromString "Hello, World!"-- Delete "World" (offset 7, len 5)let pt1 := pt.delete 7 5 7assertEqual "Delete middle" "Hello, !" pt1.toString-- Delete startlet pt2 := pt1.delete 0 7 0assertEqual "Delete start" "!" pt2.toString-- Delete endlet pt3 := pt2.delete 0 1 0assertEqual "Delete end" "" pt3.toStringdef test : IO Unit := doIO.println "Starting PieceTable Basic Test..."testInserttestDeleteIO.println "PieceTable Basic Test passed!"end Test.PieceTable.Basic
import ViE.Data.PieceTableimport Test.Utilsopen ViEnamespace Test.PieceTable.Appendedopen Test.Utilsdef testAppends : IO Unit := doIO.println "testAppends..."let pt := PieceTable.fromString "Line1\n"-- Append Line 2let pt1 := pt.insert pt.length "Line2\n" pt.lengthassertEqual "Append 1" "Line1\nLine2\n" pt1.toString-- Append Line 3let pt2 := pt1.insert pt1.length "Line3" pt1.lengthassertEqual "Append 2" "Line1\nLine2\nLine3" pt2.toStringdef test : IO Unit := doIO.println "Starting PieceTable Appended Test..."testAppendsIO.println "PieceTable Appended Test passed!"end Test.PieceTable.Appended
if s_l.getCursor != Point.make 0 1 thenlet c := s_l.getCursorlet line := ViE.getLineFromBuffer s_l.getActiveBuffer c.row |>.getD "ERR"let len := ViE.getLineLengthFromBuffer s_l.getActiveBuffer c.row |>.getD 999IO.println s!"DEBUG FAILURE: l motion. Cursor: ({c.row.val}, {c.col.val}). Line 0: '{line}' (len: {len})"assert "l moves right" (s_l.getCursor == Point.make 0 1)
let p_res := s_p.getActiveBuffer.table.toStringif p_res != "line1\nline2\nline3\nline1\n" thenIO.println s!"DEBUG FAILURE: p paste. Expected 'line1\\nline2\\nline3\\nline1\\n', got '{p_res}'"assert "p pastes below" (s_p.getActiveBuffer.table.toString == "line1\nline2\nline3\nline1\n")
assertBuffer "p pastes below" s_p "line1\nline2\nline3\nline1\n"
let text2 := (s2.getActiveBuffer.table.toString)assert "Text after undo" (text2 == "")-- Cursor check: Should be back at (0, 0)let c2 := s2.getCursorassert s!"Cursor after undo should be (0,0) but is ({c2.row.val}, {c2.col.val})" (c2.row.val == 0 && c2.col.val == 0)
assertBuffer "Text after undo" s2 ""assertCursor "Cursor after undo should be (0,0)" s2 0 0
assert "Text after re-insert d" (text3 == "d")let c3 := s3.getCursorassert s!"Cursor after insert 'd' and Esc should be (0,0) but is ({c3.row.val}, {c3.col.val})" (c3.row.val == 0 && c3.col.val == 0)
assertBuffer "Text after re-insert d" s3 "d"assertCursor "Cursor after insert 'd' and Esc should be (0,0)" s3 0 0