From 756f44e7f82ebf0d6516be56fbdcd2a1c6d70f9a Mon Sep 17 00:00:00 2001 From: Humza Shahid Date: Tue, 10 Feb 2026 09:56:35 +0000 Subject: [PATCH] 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. --- fcore/search-list/search-list.sml | 9 +- test/normal-delete-tests.sml | 161 ++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+), 3 deletions(-) diff --git a/fcore/search-list/search-list.sml b/fcore/search-list/search-list.sml index 9b066f7..e267aa2 100644 --- a/fcore/search-list/search-list.sml +++ b/fcore/search-list/search-list.sml @@ -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 = diff --git a/test/normal-delete-tests.sml b/test/normal-delete-tests.sml index b110d64..20fa2a4 100644 --- a/test/normal-delete-tests.sml +++ b/test/normal-delete-tests.sml @@ -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^'"