diff --git a/fcore/normal-mode/normal-move.sml b/fcore/normal-mode/normal-move.sml index a413d5a..458c4d0 100644 --- a/fcore/normal-mode/normal-move.sml +++ b/fcore/normal-mode/normal-move.sml @@ -68,6 +68,13 @@ struct val bufferIdx = Int.max (0, textLength - 1) val bufferLine = bufferLine - 1 + val buffer = LineGap.goToIdx (bufferIdx, buffer) + val bufferIdx = + if Cursor.isOnNewlineAfterChr (buffer, bufferIdx) then + Int.max (0, bufferIdx - 1) + else + bufferIdx + val buffer = LineGap.goToIdx (bufferIdx, buffer) val visualScrollColumn = TextScroll.getScrollColumn @@ -248,10 +255,8 @@ struct val lineIdx = LineGap.lineNumberToIdx (newCursorLineNumber, buffer) val lineIdx = - if Cursor.isPrevChrStartOfLine (buffer, lineIdx) then - lineIdx - else - lineIdx - 1 + if Cursor.isPrevChrStartOfLine (buffer, lineIdx) then lineIdx + else lineIdx - 1 val buffer = LineGap.goToIdx (lineIdx, buffer) val lineIdx = Cursor.vi0 (buffer, lineIdx) @@ -274,10 +279,8 @@ struct val buffer = LineGap.goToIdx (lineIdx, buffer) val lineIdx = - if Cursor.isPrevChrStartOfLine (buffer, lineIdx) then - lineIdx - else - lineIdx + 1 + if Cursor.isPrevChrStartOfLine (buffer, lineIdx) then lineIdx + else lineIdx + 1 val lineIdx = if lineIdx >= #textLength buffer - 1 then diff --git a/test/normal-move.sml b/test/normal-move.sml index 0fa5e0a..e33ccfa 100644 --- a/test/normal-move.sml +++ b/test/normal-move.sml @@ -1328,23 +1328,55 @@ struct ] val GMove = describe "move motion 'G'" - [test "moves cursor to last char in buffer" (fn _ => - (* Note: We assume unix-style line endings: - * End of file always has \n at the end. - * We don't want cursor to ever reach this last \n - * so we say last char is the char before \n - * *) - let - (* arrange *) - val str = "01234\n56789\n" - val app = TestUtils.init str + [ test + "moves cursor to second last char in buffer, \ + \if last char is a newline preced by a non-newline" + (fn _ => + (* Note: We assume unix-style line endings: + * End of file always has \n at the end. *) + let + (* arrange *) + val str = "01234\n56789\n" + val app = TestUtils.init str - (* act *) - val app = TestUtils.update (app, CHAR_EVENT #"G") - in - (* assert *) - Expect.isTrue (#cursorIdx app = String.size str - 1) - end)] + (* act *) + val app = TestUtils.update (app, CHAR_EVENT #"G") + in + (* assert *) + Expect.isTrue (#cursorIdx app = String.size str - 2) + end) + , test + "moves cursor to last char in buffer, \ + \if last char is a newline and second-last char is also a newline" + (fn _ => + let + (* arrange *) + val str = "01234\n5678\n\n" + val app = TestUtils.init str + + (* act *) + val app = TestUtils.update (app, CHAR_EVENT #"G") + in + (* assert *) + Expect.isTrue (#cursorIdx app = String.size str - 1) + end) + , test + "moves cursor to last char in buffer, \ + \if last char is not a newline and second-last char \ + \is also not a newline" + (fn _ => + let + (* arrange *) + val str = "01234\n5678\n\n" + val app = TestUtils.init str + + (* act *) + val app = TestUtils.update (app, CHAR_EVENT #"G") + in + (* assert *) + Expect.isTrue (#cursorIdx app = String.size str - 1) + end) + ] val percentMove = describe "move motion '%'" [ test "moves to next ) when cursor is on (" (fn _ =>