change vi-caps-word-dfa.sml to regard newlines as final states, as with vi-word-dfa.sml in previous commit

This commit is contained in:
2025-12-27 09:35:32 +00:00
parent 1df0952f08
commit 5c5910f748
3 changed files with 90 additions and 23 deletions

View File

@@ -5,27 +5,52 @@ struct
val startSpaceState: Word8.word = 0w2 val startSpaceState: Word8.word = 0w2
val nonBlankAfterSpaceState: Word8.word = 0w3 val nonBlankAfterSpaceState: Word8.word = 0w3
val spaceAfterNonBlankState = 0w4 val spaceAfterNonBlankState = 0w4
val startNewline: Word8.word = 0w5
val newlineToNewline: Word8.word = 0w6
val chrToNewline: Word8.word = 0w07
fun makeStart i = fun makeStart i =
let val chr = Char.chr i let
in if Char.isSpace chr then startSpaceState else startNonBlankState val chr = Char.chr i
in
if chr = #"\n" then startNewline
else if Char.isSpace chr then startSpaceState
else startNonBlankState
end end
fun makeStartNonBlankState i = fun makeStartNonBlankState i =
let val chr = Char.chr i let
in if Char.isSpace chr then spaceAfterNonBlankState else startNonBlankState val chr = Char.chr i
in
if chr = #"\n" then chrToNewline
else if Char.isSpace chr then spaceAfterNonBlankState
else startNonBlankState
end end
fun makeStartSpace i = fun makeStartSpace i =
let val chr = Char.chr i let
in if Char.isSpace chr then startSpaceState else nonBlankAfterSpaceState val chr = Char.chr i
in
if chr = #"\n" then chrToNewline
else if Char.isSpace chr then startSpaceState
else nonBlankAfterSpaceState
end end
fun makeNonBlankAfterSpace i = fun makeNonBlankAfterSpace i =
let let
val chr = Char.chr i val chr = Char.chr i
in in
if Char.isSpace chr then spaceAfterNonBlankState if chr = #"\n" then chrToNewline
else if Char.isSpace chr then spaceAfterNonBlankState
else nonBlankAfterSpaceState
end
fun makeStartNewline i =
let
val chr = Char.chr i
in
if chr = #"\n" then newlineToNewline
else if Char.isSpace chr then startSpaceState
else nonBlankAfterSpaceState else nonBlankAfterSpaceState
end end
@@ -34,6 +59,7 @@ struct
val startSpaceTable = Vector.tabulate (255, makeStartSpace) val startSpaceTable = Vector.tabulate (255, makeStartSpace)
val nonBlankAfterSpaceTable = Vector.tabulate (255, makeNonBlankAfterSpace) val nonBlankAfterSpaceTable = Vector.tabulate (255, makeNonBlankAfterSpace)
val spaceAfterNonBlankTable = nonBlankAfterSpaceTable val spaceAfterNonBlankTable = nonBlankAfterSpaceTable
val newlineTable = Vector.tabulate (255, makeStartNewline)
val tables = val tables =
#[ startTable #[ startTable
@@ -41,6 +67,9 @@ struct
, startSpaceTable , startSpaceTable
, nonBlankAfterSpaceTable , nonBlankAfterSpaceTable
, spaceAfterNonBlankTable , spaceAfterNonBlankTable
, newlineTable
, newlineTable
, newlineTable
] ]
structure StartOfNextWORD = structure StartOfNextWORD =
@@ -55,8 +84,31 @@ struct
val tables = tables val tables = tables
fun finish x = x fun finish x = x
fun isFinal currentState = fun isFinal currentState =
currentState = nonBlankAfterSpaceState currentState = nonBlankAfterSpaceState
orelse currentState = newlineToNewline
end)
val fStart = Folder.foldNext
end)
structure StartOfNextWORDForDelete =
MakeNextDfaLoop
(struct
val startState = startState
structure Folder =
MakeCharFolderNext
(struct
val startState = startState
val tables = tables
fun finish x = x
fun isFinal currentState =
currentState = nonBlankAfterSpaceState
orelse currentState = chrToNewline
end) end)
val fStart = Folder.foldNext val fStart = Folder.foldNext
@@ -74,6 +126,7 @@ struct
val tables = tables val tables = tables
fun finish x = x fun finish x = x
fun isFinal currentState = fun isFinal currentState =
currentState = nonBlankAfterSpaceState currentState = nonBlankAfterSpaceState
end) end)
@@ -87,7 +140,11 @@ struct
val startState = startState val startState = startState
val tables = tables val tables = tables
fun isFinal currentState = currentState = spaceAfterNonBlankState fun isFinal currentState =
currentState = spaceAfterNonBlankState
orelse currentState = chrToNewline
orelse currentState = newlineToNewline
fun finish idx = idx + 1 fun finish idx = idx + 1
end) end)
@@ -105,13 +162,17 @@ struct
val fStart = StartOfCurrentWORDFolder.foldPrev val fStart = StartOfCurrentWORDFolder.foldPrev
end) end)
fun endOfCurrentWORDFolderIsFinal currentState =
currentState = spaceAfterNonBlankState orelse currentState = chrToNewline
structure EndOfCurrentWORDFolder = structure EndOfCurrentWORDFolder =
MakeCharFolderNext MakeCharFolderNext
(struct (struct
val startState = startState val startState = startState
val tables = tables val tables = tables
fun isFinal currentState = currentState = spaceAfterNonBlankState val isFinal = endOfCurrentWORDFolderIsFinal
fun finish idx = fun finish idx =
Int.max (0, idx - 1) Int.max (0, idx - 1)
end) end)
@@ -134,8 +195,8 @@ struct
val startState = startState val startState = startState
val tables = tables val tables = tables
fun isFinal currentState = val isFinal = endOfCurrentWORDFolderIsFinal
currentState = spaceAfterNonBlankState
fun finish idx = idx fun finish idx = idx
end) end)
@@ -151,6 +212,7 @@ struct
(* W *) (* W *)
val startOfNextWORD = StartOfNextWORD.next val startOfNextWORD = StartOfNextWORD.next
val startOfNextWORDForDelete = StartOfNextWORDForDelete.next
(* gE *) (* gE *)
val endOfPrevWORD = EndOfPrevWORD.prev val endOfPrevWORD = EndOfPrevWORD.prev
(* B *) (* B *)

