refactor Cursor.viH to use DFA
This commit is contained in:
@@ -4,19 +4,30 @@ struct
|
||||
val notNewlineState: Word8.word = 0w1
|
||||
val oneNewlineState: Word8.word = 0w2
|
||||
val twoNewlineState: Word8.word = 0w3
|
||||
val notNewlineAfterNewlineState: Word8.word = 0w4
|
||||
|
||||
fun makeStart i =
|
||||
if Char.chr i = #"\n" then oneNewlineState else notNewlineState
|
||||
|
||||
fun makeOneNewline i =
|
||||
if Char.chr i = #"\n" then twoNewlineState else notNewlineState
|
||||
if Char.chr i = #"\n" then twoNewlineState else notNewlineAfterNewlineState
|
||||
|
||||
fun makeTwoNeline i =
|
||||
if Char.chr i = #"\n" then oneNewlineState else notNewlineAfterNewlineState
|
||||
|
||||
val startTable = Vector.tabulate (255, makeStart)
|
||||
val notNewlineTable = startTable
|
||||
val oneNewlineTable = Vector.tabulate (255, makeOneNewline)
|
||||
val twoNewLineTable = startTable
|
||||
val notNewlineAfterNewlineTable = notNewlineTable
|
||||
|
||||
val tables = #[startTable, notNewlineTable, oneNewlineTable, twoNewLineTable]
|
||||
val tables =
|
||||
#[ startTable
|
||||
, notNewlineTable
|
||||
, oneNewlineTable
|
||||
, twoNewLineTable
|
||||
, notNewlineAfterNewlineTable
|
||||
]
|
||||
|
||||
fun next (currentState, chr) =
|
||||
let val table = Vector.sub (tables, Word8.toInt currentState)
|
||||
@@ -38,12 +49,17 @@ struct
|
||||
val chr = String.sub (str, idx)
|
||||
val newState = next (currentState, chr)
|
||||
in
|
||||
if newState = twoNewlineState then
|
||||
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
|
||||
else if
|
||||
newState = notNewlineState
|
||||
orelse newState = notNewlineAfterNewlineState
|
||||
then
|
||||
if counter - 1 = ~1 then
|
||||
absIdx
|
||||
else
|
||||
@@ -55,5 +71,43 @@ struct
|
||||
val fStart = loop
|
||||
end)
|
||||
|
||||
structure ViH =
|
||||
MakePrevDfaLoop
|
||||
(struct
|
||||
val startState = startState
|
||||
|
||||
fun loop (idx, absIdx, str, tl, currentState, counter) =
|
||||
if idx < 0 then
|
||||
case tl of
|
||||
str :: tl =>
|
||||
loop
|
||||
(String.size str - 1, 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
|
||||
else loop (idx - 1, absIdx - 1, str, tl, newState, 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 if newState = notNewlineAfterNewlineState then
|
||||
if counter - 1 <= 0 then
|
||||
absIdx
|
||||
else
|
||||
loop (idx - 1, absIdx - 1, str, tl, startState, counter - 1)
|
||||
else
|
||||
loop (idx - 1, absIdx - 1, str, tl, newState, counter)
|
||||
end
|
||||
|
||||
val fStart = loop
|
||||
end)
|
||||
|
||||
val next = ViL.next
|
||||
val prev = ViH.prev
|
||||
end
|
||||
|
||||
@@ -57,77 +57,7 @@ struct
|
||||
val viDlrForDelete = ViDlrDfa.nextForDelete
|
||||
|
||||
val viL = ViLDfa.next
|
||||
|
||||
structure ViH =
|
||||
MakeIfCharFolderPrev
|
||||
(struct
|
||||
type env = unit
|
||||
|
||||
fun helpViH (strIdx, hd, cursorIdx, leftStrings) =
|
||||
if strIdx > 0 then
|
||||
(* bounds check: can access prev char in hd *)
|
||||
if String.sub (hd, strIdx - 1) = #"\n" then
|
||||
(* prev char is line break *)
|
||||
if strIdx - 1 > 0 then
|
||||
(* bounds check: can access two chars back in hd *)
|
||||
if String.sub (hd, strIdx - 2) = #"\n" then
|
||||
(* line break followed by line break
|
||||
* so it is fine to decrement by 1 *)
|
||||
cursorIdx - 1
|
||||
else
|
||||
(* non-line break followed by line break
|
||||
* so we have to decrement by two,
|
||||
* skipping over line break *)
|
||||
cursorIdx - 2
|
||||
else
|
||||
(* need to check two chars back in leftStrings *)
|
||||
(case leftStrings of
|
||||
lhd :: ltl =>
|
||||
if String.sub (lhd, String.size lhd - 1) = #"\n" then
|
||||
(* double line break *)
|
||||
cursorIdx - 1
|
||||
else
|
||||
(* non-line break precedes line break *)
|
||||
cursorIdx - 2
|
||||
| [] => cursorIdx - 1)
|
||||
else
|
||||
(* prev char is not line break so we can decrement by 1 *)
|
||||
cursorIdx - 1
|
||||
else
|
||||
(* prev char is in leftStrings *)
|
||||
(case leftStrings of
|
||||
lhd :: ltl =>
|
||||
if String.sub (lhd, String.size lhd - 1) = #"\n" then
|
||||
(* one line break *)
|
||||
if String.size lhd > 1 then
|
||||
(* bounds check: prev-prev chr is in lhd *)
|
||||
if String.sub (lhd, String.size lhd - 2) = #"\n" then
|
||||
(* double line break *)
|
||||
cursorIdx - 1
|
||||
else
|
||||
(* non-line break precedes line break *)
|
||||
cursorIdx - 2
|
||||
else
|
||||
(* prev-prev chr is in ltl *)
|
||||
(case ltl of
|
||||
ltlhd :: _ =>
|
||||
if String.sub (ltlhd, String.size ltlhd - 1) = #"\n" then
|
||||
(* double line break *)
|
||||
cursorIdx - 1
|
||||
else
|
||||
(* non-line break precedes line break *)
|
||||
cursorIdx - 2
|
||||
| [] => cursorIdx - 1)
|
||||
else
|
||||
(* no line break *)
|
||||
cursorIdx - 1
|
||||
| [] => 0)
|
||||
|
||||
fun fStart (strIdx, hd, _, cursorIdx, leftStrings, _, _) =
|
||||
helpViH (strIdx, hd, cursorIdx, leftStrings)
|
||||
end)
|
||||
|
||||
fun viH (lineGap, cursorIdx) = ViH.foldPrev (lineGap, cursorIdx, ())
|
||||
val viH = ViLDfa.prev
|
||||
|
||||
fun helpGetCursorColumn (distanceFromLine, strList, lineList) =
|
||||
case (strList, lineList) of
|
||||
|
||||
@@ -42,7 +42,6 @@ struct
|
||||
end
|
||||
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)
|
||||
|
||||
@@ -76,6 +75,7 @@ struct
|
||||
end
|
||||
end
|
||||
|
||||
structure MoveViH = MakeDfaMove (struct val fMove = Cursor.viH end)
|
||||
structure MoveViL = MakeDfaMove (struct val fMove = Cursor.viL end)
|
||||
|
||||
structure MoveToNextWord = MakeDfaMove (struct val fMove = Cursor.nextWord end)
|
||||
|
||||
@@ -337,7 +337,7 @@ struct
|
||||
else
|
||||
let
|
||||
val buffer = LineGap.goToIdx (low, buffer)
|
||||
val low = Cursor.viH (buffer, low)
|
||||
val low = Cursor.viH (buffer, low, 1)
|
||||
val buffer = LineGap.goToIdx (low, buffer)
|
||||
val low = Cursor.vi0 (buffer, low)
|
||||
val newCount = if low = 0 then 0 else count - 1
|
||||
|
||||
@@ -250,7 +250,7 @@ struct
|
||||
fun parseDeleteTerminal (str, count, app, chrCmd, time) =
|
||||
case chrCmd of
|
||||
(* terminal commands: require no input after *)
|
||||
#"h" => NormalDelete.delete (app, count, Cursor.viH, time)
|
||||
#"h" => NormalDelete.deleteByDfa (app, count, Cursor.viH, 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
|
||||
@@ -346,7 +346,7 @@ struct
|
||||
fun parseDeleteTerminal (str, count, app, chrCmd, time) =
|
||||
case chrCmd of
|
||||
(* terminal commands: require no input after *)
|
||||
#"h" => NormalYankDelete.delete (app, count, Cursor.viH, time)
|
||||
#"h" => NormalYankDelete.deleteByDfa (app, count, Cursor.viH, 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
|
||||
|
||||
Reference in New Issue
Block a user