diff --git a/fcore/app-update.sml b/fcore/app-update.sml index 2ffce8c..a371718 100644 --- a/fcore/app-update.sml +++ b/fcore/app-update.sml @@ -340,7 +340,15 @@ struct fun helpDelete (app: app_type, buffer, cursorIdx, count, fMove) = if count = 0 then - buildTextAndClear (app, buffer, cursorIdx) + let + (* If we have deleted from the buffer so that cursorIdx + * is no longer a valid idx, + * clip cursorIdx to the end. *) + val buffer = LineGap.goToIdx (cursorIdx, buffer) + val cursorIdx = Cursor.clipIdxAfterDelete (buffer, cursorIdx) + in + buildTextAndClear (app, buffer, cursorIdx) + end else let (* get otherIdx, where cursor will want to go after motion. *) diff --git a/fcore/cursor.sml b/fcore/cursor.sml index 677aa3b..2c34fee 100644 --- a/fcore/cursor.sml +++ b/fcore/cursor.sml @@ -1713,4 +1713,35 @@ struct end | [] => true end + + (* Prerequisite: lineGap is moved to cursorIdx *) + fun clipIdxAfterDelete (lineGap: LineGap.t, cursorIdx) = + let + val {rightStrings, idx = bufferIdx, ...} = lineGap + in + case rightStrings of + hd :: tl => + let + val strIdx = cursorIdx - bufferIdx + in + if strIdx < String.size hd then + cursorIdx + else + (* strIdx is in tl *) + (case tl of + tlhd :: tltl => + let + val strIdx = strIdx - String.size hd + in + if strIdx < String.size tlhd then + cursorIdx + else + bufferIdx + String.size hd + String.size tlhd - 1 + end + | [] => + bufferIdx + String.size hd - 1) + end + | [] => + Int.max (bufferIdx - 1, 0) + end end diff --git a/shf b/shf index 8e81a70..740b6b8 100755 Binary files a/shf and b/shf differ