add additional test for 'dn' motion after finding bug, fixed bug (rewrote high-level delete fundtion in persistent-vector.sml to address it), and begin adding tests for 'dN' motion
This commit is contained in:
@@ -483,7 +483,7 @@ struct
|
|||||||
else
|
else
|
||||||
if splitIdx > Vector.sub (sizes, Vector.length sizes - 1) then
|
if splitIdx > Vector.sub (sizes, Vector.length sizes - 1) then
|
||||||
empty
|
empty
|
||||||
else if splitIdx < Vector.sub (sizes, 0) then
|
else if splitIdx < #start (Vector.sub (items, 0)) then
|
||||||
tree
|
tree
|
||||||
else
|
else
|
||||||
let
|
let
|
||||||
@@ -743,13 +743,6 @@ struct
|
|||||||
let
|
let
|
||||||
val finish = start + length
|
val finish = start + length
|
||||||
|
|
||||||
val matchBeforeStart = prevMatch (start, tree, 1)
|
|
||||||
val matchBeforeStart =
|
|
||||||
if matchBeforeStart >= start then
|
|
||||||
~1
|
|
||||||
else
|
|
||||||
matchBeforeStart
|
|
||||||
|
|
||||||
val matchAfterFinish = nextMatch (finish, tree, 1)
|
val matchAfterFinish = nextMatch (finish, tree, 1)
|
||||||
val matchAfterFinish =
|
val matchAfterFinish =
|
||||||
if matchAfterFinish < finish then
|
if matchAfterFinish < finish then
|
||||||
@@ -757,63 +750,47 @@ struct
|
|||||||
else
|
else
|
||||||
matchAfterFinish
|
matchAfterFinish
|
||||||
in
|
in
|
||||||
if matchBeforeStart = ~1 andalso matchAfterFinish = ~1 then
|
let
|
||||||
empty
|
val left = splitLeft (start, tree)
|
||||||
else if matchAfterFinish = ~1 then
|
val right = splitRight (finish, tree)
|
||||||
(* there is no match after 'finish', so just split left.
|
in
|
||||||
* No need to decrement or split right,
|
if isEmpty left andalso isEmpty right then
|
||||||
* because the right vector would be empty. *)
|
empty
|
||||||
splitLeft (start, tree)
|
else if isEmpty left then
|
||||||
else if matchBeforeStart = ~1 then
|
(* just decrement right and return it *)
|
||||||
(* We don't want to use left split
|
let
|
||||||
* because there are no elements
|
val rightStart = getStartIdx right
|
||||||
* before the deletion range's 'start'.
|
val shouldBeStartIdx = matchAfterFinish - length
|
||||||
* So we make a right split and then decrement it. *)
|
val difference = rightStart - shouldBeStartIdx
|
||||||
let
|
in
|
||||||
val right = splitRight (finish, tree)
|
if difference = 0 then
|
||||||
in
|
right
|
||||||
if isEmpty right then
|
else
|
||||||
empty
|
decrementBy (difference, right)
|
||||||
else
|
end
|
||||||
let
|
else if isEmpty right then
|
||||||
val startIdx = getStartIdx right
|
(* return left half without doing anything *)
|
||||||
val shouldBeStartIdx = matchAfterFinish - length
|
left
|
||||||
val difference = startIdx - shouldBeStartIdx
|
else
|
||||||
in
|
(* decrement right, and then merge both together *)
|
||||||
if difference = 0 then
|
let
|
||||||
right
|
val leftSize = getFinishIdx left
|
||||||
else if isEmpty right then
|
val rightStartRelative = getStartIdx right
|
||||||
empty
|
val rightStartAbsolute = leftSize + rightStartRelative
|
||||||
else
|
|
||||||
decrementBy (difference, right)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
let
|
|
||||||
val left = splitLeft (start, tree)
|
|
||||||
val right = splitRight (finish, tree)
|
|
||||||
in
|
|
||||||
if isEmpty right then
|
|
||||||
left
|
|
||||||
else
|
|
||||||
let
|
|
||||||
val leftSize = getFinishIdx left
|
|
||||||
val rightStartRelative = getStartIdx right
|
|
||||||
val rightStartAbsolute = leftSize + rightStartRelative
|
|
||||||
|
|
||||||
val shouldBeStartIdx = matchAfterFinish - length
|
val shouldBeStartIdx = matchAfterFinish - length
|
||||||
val difference = rightStartAbsolute - shouldBeStartIdx
|
val difference = rightStartAbsolute - shouldBeStartIdx
|
||||||
in
|
in
|
||||||
if difference = 0 then
|
if difference = 0 then
|
||||||
|
merge (left, right)
|
||||||
|
else
|
||||||
|
let
|
||||||
|
val right = decrementBy (difference, right)
|
||||||
|
in
|
||||||
merge (left, right)
|
merge (left, right)
|
||||||
else
|
end
|
||||||
let
|
end
|
||||||
val right = decrementBy (difference, right)
|
end
|
||||||
in
|
|
||||||
merge (left, right)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
(* Usually, when inserting, we want the absolute metadata
|
(* Usually, when inserting, we want the absolute metadata
|
||||||
|
|||||||
@@ -144,13 +144,13 @@ struct
|
|||||||
in
|
in
|
||||||
(buffer, searchList)
|
(buffer, searchList)
|
||||||
end
|
end
|
||||||
else if PersistentVector.isInRange (idx, searchList) then
|
|
||||||
(buffer, searchList)
|
|
||||||
else if Dfa.isDead curState then
|
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
|
||||||
(startPos + 1, buffer, searchList, dfa, 0, startPos + 1, ~1)
|
(startPos + 1, buffer, searchList, dfa, 0, startPos + 1, ~1)
|
||||||
|
else if PersistentVector.isInRange (prevFinalPos, searchList) then
|
||||||
|
(buffer, searchList)
|
||||||
else
|
else
|
||||||
(* new match. Insert and continue *)
|
(* new match. Insert and continue *)
|
||||||
let
|
let
|
||||||
|
|||||||
@@ -5824,7 +5824,6 @@ struct
|
|||||||
(* assert *)
|
(* assert *)
|
||||||
Expect.isTrue assertion
|
Expect.isTrue assertion
|
||||||
end)
|
end)
|
||||||
|
|
||||||
, test "extends match when match should extend after deletion" (fn _ =>
|
, test "extends match when match should extend after deletion" (fn _ =>
|
||||||
let
|
let
|
||||||
(* arrange *)
|
(* arrange *)
|
||||||
@@ -5850,6 +5849,41 @@ struct
|
|||||||
[{start = 0, finish = 4}, {start = 6, finish = 10}]
|
[{start = 0, finish = 4}, {start = 6, finish = 10}]
|
||||||
val expectedNewSearchList = [{start = 0, finish = 9}]
|
val expectedNewSearchList = [{start = 0, finish = 9}]
|
||||||
|
|
||||||
|
val assertion =
|
||||||
|
oldSearchList = expectedOldSearchList
|
||||||
|
andalso newSearchList = expectedNewSearchList
|
||||||
|
in
|
||||||
|
Expect.isTrue assertion
|
||||||
|
end)
|
||||||
|
, test "detects match when we delete in middle of it" (fn _ =>
|
||||||
|
let
|
||||||
|
(* arrange *)
|
||||||
|
val originalIdx = 1
|
||||||
|
val originalString = "hello hello hello\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, "dn")
|
||||||
|
|
||||||
|
(* assert *)
|
||||||
|
val oldSearchList = #searchList app
|
||||||
|
val oldSearchList = PersistentVector.toList oldSearchList
|
||||||
|
val newSearchList = #searchList newApp
|
||||||
|
val newSearchList = PersistentVector.toList newSearchList
|
||||||
|
|
||||||
|
val expectedOldSearchList =
|
||||||
|
[ {start = 0, finish = 4}
|
||||||
|
, {start = 6, finish = 10}
|
||||||
|
, {start = 12, finish = 16}
|
||||||
|
]
|
||||||
|
val expectedNewSearchList =
|
||||||
|
[{start = 1, finish = 5}, {start = 7, finish = 11}]
|
||||||
|
|
||||||
val assertion =
|
val assertion =
|
||||||
oldSearchList = expectedOldSearchList
|
oldSearchList = expectedOldSearchList
|
||||||
andalso newSearchList = expectedNewSearchList
|
andalso newSearchList = expectedNewSearchList
|
||||||
@@ -5952,6 +5986,45 @@ struct
|
|||||||
(actualString = expectedString
|
(actualString = expectedString
|
||||||
andalso cursorIdx = expectedCursorIdx)
|
andalso cursorIdx = expectedCursorIdx)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
, test
|
||||||
|
"decrements subsequent matches in search list \
|
||||||
|
\when we delete prior to last match"
|
||||||
|
(fn _ =>
|
||||||
|
let
|
||||||
|
(* arrange *)
|
||||||
|
val originalIdx = 1
|
||||||
|
val originalString = "hello hello hello\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, "dN")
|
||||||
|
|
||||||
|
(* assert *)
|
||||||
|
val oldSearchList = #searchList app
|
||||||
|
val oldSearchList = PersistentVector.toList oldSearchList
|
||||||
|
val newSearchList = #searchList newApp
|
||||||
|
val newSearchList = PersistentVector.toList newSearchList
|
||||||
|
|
||||||
|
val expectedOldSearchList =
|
||||||
|
[ {start = 0, finish = 4}
|
||||||
|
, {start = 6, finish = 10}
|
||||||
|
, {start = 12, finish = 16}
|
||||||
|
]
|
||||||
|
val expectedNewSearchList =
|
||||||
|
[{start = 5, finish = 9}, {start = 11, finish = 15}]
|
||||||
|
|
||||||
|
val assertion =
|
||||||
|
oldSearchList = expectedOldSearchList
|
||||||
|
andalso newSearchList = expectedNewSearchList
|
||||||
|
in
|
||||||
|
Expect.isTrue assertion
|
||||||
|
end)
|
||||||
]
|
]
|
||||||
|
|
||||||
val dfDelete = describe "delete motion 'df<char>'"
|
val dfDelete = describe "delete motion 'df<char>'"
|
||||||
|
|||||||
Reference in New Issue
Block a user