implement the difference between the 'w' motion and 'dw' motion using the transition table in vi-word-dfa, rather than convoluted if-branching
This commit is contained in:
@@ -132,6 +132,40 @@ struct
|
|||||||
val fStart = Folder.foldNext
|
val fStart = Folder.foldNext
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
(* This is the same as StartOfNextWord, except for the `isFinal` function.
|
||||||
|
* The difference is that the `isFinal` function here considers
|
||||||
|
* the state where any character goes to a newline,
|
||||||
|
* to be a final state.
|
||||||
|
* This is because, in Vim, the 'w' motion will move past a newline
|
||||||
|
* when that newline is preceded by a non-newline character.
|
||||||
|
* However, the 'dw' motion deletes until that newline
|
||||||
|
* (not including the newline itself).
|
||||||
|
* It is easier, less fragile, and perhaps clearer,
|
||||||
|
* to implement the difference using a transition table like this
|
||||||
|
* than convoluted if-statements. *)
|
||||||
|
structure StartOfNextWordForDelete =
|
||||||
|
MakeNextDfaLoop
|
||||||
|
(struct
|
||||||
|
val startState = startState
|
||||||
|
|
||||||
|
structure Folder =
|
||||||
|
MakeCharFolderNext
|
||||||
|
(struct
|
||||||
|
val startState = startState
|
||||||
|
val tables = tables
|
||||||
|
|
||||||
|
fun isFinal currentState =
|
||||||
|
currentState = alphaToPunct orelse currentState = punctToAlpha
|
||||||
|
orelse currentState = spaceToAlpha
|
||||||
|
orelse currentState = spaceToPunct
|
||||||
|
orelse currentState = chrToNewline
|
||||||
|
|
||||||
|
fun finish x = x
|
||||||
|
end)
|
||||||
|
|
||||||
|
val fStart = Folder.foldNext
|
||||||
|
end)
|
||||||
|
|
||||||
structure EndOfPrevWord =
|
structure EndOfPrevWord =
|
||||||
MakePrevDfaLoop
|
MakePrevDfaLoop
|
||||||
(struct
|
(struct
|
||||||
@@ -232,6 +266,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 *)
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ struct
|
|||||||
|
|
||||||
(* equivalent of vi's 'w' command *)
|
(* equivalent of vi's 'w' command *)
|
||||||
val nextWord = ViWordDfa.startOfNextWord
|
val nextWord = ViWordDfa.startOfNextWord
|
||||||
|
val nextWordForDelete = ViWordDfa.startOfNextWordForDelete
|
||||||
|
|
||||||
(* equivalent of vi's 'W' command *)
|
(* equivalent of vi's 'W' command *)
|
||||||
val nextWORD = ViCapsWordDfa.startOfNextWORD
|
val nextWORD = ViCapsWordDfa.startOfNextWORD
|
||||||
|
|||||||
@@ -335,42 +335,10 @@ struct
|
|||||||
val {buffer, cursorIdx, ...} = app
|
val {buffer, cursorIdx, ...} = app
|
||||||
|
|
||||||
val buffer = LineGap.goToIdx (cursorIdx, buffer)
|
val buffer = LineGap.goToIdx (cursorIdx, buffer)
|
||||||
val high = Cursor.nextWord (buffer, cursorIdx, count)
|
val high = Cursor.nextWordForDelete (buffer, cursorIdx, count)
|
||||||
val buffer = LineGap.goToIdx (high, buffer)
|
val length = high - cursorIdx
|
||||||
in
|
in
|
||||||
(* The Cursor.nextWord skips newlines in some cases,
|
deleteAndFinish (app, cursorIdx, length, buffer, time)
|
||||||
* which makes sense for the 'w' move motion.
|
|
||||||
* However, we sometimes don't want to skip newlines when deleting.
|
|
||||||
* For example, when 'dw' is used on the last word in a line,
|
|
||||||
* the 'w' motion would go to the first character of the next line
|
|
||||||
* but the 'dw' motion should delete until the newline. *)
|
|
||||||
if high >= #textLength buffer then
|
|
||||||
let
|
|
||||||
val finish = #textLength buffer - 1
|
|
||||||
val buffer = LineGap.goToIdx (finish, buffer)
|
|
||||||
val length =
|
|
||||||
if Cursor.isCursorAtStartOfLine (buffer, finish) then
|
|
||||||
finish - cursorIdx
|
|
||||||
else
|
|
||||||
high - cursorIdx
|
|
||||||
in
|
|
||||||
deleteAndFinish (app, cursorIdx, length, buffer, time)
|
|
||||||
end
|
|
||||||
else if Cursor.isCursorAtStartOfLine (buffer, high) then
|
|
||||||
deleteAndFinish (app, cursorIdx, high - cursorIdx, buffer, time)
|
|
||||||
else
|
|
||||||
let
|
|
||||||
val beforeHigh = high - 1
|
|
||||||
val buffer = LineGap.goToIdx (beforeHigh, buffer)
|
|
||||||
val high =
|
|
||||||
if
|
|
||||||
Cursor.isCursorAtStartOfLine (buffer, beforeHigh)
|
|
||||||
andalso beforeHigh <> cursorIdx
|
|
||||||
then beforeHigh
|
|
||||||
else high
|
|
||||||
in
|
|
||||||
deleteAndFinish (app, cursorIdx, high - cursorIdx, buffer, time)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
fun deleteByDfa (app as {buffer, ...}: app_type, count, fMove, time) =
|
fun deleteByDfa (app as {buffer, ...}: app_type, count, fMove, time) =
|
||||||
|
|||||||
Reference in New Issue
Block a user