diff --git a/shf/fcore/search-list/search-list.sml b/shf/fcore/search-list/search-list.sml index e05f0bd..9c006d6 100644 --- a/shf/fcore/search-list/search-list.sml +++ b/shf/fcore/search-list/search-list.sml @@ -131,20 +131,7 @@ struct fun insertUntilMatch (idx, buffer, searchList, dfa, curState, startPos, prevFinalPos) = - if idx = #textLength buffer then - if prevFinalPos < 0 then - (buffer, searchList) - else if PersistentVector.isInRange (prevFinalPos, searchList) then - (buffer, searchList) - else - let - val searchList = - PersistentVector.insertMatchKeepingAbsoluteInddices - (startPos, prevFinalPos, searchList) - in - (buffer, searchList) - end - else if Dfa.isDead curState then + if Dfa.isDead curState then if prevFinalPos = ~1 then (* no match found: restart search from `startPos + 1` *) insertUntilMatch @@ -161,6 +148,19 @@ struct in insertUntilMatch (newStart, buffer, searchList, dfa, 0, newStart, ~1) end + else if idx = #textLength buffer then + if prevFinalPos < 0 then + (buffer, searchList) + else if PersistentVector.isInRange (prevFinalPos, searchList) then + (buffer, searchList) + else + let + val searchList = + PersistentVector.insertMatchKeepingAbsoluteInddices + (startPos, prevFinalPos, searchList) + in + (buffer, searchList) + end else let val buffer = LineGap.goToIdx (idx, buffer) @@ -176,14 +176,7 @@ struct fun tryExtendingPrevMatch (idx, buffer, searchList, dfa, finalPos, curState, start) = - if idx = #textLength buffer then - let - val searchList = - PersistentVector.extendExistingMatch (start, finalPos, searchList) - in - (buffer, searchList) - end - else if Dfa.isDead curState then + if Dfa.isDead curState then let val searchList = PersistentVector.extendExistingMatch (start, finalPos, searchList) @@ -191,6 +184,13 @@ struct insertUntilMatch (finalPos + 1, buffer, searchList, dfa, 0, finalPos + 1, ~1) end + else if idx = #textLength buffer then + let + val searchList = + PersistentVector.extendExistingMatch (start, finalPos, searchList) + in + (buffer, searchList) + end else let val buffer = LineGap.goToIdx (idx, buffer) diff --git a/shf/temp.txt b/shf/temp.txt index a2c1105..93f9fd7 100644 --- a/shf/temp.txt +++ b/shf/temp.txt @@ -1,2 +1 @@ -hello hello hello -world world world +hello again world diff --git a/shf/test/normal-delete-tests.sml b/shf/test/normal-delete-tests.sml index a88537f..36aa39f 100644 --- a/shf/test/normal-delete-tests.sml +++ b/shf/test/normal-delete-tests.sml @@ -6296,6 +6296,153 @@ struct Expect.isTrue (actualString = expectedString andalso cursorIdx = expectedCursorIdx) end) + , test "has same searchList when deleting after all matches" (fn _ => + let + (* arrange *) + val originalIdx = 9 + val originalString = "hello world again\n" + + val app = TestUtils.init originalString + val app = AppWith.idx (app, originalIdx) + + val app = TestUtils.updateMany (app, "/o") + val app = AppUpdate.update (app, InputMsg.KEY_ENTER, Time.now ()) + + (* act *) + val newApp = TestUtils.updateMany (app, "dfn") + in + (* assert *) + Expect.isTrue (#searchList app = #searchList newApp) + end) + , test "decrements search list when we delete text section 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, "dfl") + + (* 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 = 3, finish = 7}] + + 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 = 5 + val originalString = "hello again world\n" + + val app = TestUtils.init originalString + val app = AppWith.idx (app, originalIdx) + + val app = TestUtils.updateMany (app, "/hello world") + val app = AppUpdate.update (app, InputMsg.KEY_ENTER, Time.now ()) + + (* act *) + val newApp = TestUtils.updateMany (app, "dfn") + + (* 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 = 10}] + + 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 = 5 + val originalString = "hello world\n" + + val app = TestUtils.init originalString + val app = AppWith.idx (app, originalIdx) + + val app = TestUtils.updateMany (app, "/o+") + val app = AppUpdate.update (app, InputMsg.KEY_ENTER, Time.now ()) + + (* act *) + val newApp = TestUtils.updateMany (app, "dfw") + + (* assert *) + val oldSearchList = #searchList app + val oldSearchList = PersistentVector.toList oldSearchList + + val newSearchList = #searchList newApp + val newSearchList = PersistentVector.toList newSearchList + + val expectedOldSearchList = + [{start = 4, finish = 4}, {start = 7, finish = 7}] + val expectedNewSearchList = [{start = 4, finish = 5}] + + 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 = 3 + 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, "dft") + + (* 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 dtDelete = describe "delete motion 'dt'"