amend 'dw' motion in line with previous commit
This commit is contained in:
@@ -16,8 +16,11 @@ struct
|
||||
val newlineToNewline: Word8.word = 0w9
|
||||
val chrToNewline: Word8.word = 0w10
|
||||
|
||||
val alphaToPunct: Word8.word = 0w11
|
||||
val punctToAlpha: Word8.word = 0w12
|
||||
val newlineToAlpha: Word8.word = 0w11
|
||||
val newlineToPunct: Word8.word = 0w12
|
||||
|
||||
val alphaToPunct: Word8.word = 0w13
|
||||
val punctToAlpha: Word8.word = 0w14
|
||||
|
||||
fun makeStart i =
|
||||
let
|
||||
@@ -63,10 +66,10 @@ struct
|
||||
let
|
||||
val chr = Char.chr i
|
||||
in
|
||||
if Char.isAlphaNum chr orelse chr = #"_" then startAlpha
|
||||
if Char.isAlphaNum chr orelse chr = #"_" then newlineToAlpha
|
||||
else if chr = #"\n" then newlineToNewline
|
||||
else if Char.isSpace chr then startSpace
|
||||
else startPunct
|
||||
else newlineToPunct
|
||||
end
|
||||
|
||||
val startTable = Vector.tabulate (255, makeStart)
|
||||
@@ -99,6 +102,9 @@ struct
|
||||
, newlineTable
|
||||
, newlineTable
|
||||
, newlineTable
|
||||
|
||||
, startAlphaTable
|
||||
, startPunctTable
|
||||
]
|
||||
|
||||
structure StartOfNextWord =
|
||||
@@ -117,6 +123,8 @@ struct
|
||||
orelse currentState = spaceToAlpha
|
||||
orelse currentState = spaceToPunct
|
||||
orelse currentState = newlineToNewline
|
||||
orelse currentState = newlineToAlpha
|
||||
orelse currentState = newlineToPunct
|
||||
|
||||
fun finish x = x
|
||||
end)
|
||||
|
||||
@@ -33,6 +33,9 @@ struct
|
||||
|
||||
val low =
|
||||
if Cursor.isOnNewlineAfterChr (buffer, low) then low - 1 else low
|
||||
|
||||
val buffer =
|
||||
if #textLength buffer = 0 then LineGap.fromString "\n" else buffer
|
||||
in
|
||||
finishAfterDeletingBuffer (app, low, buffer, time, initialMsg)
|
||||
end
|
||||
@@ -324,6 +327,52 @@ struct
|
||||
end
|
||||
end
|
||||
|
||||
fun deleteWord (app as {buffer, ...}: app_type, count, time) =
|
||||
if #textLength buffer = 1 then
|
||||
NormalFinish.clearMode app
|
||||
else
|
||||
let
|
||||
val {buffer, cursorIdx, ...} = app
|
||||
|
||||
val buffer = LineGap.goToIdx (cursorIdx, buffer)
|
||||
val high = Cursor.nextWord (buffer, cursorIdx, count)
|
||||
val buffer = LineGap.goToIdx (high, buffer)
|
||||
in
|
||||
(* The Cursor.nextWord skips newlines in some cases,
|
||||
* 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
|
||||
|
||||
fun deleteByDfa (app as {buffer, ...}: app_type, count, fMove, time) =
|
||||
if #textLength buffer = 1 then
|
||||
NormalFinish.clearMode app
|
||||
|
||||
@@ -257,7 +257,7 @@ struct
|
||||
* other cursor motions *)
|
||||
| #"j" => NormalDelete.deleteLineDown (app, count, time)
|
||||
| #"k" => NormalDelete.deleteLineBack (app, count, time)
|
||||
| #"w" => NormalDelete.deleteByDfa (app, count, Cursor.nextWord, time)
|
||||
| #"w" => NormalDelete.deleteWord (app, count, time)
|
||||
| #"W" => NormalDelete.deleteByDfa (app, count, Cursor.nextWORD, time)
|
||||
| #"b" => NormalDelete.deleteByDfa (app, count, Cursor.prevWord, time)
|
||||
| #"B" => NormalDelete.deleteByDfa (app, count, Cursor.prevWORD, time)
|
||||
@@ -346,7 +346,7 @@ struct
|
||||
* other cursor motions *)
|
||||
| #"j" => NormalYankDelete.deleteLineDown (app, count, time)
|
||||
| #"k" => NormalYankDelete.deleteLineBack (app, count, time)
|
||||
| #"w" => NormalYankDelete.deleteByDfa (app, count, Cursor.nextWord, time)
|
||||
| #"w" => NormalYankDelete.deleteWord (app, count, time)
|
||||
| #"W" => NormalYankDelete.deleteByDfa (app, count, Cursor.nextWORD, time)
|
||||
| #"b" => NormalYankDelete.deleteByDfa (app, count, Cursor.prevWord, time)
|
||||
| #"B" => NormalYankDelete.deleteByDfa (app, count, Cursor.prevWORD, time)
|
||||
|
||||
@@ -944,30 +944,27 @@ struct
|
||||
in
|
||||
Expect.isTrue (stringsAreExpected andalso cursorsAreExpected)
|
||||
end)
|
||||
, test
|
||||
"deletes newline when there is a newline after current word \
|
||||
\and there is another word following that newline"
|
||||
(fn _ =>
|
||||
let
|
||||
(* arrange *)
|
||||
val originalString = "hello\nworld\nagain\n"
|
||||
val app = TestUtils.init originalString
|
||||
val app = AppWith.idx (app, 1)
|
||||
, test "does not delete newline following word" (fn _ =>
|
||||
let
|
||||
(* arrange *)
|
||||
val originalString = "hello\nworld\nagain\n"
|
||||
val app = TestUtils.init originalString
|
||||
val app = AppWith.idx (app, 0)
|
||||
|
||||
(* act *)
|
||||
val {buffer, cursorIdx, ...} = TestUtils.updateMany (app, "dw")
|
||||
(* act *)
|
||||
val {buffer, cursorIdx, ...} = TestUtils.updateMany (app, "dw")
|
||||
|
||||
(* assert *)
|
||||
val expectedString = "hworld\nagain\n"
|
||||
val expectedCursor = 1
|
||||
(* assert *)
|
||||
val expectedString = "\nworld\nagain\n"
|
||||
val expectedCursor = 0
|
||||
|
||||
val actualString = LineGap.toString buffer
|
||||
val actualString = LineGap.toString buffer
|
||||
|
||||
val stringIsExpected = expectedString = actualString
|
||||
val cursorIsExpected = expectedCursor = cursorIdx
|
||||
in
|
||||
Expect.isTrue (stringIsExpected andalso cursorIsExpected)
|
||||
end)
|
||||
val stringIsExpected = expectedString = actualString
|
||||
val cursorIsExpected = expectedCursor = cursorIdx
|
||||
in
|
||||
Expect.isTrue (stringIsExpected andalso cursorIsExpected)
|
||||
end)
|
||||
, test
|
||||
"deletes until first punctuation char when on an alpha char \
|
||||
\and there is no space between alpha and punctuation"
|
||||
|
||||
@@ -754,6 +754,18 @@ struct
|
||||
(* assert *)
|
||||
Expect.isTrue (#cursorIdx app = 4)
|
||||
end)
|
||||
, test "moves cursor to character after newline" (fn _ =>
|
||||
let
|
||||
(* arrange *)
|
||||
val app = TestUtils.init "hello\nworld\nagain\n"
|
||||
val app = AppWith.idx (app, 0)
|
||||
|
||||
(* act *)
|
||||
val app = TestUtils.update (app, CHAR_EVENT #"w")
|
||||
in
|
||||
(* assert *)
|
||||
Expect.isTrue (#cursorIdx app = 6)
|
||||
end)
|
||||
]
|
||||
|
||||
val WMove = describe "move motion 'W'"
|
||||
|
||||
Reference in New Issue
Block a user