when deleting inside pair, instead of searching either for either chr1 or chr2 and stopping at first match, search instead for openChr and closeChr, and keep an integer tracking what level of nesting we are at. This gives us the behaviour we want, which is to delete the pair at the correct level of nesting. When we encounter openChr, we increment the nesting counter by 1 and continue searching. When we encounter closeChr, if the nesting counter is 0, we return the current index, but if the nesting counter is higher than 0 when encounter closeChr, we decrement the nesting counter by 1 and continue searching.

This commit is contained in:
2026-01-02 18:50:04 +00:00
parent 37b6f6ab0a
commit 886f384490
4 changed files with 99 additions and 18 deletions

View File

@@ -209,29 +209,61 @@ struct
val toPrevChr = ToPrevChr.foldPrev val toPrevChr = ToPrevChr.foldPrev
structure ToEitherChrNext = structure ToCloseChrNext =
MakeIfCharFolderNext MakeIfCharFolderNext
(struct (struct
type env = {chr1: char, chr2: char} type env = {openChr: char, closeChr: char}
fun loop (strPos, str, absIdx, stl, chr1, chr2) = fun loop (strPos, str, absIdx, stl, openChr, closeChr, openCount) =
if strPos = String.size str then if strPos = String.size str then
case stl of case stl of
str :: stl => loop (0, str, absIdx, stl, chr1, chr2) str :: stl =>
loop (0, str, absIdx, stl, openChr, closeChr, openCount)
| [] => ~1 | [] => ~1
else else
let let
val chr = String.sub (str, strPos) val chr = String.sub (str, strPos)
in in
if chr = chr1 orelse chr = chr2 then absIdx if chr = openChr then
else loop (strPos + 1, str, absIdx + 1, stl, chr1, chr2) loop
( strPos + 1
, str
, absIdx + 1
, stl
, openChr
, closeChr
, openCount + 1
)
else if chr = closeChr then
if openCount = 0 then
absIdx
else
loop
( strPos + 1
, str
, absIdx + 1
, stl
, openChr
, closeChr
, openCount - 1
)
else
loop
( strPos + 1
, str
, absIdx + 1
, stl
, openChr
, closeChr
, openCount
)
end end
fun fStart (strPos, str, _, absIdx, stl, _, {chr1, chr2}) = fun fStart (strPos, str, _, absIdx, stl, _, {openChr, closeChr}) =
loop (strPos, str, absIdx, stl, chr1, chr2) loop (strPos, str, absIdx, stl, openChr, closeChr, 0)
end) end)
val toEitherChrNext = ToEitherChrNext.foldNext val toCloseChrNext = ToCloseChrNext.foldNext
structure NextPairChr = structure NextPairChr =
MakeIfCharFolderNext MakeIfCharFolderNext

View File

@@ -1035,6 +1035,51 @@ struct
deleteAndFinish (app, low, length, buffer, time) deleteAndFinish (app, low, length, buffer, time)
end end
fun deleteInsidePair (app: app_type, openChr, closeChr, time) =
let
val {buffer, cursorIdx, dfa, ...} = app
val buffer = LineGap.goToIdx (cursorIdx, buffer)
val nextIdx =
Cursor.toCloseChrNext
(buffer, cursorIdx, {openChr = openChr, closeChr = closeChr})
in
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
let
val low = Int.min (nextIdx, matchIdx)
val high = Int.max (nextIdx, matchIdx)
in
if high = low + 1 then
NormalFinish.clearMode app
else
let
val deleteLow = low + 1
val length = high - deleteLow
val buffer = LineGap.goToIdx (high, buffer)
val initialMsg = Fn.initMsgs (deleteLow, length, buffer)
val buffer = LineGap.delete (deleteLow, length, buffer)
val (buffer, searchList) = SearchList.build (buffer, dfa)
val buffer = LineGap.goToIdx (low, buffer)
in
NormalFinish.buildTextAndClear
(app, buffer, low, searchList, initialMsg, time)
end
end
end
end
fun finishAfterDeleteInside (app: app_type, origLow, high, time) = fun finishAfterDeleteInside (app: app_type, origLow, high, time) =
if origLow = high then if origLow = high then
NormalFinish.clearMode app NormalFinish.clearMode app

View File

@@ -222,14 +222,18 @@ struct
case chr of case chr of
#"w" => NormalDelete.deleteInsideWord (app, time) #"w" => NormalDelete.deleteInsideWord (app, time)
| #"W" => NormalDelete.deleteInsideWORD (app, time) | #"W" => NormalDelete.deleteInsideWORD (app, time)
| #"(" => NormalDelete.deleteInsideChrOpen (app, chr, time)
| #"[" => NormalDelete.deleteInsideChrOpen (app, chr, time) | #"(" => NormalDelete.deleteInsidePair (app, #"(", #")", time)
| #"{" => NormalDelete.deleteInsideChrOpen (app, chr, time) | #")" => NormalDelete.deleteInsidePair (app, #"(", #")", time)
| #"<" => NormalDelete.deleteInsideChrOpen (app, chr, time)
| #")" => NormalDelete.deleteInsideChrClose (app, chr, time) | #"[" => NormalDelete.deleteInsidePair (app, #"[", #"]", time)
| #"]" => NormalDelete.deleteInsideChrClose (app, chr, time) | #"]" => NormalDelete.deleteInsidePair (app, #"[", #"]", time)
| #"}" => NormalDelete.deleteInsideChrClose (app, chr, time)
| #">" => NormalDelete.deleteInsideChrClose (app, chr, time) | #"{" => NormalDelete.deleteInsidePair (app, #"{", #"}", time)
| #"}" => NormalDelete.deleteInsidePair (app, #"{", #"}", time)
| #"<" => NormalDelete.deleteInsidePair (app, #"<", #">", time)
| #">" => NormalDelete.deleteInsidePair (app, #"<", #">", time)
| _ => NormalFinish.clearMode app | _ => NormalFinish.clearMode app
fun parseDeleteAround (app, chr, time) = fun parseDeleteAround (app, chr, time) =

View File

@@ -1 +1 @@
(((hello))) ( ( ( hello ) ) )