View File

@@ -181,6 +181,9 @@ struct
currentState = alphaToPunct orelse currentState = punctToAlpha currentState = alphaToPunct orelse currentState = punctToAlpha
orelse currentState = spaceToAlpha orelse currentState = spaceToAlpha
orelse currentState = spaceToPunct orelse currentState = spaceToPunct
orelse currentState = newlineToNewline
orelse currentState = newlineToAlpha
orelse currentState = newlineToPunct
fun finish x = x fun finish x = x
end) end)

View File

@@ -782,18 +782,20 @@ struct
in in
Expect.isTrue (chr = #"w") Expect.isTrue (chr = #"w")
end) end)
, test "moves cursor past newline when next WORD is after newline" (fn _ => , test
"moves cursor to first char-after-newline \
\when cursor is on last word of line \
\and there is another line after this one"
(fn _ =>
let let
(* arrange *) (* arrange *)
val app = TestUtils.init "hello \n\n\n world\n" val app = TestUtils.init "hello \n\n\n world\n"
(* act *) (* act *)
val app = TestUtils.update (app, CHAR_EVENT #"W") val {cursorIdx, ...} = TestUtils.update (app, CHAR_EVENT #"W")
(* assert *)
val cursorChr = getChr app
in in
Expect.isTrue (cursorChr = #"w") (* assert *)
Expect.isTrue (cursorIdx = 7)
end) end)
, test "does not break on punctuation when cursor is on alphanumeric char" , test "does not break on punctuation when cursor is on alphanumeric char"
(fn _ => (fn _ =>