diff --git a/internal/action/actions.go b/internal/action/actions.go index 82ca983f2..4599606c1 100644 --- a/internal/action/actions.go +++ b/internal/action/actions.go @@ -1669,63 +1669,77 @@ func (h *BufPane) End() bool { // PageUp scrolls the view up a page func (h *BufPane) PageUp() bool { - h.ScrollUp(h.BufView().Height) + pageOverlap := int(h.Buf.Settings["pageoverlap"].(float64)) + h.ScrollUp(h.BufView().Height - pageOverlap) return true } // PageDown scrolls the view down a page func (h *BufPane) PageDown() bool { - h.ScrollDown(h.BufView().Height) + pageOverlap := int(h.Buf.Settings["pageoverlap"].(float64)) + h.ScrollDown(h.BufView().Height - pageOverlap) h.ScrollAdjust() return true } // SelectPageUp selects up one page func (h *BufPane) SelectPageUp() bool { + pageOverlap := int(h.Buf.Settings["pageoverlap"].(float64)) + scrollAmount := h.BufView().Height - pageOverlap if !h.Cursor.HasSelection() { h.Cursor.OrigSelection[0] = h.Cursor.Loc } - h.MoveCursorUp(h.BufView().Height) + h.MoveCursorUp(scrollAmount) h.Cursor.SelectTo(h.Cursor.Loc) + if h.Cursor.Num == 0 { + h.ScrollUp(scrollAmount) + } h.Relocate() return true } // SelectPageDown selects down one page func (h *BufPane) SelectPageDown() bool { + pageOverlap := int(h.Buf.Settings["pageoverlap"].(float64)) + scrollAmount := h.BufView().Height - pageOverlap if !h.Cursor.HasSelection() { h.Cursor.OrigSelection[0] = h.Cursor.Loc } - h.MoveCursorDown(h.BufView().Height) + h.MoveCursorDown(scrollAmount) h.Cursor.SelectTo(h.Cursor.Loc) + if h.Cursor.Num == 0 { + h.ScrollDown(scrollAmount) + h.ScrollAdjust() + } h.Relocate() return true } -// CursorPageUp places the cursor a page up +// CursorPageUp places the cursor a page up, +// moving the view to keep cursor at the same relative position in the view func (h *BufPane) CursorPageUp() bool { h.Cursor.Deselect(true) - - if h.Cursor.HasSelection() { - h.Cursor.Loc = h.Cursor.CurSelection[0] - h.Cursor.ResetSelection() - h.Cursor.StoreVisualX() + pageOverlap := int(h.Buf.Settings["pageoverlap"].(float64)) + scrollAmount := h.BufView().Height - pageOverlap + h.MoveCursorUp(scrollAmount) + if h.Cursor.Num == 0 { + h.ScrollUp(scrollAmount) } - h.MoveCursorUp(h.BufView().Height) h.Relocate() return true } -// CursorPageDown places the cursor a page up +// CursorPageDown places the cursor a page down, +// moving the view to keep cursor at the same relative position in the view func (h *BufPane) CursorPageDown() bool { h.Cursor.Deselect(false) - - if h.Cursor.HasSelection() { - h.Cursor.Loc = h.Cursor.CurSelection[1] - h.Cursor.ResetSelection() - h.Cursor.StoreVisualX() + pageOverlap := int(h.Buf.Settings["pageoverlap"].(float64)) + scrollAmount := h.BufView().Height - pageOverlap + h.MoveCursorDown(scrollAmount) + if h.Cursor.Num == 0 { + h.ScrollDown(scrollAmount) + h.ScrollAdjust() } - h.MoveCursorDown(h.BufView().Height) h.Relocate() return true } diff --git a/internal/config/settings.go b/internal/config/settings.go index 910a3072c..ca6d27deb 100644 --- a/internal/config/settings.go +++ b/internal/config/settings.go @@ -32,6 +32,7 @@ var optionValidators = map[string]optionValidator{ "helpsplit": validateChoice, "matchbracestyle": validateChoice, "multiopen": validateChoice, + "pageoverlap": validateNonNegativeValue, "reload": validateChoice, "scrollmargin": validateNonNegativeValue, "scrollspeed": validateNonNegativeValue, @@ -76,6 +77,7 @@ var defaultCommonSettings = map[string]interface{}{ "matchbraceleft": true, "matchbracestyle": "underline", "mkparents": false, + "pageoverlap": float64(2), "permbackup": false, "readonly": false, "reload": "prompt", diff --git a/internal/display/softwrap.go b/internal/display/softwrap.go index 29ddf0017..1abb9bf14 100644 --- a/internal/display/softwrap.go +++ b/internal/display/softwrap.go @@ -291,13 +291,7 @@ func (w *BufWindow) diff(s1, s2 SLoc) int { // within the buffer boundaries. func (w *BufWindow) Scroll(s SLoc, n int) SLoc { if !w.Buf.Settings["softwrap"].(bool) { - s.Line += n - if s.Line < 0 { - s.Line = 0 - } - if s.Line > w.Buf.LinesNum()-1 { - s.Line = w.Buf.LinesNum() - 1 - } + s.Line = util.Clamp(s.Line + n, 0, w.Buf.LinesNum()-1) return s } return w.scroll(s, n) diff --git a/runtime/help/options.md b/runtime/help/options.md index 0ea3b4ee1..c925d52e0 100644 --- a/runtime/help/options.md +++ b/runtime/help/options.md @@ -285,6 +285,13 @@ Here are the available options: default value: `tab` +* `pageoverlap`: the number of lines from the current view to keep in view + when paging up or down. If this is set to 2, for instance, and you page + down, the last two lines of the previous page will be the first two lines + of the next page. + + default value: `2` + * `paste`: treat characters sent from the terminal in a single chunk as a paste event rather than a series of manual key presses. If you are pasting using the terminal keybinding (not `Ctrl-v`, which is micro's default paste