add tests for 'df<char>' motion, uncover bug found by test where new match was not recognised after deletion if match involved last character in buffer, and fix that bug by checking (in fcore/search-list/search-list.sm) if we are at a dead state before we check if we are in the last index of the buffer
This commit is contained in:
@@ -131,20 +131,7 @@ struct
|
|||||||
|
|
||||||
fun insertUntilMatch
|
fun insertUntilMatch
|
||||||
(idx, buffer, searchList, dfa, curState, startPos, prevFinalPos) =
|
(idx, buffer, searchList, dfa, curState, startPos, prevFinalPos) =
|
||||||
if idx = #textLength buffer then
|
if Dfa.isDead curState 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 prevFinalPos = ~1 then
|
if prevFinalPos = ~1 then
|
||||||
(* no match found: restart search from `startPos + 1` *)
|
(* no match found: restart search from `startPos + 1` *)
|
||||||
insertUntilMatch
|
insertUntilMatch
|
||||||
@@ -161,6 +148,19 @@ struct
|
|||||||
in
|
in
|
||||||
insertUntilMatch (newStart, buffer, searchList, dfa, 0, newStart, ~1)
|
insertUntilMatch (newStart, buffer, searchList, dfa, 0, newStart, ~1)
|
||||||
end
|
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
|
else
|
||||||
let
|
let
|
||||||
val buffer = LineGap.goToIdx (idx, buffer)
|
val buffer = LineGap.goToIdx (idx, buffer)
|
||||||
@@ -176,14 +176,7 @@ struct
|
|||||||
|
|
||||||
fun tryExtendingPrevMatch
|
fun tryExtendingPrevMatch
|
||||||
(idx, buffer, searchList, dfa, finalPos, curState, start) =
|
(idx, buffer, searchList, dfa, finalPos, curState, start) =
|
||||||
if idx = #textLength buffer then
|
if Dfa.isDead curState then
|
||||||
let
|
|
||||||
val searchList =
|
|
||||||
PersistentVector.extendExistingMatch (start, finalPos, searchList)
|
|
||||||
in
|
|
||||||
(buffer, searchList)
|
|
||||||
end
|
|
||||||
else if Dfa.isDead curState then
|
|
||||||
let
|
let
|
||||||
val searchList =
|
val searchList =
|
||||||
PersistentVector.extendExistingMatch (start, finalPos, searchList)
|
PersistentVector.extendExistingMatch (start, finalPos, searchList)
|
||||||
@@ -191,6 +184,13 @@ struct
|
|||||||
insertUntilMatch
|
insertUntilMatch
|
||||||
(finalPos + 1, buffer, searchList, dfa, 0, finalPos + 1, ~1)
|
(finalPos + 1, buffer, searchList, dfa, 0, finalPos + 1, ~1)
|
||||||
end
|
end
|
||||||
|
else if idx = #textLength buffer then
|
||||||
|
let
|
||||||
|
val searchList =
|
||||||
|
PersistentVector.extendExistingMatch (start, finalPos, searchList)
|
||||||
|
in
|
||||||
|
(buffer, searchList)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
let
|
let
|
||||||
val buffer = LineGap.goToIdx (idx, buffer)
|
val buffer = LineGap.goToIdx (idx, buffer)
|
||||||
|
|||||||
@@ -1,2 +1 @@
|
|||||||
hello hello hello
|
hello again world
|
||||||
world world world
|
|
||||||
|
|||||||
@@ -6296,6 +6296,153 @@ struct
|
|||||||
Expect.isTrue
|
Expect.isTrue
|
||||||
(actualString = expectedString andalso cursorIdx = expectedCursorIdx)
|
(actualString = expectedString andalso cursorIdx = expectedCursorIdx)
|
||||||
end)
|
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<char>'"
|
val dtDelete = describe "delete motion 'dt<char>'"
|
||||||
|
|||||||
Reference in New Issue
Block a user