diff --git a/fcore/cursor.sml b/fcore/cursor.sml index 7e81a0d..9bc5d31 100644 --- a/fcore/cursor.sml +++ b/fcore/cursor.sml @@ -209,61 +209,69 @@ struct val toPrevChr = ToPrevChr.foldPrev - structure ToCloseChrNext = - MakeIfCharFolderNext + structure ToOpenChrPrev = + MakeIfCharFolderPrev (struct type env = {openChr: char, closeChr: char} - fun loop (strPos, str, absIdx, stl, openChr, closeChr, openCount) = - if strPos = String.size str then + fun loop (strPos, str, absIdx, stl, openChr, closeChr, closeCount) = + if strPos < 0 then case stl of str :: stl => - loop (0, str, absIdx, stl, openChr, closeChr, openCount) + loop + ( String.size str - 1 + , str + , absIdx + , stl + , openChr + , closeChr + , closeCount + ) | [] => ~1 else let val chr = String.sub (str, strPos) in if chr = openChr then - loop - ( strPos + 1 - , str - , absIdx + 1 - , stl - , openChr - , closeChr - , openCount + 1 - ) - else if chr = closeChr then - if openCount = 0 then + if closeCount = 0 then absIdx else loop - ( strPos + 1 + ( strPos - 1 , str - , absIdx + 1 + , absIdx - 1 , stl , openChr , closeChr - , openCount - 1 + , closeCount - 1 ) - else + else if chr = closeChr then loop - ( strPos + 1 + ( strPos - 1 , str - , absIdx + 1 + , absIdx - 1 , stl , openChr , closeChr - , openCount + , closeCount + 1 + ) + else + loop + ( strPos - 1 + , str + , absIdx - 1 + , stl + , openChr + , closeChr + , closeCount ) end 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) - val toCloseChrNext = ToCloseChrNext.foldNext + val toOpenChrPrev = ToOpenChrPrev.foldPrev structure NextPairChr = MakeIfCharFolderNext diff --git a/fcore/normal-mode/make-normal-delete.sml b/fcore/normal-mode/make-normal-delete.sml index c173c5b..3aa80af 100644 --- a/fcore/normal-mode/make-normal-delete.sml +++ b/fcore/normal-mode/make-normal-delete.sml @@ -1068,29 +1068,56 @@ struct val cursorChr = LineGap.sub (cursorIdx, buffer) in if cursorChr = openChr orelse cursorChr = closeChr then + (* cursor is at pair, so match and delete *) let val otherIdx = Cursor.matchPair (buffer, cursorIdx) in - finishDeletingInsidePair (app, buffer, cursorIdx, otherIdx, dfa, time) - end - else - let - val nextIdx = - Cursor.toCloseChrNext - (buffer, cursorIdx, {openChr = openChr, closeChr = closeChr}) - in - if nextIdx = ~1 then + if otherIdx = ~1 then NormalFinish.clearMode app 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 - val buffer = LineGap.goToIdx (nextIdx, buffer) - val matchIdx = Cursor.matchPair (buffer, nextIdx) + val nextIdx = + Cursor.toNextChr + (buffer, cursorIdx, {findChr = openChr, count = 1}) 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 else finishDeletingInsidePair - (app, buffer, nextIdx, matchIdx, dfa, time) + (app, buffer, prevIdx, otherIdx, dfa, time) end end end @@ -1155,8 +1182,7 @@ struct else let val nextIdx = - Cursor.toCloseChrNext - (buffer, cursorIdx, {openChr = openChr, closeChr = closeChr}) + Cursor.toNextChr (buffer, cursorIdx, {findChr = openChr, count = 1}) in if nextIdx = ~1 then NormalFinish.clearMode app diff --git a/temp.txt b/temp.txt index fd34872..36fba7d 100644 --- a/temp.txt +++ b/temp.txt @@ -1 +1 @@ -( ( ( hello ) ) ) +( ( hello ) ) diff --git a/test/normal-delete.sml b/test/normal-delete.sml index 29f931d..334c762 100644 --- a/test/normal-delete.sml +++ b/test/normal-delete.sml @@ -5075,6 +5075,82 @@ struct 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 = [ dhDelete , dlDelete @@ -5105,5 +5181,6 @@ struct , dawDelete , daWDelete , pairDelete + , diParenDelete ] end diff --git a/todo.md b/todo.md index c140f20..bd33b5d 100644 --- a/todo.md +++ b/todo.md @@ -1,7 +1,7 @@ # To-do list - Add tests for: - - `di` and `da` + - `da` Afterwards, add tests for yanking.