fix bugs in vi-l-dfa (we want to stop looping when the counter is ~1, because the starting character will likely be final/a not-newline, and we want to loop at least once; also, we want to special case 'twoNewlineState' as a final case which causes us to go backwards by 1 instead of treating 'oneNewlineState' as a final/special case). We also modify other code to use the new vi-l implementation in the program.

This commit is contained in:
2025-09-17 03:52:31 +01:00
parent 5174a5b0a4
commit 9ddb5f68d7
6 changed files with 40 additions and 68 deletions

View File

@@ -18,24 +18,41 @@ struct
val tables = #[startTable, notNewlineTable, oneNewlineTable, twoNewLineTable]
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
structure Folder =
MakeCharFolderNext
(struct
val startState = startState
val tables = tables
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 = twoNewlineState then
if counter - 1 = ~1 then
absIdx - 1
else
loop (idx + 1, absIdx + 1, str, tl, startState, counter - 1)
else if newState = notNewlineState then
if counter - 1 = ~1 then
absIdx
else
loop (idx + 1, absIdx + 1, str, tl, startState, counter - 1)
else
loop (idx + 1, absIdx + 1, str, tl, newState, counter)
end
fun finish x = x
fun isFinal currentState =
currentState = notNewlineState
orelse currentState = oneNewlineState
end)
val fStart = Folder.foldNext
val fStart = loop
end)
val next = ViL.next

View File

@@ -56,56 +56,7 @@ struct
val viDlr = ViDlrDfa.next
val viDlrForDelete = ViDlrDfa.nextForDelete
fun helpViL (strIdx, hd, cursorIdx, tl) =
if String.sub (hd, strIdx) = #"\n" then
(* if line break, go to next idx, no matter what chr is there *)
cursorIdx + 1
else if strIdx + 1 < String.size hd then
(* next chr is in hd *)
if String.sub (hd, strIdx + 1) = #"\n" then
(* if non-line break followed by line break, go to chr + 2 *)
cursorIdx + 2
else
cursorIdx + 1
else
(case tl of
tlhd :: _ =>
if String.sub (tlhd, 0) = #"\n" then
(* non-line break followed by line break *)
cursorIdx + 2
else
(* non-line break followed by non-line break *)
cursorIdx + 1
| [] => cursorIdx)
(* Prerequisite: lineGap is moved to requested idx first
* todo: check if we are in a \r\n pair, but this is not a priority *)
fun viL (lineGap: LineGap.t, cursorIdx) =
let
val {rightStrings, idx = bufferIdx, ...} = lineGap
in
case rightStrings of
hd :: tl =>
let
(* convert absolute cursorIdx to idx relative to hd string *)
val strIdx = cursorIdx - bufferIdx
in
if strIdx < String.size hd then
(* strIdx is in hd *)
helpViL (strIdx, hd, cursorIdx, tl)
else
(* strIdx is in tl *)
(case tl of
tlhd :: tltl =>
let val strIdx = strIdx - String.size hd
in helpViL (strIdx, tlhd, cursorIdx, tltl)
end
| [] => cursorIdx)
end
| [] =>
(* return original cursorIdx if there is nothing to the right *)
cursorIdx
end
val viL = ViLDfa.next
structure ViH =
MakeIfCharFolderPrev

View File

@@ -45,7 +45,6 @@ end
structure MoveViH = MakeMove (struct val fMove = Cursor.viH end)
structure MoveViJ = MakeMove (struct val fMove = Cursor.viJ end)
structure MoveViK = MakeMove (struct val fMove = Cursor.viK end)
structure MoveViL = MakeMove (struct val fMove = Cursor.viL end)
structure MoveToStartOfLine = MakeMove (struct val fMove = Cursor.vi0 end)
@@ -77,6 +76,8 @@ struct
end
end
structure MoveViL = MakeDfaMove (struct val fMove = Cursor.viL end)
structure MoveToNextWord = MakeDfaMove (struct val fMove = Cursor.nextWord end)
structure MoveToNextWORD = MakeDfaMove (struct val fMove = Cursor.nextWORD end)

View File

@@ -48,7 +48,7 @@ struct
val buffer = LineGap.goToIdx (lineStart, buffer)
val lineEnd = Cursor.viDlr (buffer, lineStart, 1)
val buffer = LineGap.goToIdx (lineEnd, buffer)
val nextLine = Cursor.viL (buffer, lineEnd)
val nextLine = Cursor.viL (buffer, lineEnd, 1)
val count = if lineEnd = nextLine then 0 else count - 1
in
@@ -83,7 +83,7 @@ struct
val buffer = LineGap.goToIdx (lineStart, buffer)
val lineEnd = Cursor.viDlr (buffer, lineStart, 1)
val buffer = LineGap.goToIdx (lineEnd, buffer)
val nextLine = Cursor.viL (buffer, lineEnd)
val nextLine = Cursor.viL (buffer, lineEnd, 1)
val count = if lineEnd = nextLine then 0 else count - 1
in
@@ -115,7 +115,7 @@ struct
val buffer = LineGap.goToIdx (lineStart, buffer)
val lineEnd = Cursor.viDlr (buffer, lineStart, 1)
val buffer = LineGap.goToIdx (lineEnd, buffer)
val nextLine = Cursor.viL (buffer, lineEnd)
val nextLine = Cursor.viL (buffer, lineEnd, 1)
val newCursorIdx = Int.min (lineEnd, cursorIdx)
val buffer =
@@ -251,7 +251,7 @@ struct
case chrCmd of
(* terminal commands: require no input after *)
#"h" => NormalDelete.delete (app, count, Cursor.viH, time)
| #"l" => NormalDelete.delete (app, count, Cursor.viL, time)
| #"l" => NormalDelete.deleteByDfa (app, count, Cursor.viL, time)
(* vi's 'j' and 'k' commands move up or down a column
* but 'dj' or 'dk' delete whole lines
* so their implementation differs from
@@ -347,7 +347,7 @@ struct
case chrCmd of
(* terminal commands: require no input after *)
#"h" => NormalYankDelete.delete (app, count, Cursor.viH, time)
| #"l" => NormalYankDelete.delete (app, count, Cursor.viL, time)
| #"l" => NormalYankDelete.deleteByDfa (app, count, Cursor.viL, time)
(* vi's 'j' and 'k' commands move up or down a column
* but 'dj' or 'dk' delete whole lines
* so their implementation differs from

View File

@@ -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/rect.sml
fcore/pipe-cursor.sml
end
@@ -60,6 +61,7 @@ fcore/normal-mode/normal-search-mode.sml
fcore/app-update.sml
(* TEST FILES *)
$(SML_LIB)/basis/mlton.mlb
shell/exception-logger.sml

View File

@@ -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/rect.sml
fcore/pipe-cursor.sml
end