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