Repository: zyedidia/micro
File: internal/action/actions.go (Go)

Code before:
	if !h.Cursor.HasSelection() {
		h.Cursor.OrigSelection[0] = h.Cursor.Loc
	}
	h.MoveCursorUp(h.BufView().Height)
	h.Cursor.SelectTo(h.Cursor.Loc)
	h.Relocate()
	return true
}

// SelectPageDown selects down one page
func (h *BufPane) SelectPageDown() bool {
	if !h.Cursor.HasSelection() {
		h.Cursor.OrigSelection[0] = h.Cursor.Loc
	}
	h.MoveCursorDown(h.BufView().Height)
	h.Cursor.SelectTo(h.Cursor.Loc)
	h.Relocate()
	return true
}

// CursorPageUp scrolls the view up a page,
// keeping the cursor at the same relative position in the view
func (h *BufPane) CursorPageUp() bool {
	scrollmargin := int(h.Buf.Settings["scrollmargin"].(float64))
	pageOffset := h.BufView().Height - scrollmargin
	h.Buf.ClearCursors()
	h.ScrollUp(pageOffset)
	h.MoveCursorUp(pageOffset)
	return true
}

// CursorPageDown scrolls the view down a page,
// keeping the cursor at the same relative position in the view
func (h *BufPane) CursorPageDown() bool {
	scrollmargin := int(h.Buf.Settings["scrollmargin"].(float64))
	pageOffset := h.BufView().Height - scrollmargin
	h.Buf.ClearCursors()
	h.ScrollDown(pageOffset)
	h.ScrollAdjust()
	h.MoveCursorDown(pageOffset)
	return true
}

// HalfPageUp scrolls the view up half a page
func (h *BufPane) HalfPageUp() bool {
	h.ScrollUp(h.BufView().Height / 2)
	return true
}

// HalfPageDown scrolls the view down half a page
func (h *BufPane) HalfPageDown() bool {

Review comment (bug):
I don't think we should remove multicursors. `CursorPageUp` and `CursorPageDown` are still some of the most basic cursor movement actions, so they should work with multiple cursors, like other cursor movement actions.

Moreover, try adding a multicursor and pressing PageUp or PageDown and see what happens.

I suppose it crashes because `CursorPageUp` and `CursorPageDown` are still listed in `MultiActions`, so when the user hits PageUp/Down, `CursorPageUp/Down()` is called multiple times, for each cursor. But I think we want it to remain so (as I said above), so we shouldn't remove them from `MultiActions`, we should rather remove this `h.Buf.ClearCursors()` here.

But removing `h.Buf.ClearCursors()` not enough. Since `CursorPageUp/Down()` is called multiple times, `h.ScrollUp()` is also called multiple times. As a result, the view unexpectedly moves somewhere far far away.

So, how about something like this:

```go
diff --git a/internal/action/actions.go b/internal/action/actions.go
index 7c6779ca..e9e55d1d 100644
--- a/internal/action/actions.go
+++ b/internal/action/actions.go
@@ -1701,8 +1701,9 @@ func (h *BufPane) SelectPageDown() bool {
 func (h *BufPane) CursorPageUp() bool {
 	scrollmargin := int(h.Buf.Settings["scrollmargin"].(float64))
 	pageOffset := h.BufView().Height - scrollmargin
-	h.Buf.ClearCursors()
-	h.ScrollUp(pageOffset)
+	if h.Cursor.Num == 0 {
+		h.ScrollUp(pageOffset)
+	}
 	h.MoveCursorUp(pageOffset)
 	return true
 }
@@ -1712,9 +1713,10 @@ func (h *BufPane) CursorPageUp() bool {
 func (h *BufPane) CursorPageDown() bool {
 	scrollmargin := int(h.Buf.Settings["scrollmargin"].(float64))
 	pageOffset := h.BufView().Height - scrollmargin
-	h.Buf.ClearCursors()
-	h.ScrollDown(pageOffset)
-	h.ScrollAdjust()
+	if h.Cursor.Num == 0 {
+		h.ScrollDown(pageOffset)
+		h.ScrollAdjust()
+	}
 	h.MoveCursorDown(pageOffset)
 	return true
 }
```

Code after:
	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(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(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,
// moving the view to keep cursor at the same relative position in the view
func (h *BufPane) CursorPageUp() bool {
	h.Cursor.Deselect(true)
	pageOverlap := int(h.Buf.Settings["pageoverlap"].(float64))
	scrollAmount := h.BufView().Height - pageOverlap
	h.MoveCursorUp(scrollAmount)
	if h.Cursor.Num == 0 {
		h.ScrollUp(scrollAmount)
	}
	h.Relocate()
	return true