make implementation of 'di<symbol>' more robust (we check if the cursor is inside a symbol-pair before checking if there is a symbol pair after the cursor), and add tests for 'di<symbol>' motion
This commit is contained in:
@@ -209,61 +209,69 @@ struct
|
|||||||
|
|
||||||
val toPrevChr = ToPrevChr.foldPrev
|
val toPrevChr = ToPrevChr.foldPrev
|
||||||
|
|
||||||
structure ToCloseChrNext =
|
structure ToOpenChrPrev =
|
||||||
MakeIfCharFolderNext
|
MakeIfCharFolderPrev
|
||||||
(struct
|
(struct
|
||||||
type env = {openChr: char, closeChr: char}
|
type env = {openChr: char, closeChr: char}
|
||||||
|
|
||||||
fun loop (strPos, str, absIdx, stl, openChr, closeChr, openCount) =
|
fun loop (strPos, str, absIdx, stl, openChr, closeChr, closeCount) =
|
||||||
if strPos = String.size str then
|
if strPos < 0 then
|
||||||
case stl of
|
case stl of
|
||||||
str :: stl =>
|
str :: stl =>
|
||||||
loop (0, str, absIdx, stl, openChr, closeChr, openCount)
|
loop
|
||||||
|
( String.size str - 1
|
||||||
|
, str
|
||||||
|
, absIdx
|
||||||
|
, stl
|
||||||
|
, openChr
|
||||||
|
, closeChr
|
||||||
|
, closeCount
|
||||||
|
)
|
||||||
| [] => ~1
|
| [] => ~1
|
||||||
else
|
else
|
||||||
let
|
let
|
||||||
val chr = String.sub (str, strPos)
|
val chr = String.sub (str, strPos)
|
||||||
in
|
in
|
||||||
if chr = openChr then
|
if chr = openChr then
|
||||||
loop
|
if closeCount = 0 then
|
||||||
( strPos + 1
|
|
||||||
, str
|
|
||||||
, absIdx + 1
|
|
||||||
, stl
|
|
||||||
, openChr
|
|
||||||
, closeChr
|
|
||||||
, openCount + 1
|
|
||||||
)
|
|
||||||
else if chr = closeChr then
|
|
||||||
if openCount = 0 then
|
|
||||||
absIdx
|
absIdx
|
||||||
else
|
else
|
||||||
loop
|
loop
|
||||||
( strPos + 1
|
( strPos - 1
|
||||||
, str
|
, str
|
||||||
, absIdx + 1
|
, absIdx - 1
|
||||||
, stl
|
, stl
|
||||||
, openChr
|
, openChr
|
||||||
, closeChr
|
, closeChr
|
||||||
, openCount - 1
|
, closeCount - 1
|
||||||
)
|
)
|
||||||
else
|
else if chr = closeChr then
|
||||||
loop
|
loop
|
||||||
( strPos + 1
|
( strPos - 1
|
||||||
, str
|
, str
|
||||||
, absIdx + 1
|
, absIdx - 1
|
||||||
, stl
|
, stl
|
||||||
, openChr
|
, openChr
|
||||||
, closeChr
|
, closeChr
|
||||||
, openCount
|
, closeCount + 1
|
||||||
|
)
|
||||||
|
else
|
||||||
|
loop
|
||||||
|
( strPos - 1
|
||||||
|
, str
|
||||||
|
, absIdx - 1
|
||||||
|
, stl
|
||||||
|
, openChr
|
||||||
|
, closeChr
|
||||||
|
, closeCount
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
fun fStart (strPos, str, _, absIdx, stl, _, {openChr, closeChr}) =
|
fun fStart (strPos, str, _, absIdx, stl, _, {openChr, closeChr}) =
|
||||||
loop (strPos + 1, str, absIdx + 1, stl, openChr, closeChr, 0)
|
loop (strPos, str, absIdx, stl, openChr, closeChr, 0)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
val toCloseChrNext = ToCloseChrNext.foldNext
|
val toOpenChrPrev = ToOpenChrPrev.foldPrev
|
||||||
|
|
||||||
structure NextPairChr =
|
structure NextPairChr =
|
||||||
MakeIfCharFolderNext
|
MakeIfCharFolderNext
|
||||||
|
|||||||
@@ -1068,29 +1068,56 @@ struct
|
|||||||
val cursorChr = LineGap.sub (cursorIdx, buffer)
|
val cursorChr = LineGap.sub (cursorIdx, buffer)
|
||||||
in
|
in
|
||||||
if cursorChr = openChr orelse cursorChr = closeChr then
|
if cursorChr = openChr orelse cursorChr = closeChr then
|
||||||
|
(* cursor is at pair, so match and delete *)
|
||||||
let
|
let
|
||||||
val otherIdx = Cursor.matchPair (buffer, cursorIdx)
|
val otherIdx = Cursor.matchPair (buffer, cursorIdx)
|
||||||
in
|
in
|
||||||
finishDeletingInsidePair (app, buffer, cursorIdx, otherIdx, dfa, time)
|
if otherIdx = ~1 then
|
||||||
end
|
|
||||||
else
|
|
||||||
let
|
|
||||||
val nextIdx =
|
|
||||||
Cursor.toCloseChrNext
|
|
||||||
(buffer, cursorIdx, {openChr = openChr, closeChr = closeChr})
|
|
||||||
in
|
|
||||||
if nextIdx = ~1 then
|
|
||||||
NormalFinish.clearMode app
|
NormalFinish.clearMode app
|
||||||
else
|
else
|
||||||
|
finishDeletingInsidePair
|
||||||
|
(app, buffer, cursorIdx, otherIdx, dfa, time)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
(* check to see if we are inside pair *)
|
||||||
|
let
|
||||||
|
val prevIdx =
|
||||||
|
Cursor.toOpenChrPrev
|
||||||
|
(buffer, cursorIdx, {openChr = openChr, closeChr = closeChr})
|
||||||
|
in
|
||||||
|
if prevIdx = ~1 then
|
||||||
|
(* no openChr before cursor, so check after cursor *)
|
||||||
let
|
let
|
||||||
val buffer = LineGap.goToIdx (nextIdx, buffer)
|
val nextIdx =
|
||||||
val matchIdx = Cursor.matchPair (buffer, nextIdx)
|
Cursor.toNextChr
|
||||||
|
(buffer, cursorIdx, {findChr = openChr, count = 1})
|
||||||
in
|
in
|
||||||
if matchIdx = ~1 then
|
if nextIdx = ~1 then
|
||||||
|
NormalFinish.clearMode app
|
||||||
|
else
|
||||||
|
let
|
||||||
|
val buffer = LineGap.goToIdx (nextIdx, buffer)
|
||||||
|
val matchIdx = Cursor.matchPair (buffer, nextIdx)
|
||||||
|
in
|
||||||
|
if matchIdx = ~1 then
|
||||||
|
NormalFinish.clearMode app
|
||||||
|
else
|
||||||
|
finishDeletingInsidePair
|
||||||
|
(app, buffer, nextIdx, matchIdx, dfa, time)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
(* there is an openChr before cursor, so match it,
|
||||||
|
* and if there is a match, then delete *)
|
||||||
|
let
|
||||||
|
val buffer = LineGap.goToIdx (prevIdx, buffer)
|
||||||
|
val otherIdx = Cursor.matchPair (buffer, prevIdx)
|
||||||
|
in
|
||||||
|
if otherIdx = ~1 then
|
||||||
NormalFinish.clearMode app
|
NormalFinish.clearMode app
|
||||||
else
|
else
|
||||||
finishDeletingInsidePair
|
finishDeletingInsidePair
|
||||||
(app, buffer, nextIdx, matchIdx, dfa, time)
|
(app, buffer, prevIdx, otherIdx, dfa, time)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1155,8 +1182,7 @@ struct
|
|||||||
else
|
else
|
||||||
let
|
let
|
||||||
val nextIdx =
|
val nextIdx =
|
||||||
Cursor.toCloseChrNext
|
Cursor.toNextChr (buffer, cursorIdx, {findChr = openChr, count = 1})
|
||||||
(buffer, cursorIdx, {openChr = openChr, closeChr = closeChr})
|
|
||||||
in
|
in
|
||||||
if nextIdx = ~1 then
|
if nextIdx = ~1 then
|
||||||
NormalFinish.clearMode app
|
NormalFinish.clearMode app
|
||||||
|
|||||||
@@ -5075,6 +5075,82 @@ struct
|
|||||||
end)
|
end)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
val diParenDelete = describe "delete motion 'di('"
|
||||||
|
[ test "does not delete when there is no ( after the cursor" (fn _ =>
|
||||||
|
let
|
||||||
|
(* arrange *)
|
||||||
|
val originalString = " ( ) hello\n"
|
||||||
|
val app = TestUtils.init originalString
|
||||||
|
val app = AppWith.idx (app, 7)
|
||||||
|
|
||||||
|
(* act *)
|
||||||
|
val {buffer, ...} = TestUtils.updateMany (app, "di(")
|
||||||
|
|
||||||
|
(* assert *)
|
||||||
|
val expectedString = originalString
|
||||||
|
val actualString = LineGap.toString buffer
|
||||||
|
in
|
||||||
|
Expect.isTrue (expectedString = actualString)
|
||||||
|
end)
|
||||||
|
, test
|
||||||
|
"deletes pair after cursor when there is a pair \
|
||||||
|
\before the cursor and after the cursor"
|
||||||
|
(fn _ =>
|
||||||
|
let
|
||||||
|
(* arrange *)
|
||||||
|
val originalString = " ( abc ) xyz ( def )\n"
|
||||||
|
val app = TestUtils.init originalString
|
||||||
|
val app = AppWith.idx (app, 9)
|
||||||
|
|
||||||
|
(* act *)
|
||||||
|
val {buffer, ...} = TestUtils.updateMany (app, "di(")
|
||||||
|
|
||||||
|
(* assert *)
|
||||||
|
val expectedString = " ( abc ) xyz ()\n"
|
||||||
|
val actualString = LineGap.toString buffer
|
||||||
|
in
|
||||||
|
Expect.isTrue (expectedString = actualString)
|
||||||
|
end)
|
||||||
|
, test
|
||||||
|
"deletes inside outer parens when cursor is in \
|
||||||
|
\outer paren, and there is an inner paren after cursor"
|
||||||
|
(fn _ =>
|
||||||
|
let
|
||||||
|
(* arrange *)
|
||||||
|
val originalString = "( ( hello ) )\n"
|
||||||
|
val app = TestUtils.init originalString
|
||||||
|
val app = AppWith.idx (app, 1)
|
||||||
|
|
||||||
|
(* act *)
|
||||||
|
val {buffer, ...} = TestUtils.updateMany (app, "di(")
|
||||||
|
|
||||||
|
(* assert *)
|
||||||
|
val expectedString = "()\n"
|
||||||
|
val actualString = LineGap.toString buffer
|
||||||
|
in
|
||||||
|
Expect.isTrue (expectedString = actualString)
|
||||||
|
end)
|
||||||
|
, test
|
||||||
|
"deletes inside inner parren when cursor is in inner paren-pair, \
|
||||||
|
\and there is an outer paren above this inner paren"
|
||||||
|
(fn _ =>
|
||||||
|
let
|
||||||
|
(* arrange *)
|
||||||
|
val originalString = "( ( hello ) )\n"
|
||||||
|
val app = TestUtils.init originalString
|
||||||
|
val app = AppWith.idx (app, 5)
|
||||||
|
|
||||||
|
(* act *)
|
||||||
|
val {buffer, ...} = TestUtils.updateMany (app, "di(")
|
||||||
|
|
||||||
|
(* assert *)
|
||||||
|
val expectedString = "( () )\n"
|
||||||
|
val actualString = LineGap.toString buffer
|
||||||
|
in
|
||||||
|
Expect.isTrue (expectedString = actualString)
|
||||||
|
end)
|
||||||
|
]
|
||||||
|
|
||||||
val tests =
|
val tests =
|
||||||
[ dhDelete
|
[ dhDelete
|
||||||
, dlDelete
|
, dlDelete
|
||||||
@@ -5105,5 +5181,6 @@ struct
|
|||||||
, dawDelete
|
, dawDelete
|
||||||
, daWDelete
|
, daWDelete
|
||||||
, pairDelete
|
, pairDelete
|
||||||
|
, diParenDelete
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user