diff --git a/fcore/app-update.sml b/fcore/app-update.sml index a371718..51eeef1 100644 --- a/fcore/app-update.sml +++ b/fcore/app-update.sml @@ -101,12 +101,13 @@ struct val {line = bufferLine, idx = bufferIdx, ...} = buffer val bufferIdx = bufferIdx - 1 + val bufferIdx = Cursor.clipIdx (buffer, bufferIdx) val bufferLine = bufferLine - 1 val buffer = LineGap.goToIdx (bufferIdx, buffer) val bufferLine = let - val maxHeight = windowHeight - (TextConstants.ySpace * 2) + val maxHeight = windowHeight - TextConstants.ySpace in TextWindow.getStartLineWithCursorCentered (buffer, bufferIdx, bufferLine, windowWidth, maxHeight) @@ -159,6 +160,7 @@ struct let val buffer = LineGap.goToIdx (cursorIdx, buffer) val cursorIdx = fMove (buffer, cursorIdx) + val cursorIdx = Cursor.clipIdx (buffer, cursorIdx) in helpMove (app, buffer, cursorIdx, count - 1, fMove) end @@ -258,6 +260,7 @@ struct (* move LineGap to cursorIdx, which is necessary for finding newCursorIdx *) val buffer = LineGap.goToIdx (cursorIdx, buffer) val cursorIdx = fMove (buffer, cursorIdx, chr) + val cursorIdx = Cursor.clipIdx (buffer, cursorIdx) in helpMoveToChr (app, buffer, cursorIdx, count - 1, fMove, chr) end @@ -345,7 +348,7 @@ struct * is no longer a valid idx, * clip cursorIdx to the end. *) val buffer = LineGap.goToIdx (cursorIdx, buffer) - val cursorIdx = Cursor.clipIdxAfterDelete (buffer, cursorIdx) + val cursorIdx = Cursor.clipIdx (buffer, cursorIdx) in buildTextAndClear (app, buffer, cursorIdx) end @@ -364,13 +367,6 @@ struct val length = high - low val buffer = LineGap.delete (low, length, buffer) - - (* todo: possibly decrement cursorIdx by 1 - * if deleting put cursorIdx past end of file. - * else, if deleting put cursorIdx before 0, - * ensure that it is clipped to 0. - * else, leave cursorIdx alone. - * *) in helpDelete (app, buffer, low, count - 1, fMove) end diff --git a/fcore/cursor.sml b/fcore/cursor.sml index 2c34fee..e6de8e0 100644 --- a/fcore/cursor.sml +++ b/fcore/cursor.sml @@ -1595,7 +1595,7 @@ struct val lineIdx = Vector.sub (lhd, relativeLine) in if lineIdx = String.size shd - 1 andalso List.null stl then - (* if is end of buffer, return last idx in buffer; * else, + (* if is end of buffer, return last idx in buffer; else, * increment by 1 as we want to go to first char after line break *) bufferIdx + lineIdx else @@ -1715,33 +1715,36 @@ struct end (* Prerequisite: lineGap is moved to cursorIdx *) - fun clipIdxAfterDelete (lineGap: LineGap.t, cursorIdx) = + fun clipIdx (lineGap: LineGap.t, cursorIdx) = let val {rightStrings, idx = bufferIdx, ...} = lineGap in + (* We are trying to check if cursorIdx is within the buffer. *) case rightStrings of - hd :: tl => + _ :: _ :: _ => + (* if there is a string after the hd, + * we are definitely in a valid idx and should return it *) + cursorIdx + | [hd] => let val strIdx = cursorIdx - bufferIdx in - if strIdx < String.size hd then + if strIdx < String.size hd - 1 then + (* if we are before the last char in the string. + * Unix file endings always have \n at the end + * but we do not want cursor to ever go to end + * as vi also does not go to the very end. + * This is why we check strIdx is before the last char. + * *) 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) + (* if end of buffer - 2 is greater than 0, then that; + * else, 0 *) + Int.max (bufferIdx + String.size hd - 2, 0) end - | [] => - Int.max (bufferIdx - 1, 0) + | [] => + (* if end of buffer - 2 is greater than 0, then that; + * else, 0 *) + Int.max (bufferIdx - 2, 0) end end diff --git a/shf b/shf index 740b6b8..a056025 100755 Binary files a/shf and b/shf differ