add tests for 'd$' motion, and fix bug. When we are extending an existing match and reached the last index of the buffer, we used to return the searchList right away. However, we are meant to add the extended match before returning the searchList. We do this now, and the bug is fixed.

This commit is contained in:
2026-02-10 09:56:35 +00:00
parent 3c0a1dc034
commit 756f44e7f8
2 changed files with 167 additions and 3 deletions

View File

@@ -177,9 +177,12 @@ struct
fun tryExtendingPrevMatch
(idx, buffer, searchList, dfa, finalPos, curState, start) =
if idx = #textLength buffer then
(* reached end of buffer without finding anything
* so return current buffer and searchList *)
(buffer, searchList)
let
val searchList =
PersistentVector.extendExistingMatch (start, finalPos, searchList)
in
(buffer, searchList)
end
else if Dfa.isDead curState then
let
val searchList =

View File

@@ -4,6 +4,21 @@ struct
open Railroad.Test
open InputMsg
fun printVec pv =
let
val outputList = PersistentVector.toList pv
val str =
List.map
(fn {start, finish} =>
"{start = " ^ Int.toString start ^ ", finish = "
^ Int.toString finish ^ "}") outputList
val str = String.concatWith "\n " str ^ "\n"
in
print str
end
val dhDelete = describe "delete motion 'dh'"
[ test "does not delete when cursor is at index 0" (fn _ =>
let
@@ -5255,6 +5270,152 @@ struct
(actualString = expectedString
andalso cursorIdx = expectedCursorIdx)
end)
, test "has same searchList when deleting after all matches" (fn _ =>
let
(* arrange *)
val originalIdx = 11
val originalString = "hello world again\n"
val app = TestUtils.init originalString
val app = AppWith.idx (app, originalIdx)
val app = TestUtils.updateMany (app, "/hello")
val app = AppUpdate.update (app, InputMsg.KEY_ENTER, Time.now ())
(* act *)
val newApp = TestUtils.updateMany (app, "d$")
in
(* assert *)
Expect.isTrue (#searchList app = #searchList newApp)
end)
, test "decrements search list when we delete word preceding match" (fn _ =>
let
(* arrange *)
val originalIdx = 0
val originalString = "hello\nworld\n"
val app = TestUtils.init originalString
val app = AppWith.idx (app, originalIdx)
val app = TestUtils.updateMany (app, "/world")
val app = AppUpdate.update (app, InputMsg.KEY_ENTER, Time.now ())
(* act *)
val newApp = TestUtils.updateMany (app, "d$")
(* assert *)
val oldSearchList = #searchList app
val oldSearchList = PersistentVector.toList oldSearchList
val newSearchList = #searchList newApp
val newSearchList = PersistentVector.toList newSearchList
val expectedOldSearchList = [{start = 6, finish = 10}]
val expectedNewSearchList = [{start = 1, finish = 5}]
val assertion =
oldSearchList = expectedOldSearchList
andalso newSearchList = expectedNewSearchList
in
Expect.isTrue assertion
end)
, test "recognises new match when there is a match after deletion" (fn _ =>
let
(* arrange *)
val originalIdx = 6
val originalString = "hello\nagain\nworld\n"
val app = TestUtils.init originalString
val app = AppWith.idx (app, originalIdx)
val app = TestUtils.updateMany (app, "/hello\n\nworld")
val app = AppUpdate.update (app, InputMsg.KEY_ENTER, Time.now ())
(* act *)
val newApp = TestUtils.updateMany (app, "d$")
(* assert *)
val oldSearchList = #searchList app
val oldSearchList = PersistentVector.toList oldSearchList
val newSearchList = #searchList newApp
val newSearchList = PersistentVector.toList newSearchList
val expectedOldSearchList = []
val expectedNewSearchList = [{start = 0, finish = 11}]
val assertion =
oldSearchList = expectedOldSearchList
andalso newSearchList = expectedNewSearchList
in
Expect.isTrue assertion
end)
, test
"extends existing match when existing match should extend after deletion"
(fn _ =>
let
(* arrange *)
val originalIdx = 6
val originalString = "hello\nworld\n"
val app = TestUtils.init originalString
val app = AppWith.idx (app, originalIdx)
val app = TestUtils.updateMany (app, "/\n+")
val app = AppUpdate.update (app, InputMsg.KEY_ENTER, Time.now ())
(* act *)
val newApp = TestUtils.updateMany (app, "d$")
(* assert *)
val oldSearchList = #searchList app
val oldSearchList = PersistentVector.toList oldSearchList
val newSearchList = #searchList newApp
val newSearchList = PersistentVector.toList newSearchList
val expectedOldSearchList =
[{start = 5, finish = 5}, {start = 11, finish = 11}]
val expectedNewSearchList = [{start = 5, finish = 6}]
val assertion =
oldSearchList = expectedOldSearchList
andalso newSearchList = expectedNewSearchList
in
Expect.isTrue assertion
end)
, test
"deletes match in search list \
\when match no longer exists in buffer after deletion"
(fn _ =>
let
(* arrange *)
val originalIdx = 7
val originalString = "hello world test again\n"
val app = TestUtils.init originalString
val app = AppWith.idx (app, originalIdx)
val app = TestUtils.updateMany (app, "/world")
val app = AppUpdate.update (app, InputMsg.KEY_ENTER, Time.now ())
(* act *)
val newApp = TestUtils.updateMany (app, "d$")
(* assert *)
val oldSearchList = #searchList app
val oldSearchList = PersistentVector.toList oldSearchList
val newSearchList = #searchList newApp
val newSearchList = PersistentVector.toList newSearchList
val expectedOldSearchList = [{start = 6, finish = 10}]
val expectedNewSearchList = []
val assertion =
oldSearchList = expectedOldSearchList
andalso newSearchList = expectedNewSearchList
in
Expect.isTrue assertion
end)
]
val dCaretDelete = describe "delete motion 'd^'"