From d63201ada75538b7253b7b8eb5bc0f2ff1dda2ed Mon Sep 17 00:00:00 2001 From: Humza Shahid Date: Sun, 21 Sep 2025 17:49:30 +0100 Subject: [PATCH] reimplement vi's 'l' motion so that we only skip a newline when it is preceded by a non-newline character --- fcore/cursor-dfa/vi-l-dfa.sml | 53 +++++++++++++++++++ fcore/cursor.sml | 2 +- .../text-builder/text-builder-with-cursor.sml | 6 +-- .../text-builder-with-highlight.sml | 6 +-- shf.mlb | 1 + 5 files changed, 59 insertions(+), 9 deletions(-) create mode 100644 fcore/cursor-dfa/vi-l-dfa.sml diff --git a/fcore/cursor-dfa/vi-l-dfa.sml b/fcore/cursor-dfa/vi-l-dfa.sml new file mode 100644 index 0000000..48cb613 --- /dev/null +++ b/fcore/cursor-dfa/vi-l-dfa.sml @@ -0,0 +1,53 @@ +structure ViLDfa = +struct + val startState: Word8.word = 0w0 + val newlineState: Word8.word = 0w1 + val chrState: Word8.word = 0w2 + val newlineAfterCHrState: Word8.word = 0w3 + + fun makeStart i = + if Char.chr i = #"\n" then newlineState else chrState + + fun makeChr i = + if Char.chr i = #"\n" then newlineAfterCHrState else chrState + + val startTable = Vector.tabulate (255, makeStart) + val newlineTable = startTable + val chrTable = Vector.tabulate (255, makeChr) + val newlineAfterCHrTable = startTable + + val tables = #[startTable, newlineTable, chrTable, newlineAfterCHrTable] + + fun next (currentState, chr) = + let val table = Vector.sub (tables, Word8.toInt currentState) + in Vector.sub (table, Char.ord chr) + end + + structure ViL = + MakeNextDfaLoop + (struct + val startState = startState + + fun loop (idx, absIdx, str, tl, currentState, counter) = + if idx = String.size str then + case tl of + str :: tl => loop (0, absIdx, str, tl, currentState, counter) + | [] => absIdx + else + let + val chr = String.sub (str, idx) + val newState = next (currentState, chr) + in + if newState = newlineAfterCHrState then + loop (idx + 1, absIdx + 1, str, tl, newState, counter) + else if counter - 1 = ~1 then + absIdx + else + loop (idx + 1, absIdx + 1, str, tl, newState, counter - 1) + end + + val fStart = loop + end) + + val next = ViL.next +end diff --git a/fcore/cursor.sml b/fcore/cursor.sml index dd2fafc..c25f00a 100644 --- a/fcore/cursor.sml +++ b/fcore/cursor.sml @@ -56,7 +56,7 @@ struct val viDlr = ViDlrDfa.next val viDlrForDelete = ViDlrDfa.nextForDelete - val viL = ViHlDfa.l + val viL = ViLDfa.next val viH = ViHlDfa.h fun helpGetCursorColumn (distanceFromLine, strList, lineList) = diff --git a/fcore/text-builder/text-builder-with-cursor.sml b/fcore/text-builder/text-builder-with-cursor.sml index bd980a4..48c5863 100644 --- a/fcore/text-builder/text-builder-with-cursor.sml +++ b/fcore/text-builder/text-builder-with-cursor.sml @@ -137,8 +137,6 @@ struct acc else let - val posX = #startX env - val posY = posY + TC.ySpace val acc = if absIdx = cursorIdx then Utils.makeCursor (posX, posY, env) :: acc @@ -151,8 +149,8 @@ struct , stl , line , ltl - , posX - , posY + , #startX env + , posY + TC.ySpace , 0 , lineNumber + 1 , absIdx + 1 diff --git a/fcore/text-builder/text-builder-with-highlight.sml b/fcore/text-builder/text-builder-with-highlight.sml index aba1a14..ce8daea 100644 --- a/fcore/text-builder/text-builder-with-highlight.sml +++ b/fcore/text-builder/text-builder-with-highlight.sml @@ -234,8 +234,6 @@ struct acc else let - val posX = #startX env - val posY = posY + TC.ySpace val acc = if absIdx = cursorIdx then Utils.makeCursor (posX, posY, env) :: acc @@ -248,8 +246,8 @@ struct , stl , line , ltl - , posX - , posY + , #startX env + , posY + TC.ySpace , 0 , lineNumber + 1 , absIdx + 1 diff --git a/shf.mlb b/shf.mlb index 88f8575..e12d73f 100644 --- a/shf.mlb +++ b/shf.mlb @@ -34,6 +34,7 @@ in fcore/cursor-dfa/vi-word-dfa.sml fcore/cursor-dfa/vi-caps-word-dfa.sml fcore/cursor-dfa/vi-dlr-dfa.sml + fcore/cursor-dfa/vi-l-dfa.sml fcore/cursor-dfa/vi-hl-dfa.sml fcore/rect.sml fcore/pipe-cursor.sml