Skip to content

Commit

Permalink
Another attempt to fix (half-)page-up/down for multi-line items
Browse files Browse the repository at this point in the history
Fix #4069
  • Loading branch information
junegunn committed Nov 8, 2024
1 parent 4a85843 commit 9c94f9c
Showing 1 changed file with 50 additions and 13 deletions.
63 changes: 50 additions & 13 deletions src/terminal.go
Original file line number Diff line number Diff line change
Expand Up @@ -4411,35 +4411,72 @@ func (t *Terminal) Loop() error {
t.input = append(append(t.input[:t.cx], t.yanked...), suffix...)
t.cx += len(t.yanked)
case actPageUp, actPageDown, actHalfPageUp, actHalfPageDown:
// Calculate the number of lines to move
maxItems := t.maxItems()
linesToMove := maxItems - 1
if a.t == actHalfPageUp || a.t == actHalfPageDown {
linesToMove = maxItems / 2
}
// Move at least one line even in a very short window
linesToMove = util.Max(1, linesToMove)

// Determine the direction of the movement
direction := -1
if a.t == actPageUp || a.t == actHalfPageUp {
direction = 1
}

moved := false
for linesToMove > 0 {
currentItem := t.currentItem()
if currentItem == nil {
break
}
// In non-default layout, items are listed from top to bottom
if t.layout != layoutDefault {
direction *= -1
}

itemLines, _ := t.numItemLines(currentItem, maxItems)
linesToMove -= itemLines
if moved && linesToMove < 0 {
break
// We can simply add the number of lines to the current position in
// single-line mode
if !t.canSpanMultiLines() {
t.vset(t.cy + direction*linesToMove)
req(reqList)
break
}

// But in multi-line mode, we need to carefully limit the amount of
// vertical movement so that items are not skipped. In order to do
// this, we calculate the minimum or maximum offset based on the
// direction of the movement and the number of lines of the items
// around the current scroll offset.
var minOffset, maxOffset, lineSum int
if direction > 0 {
maxOffset = t.offset
for ; maxOffset < t.merger.Length(); maxOffset++ {
itemLines, _ := t.numItemLines(t.merger.Get(maxOffset).item, maxItems)
lineSum += itemLines
if lineSum >= maxItems {
break
}
}
} else {
minOffset = t.offset
for ; minOffset >= 0 && minOffset < t.merger.Length(); minOffset-- {
itemLines, _ := t.numItemLines(t.merger.Get(minOffset).item, maxItems)
lineSum += itemLines
if lineSum >= maxItems {
if lineSum > maxItems {
minOffset++
}
break
}
}
}

for ; linesToMove > 0; linesToMove-- {
cy := t.cy
t.vmove(direction, false)
if cy == t.cy {
t.vset(cy + direction)
t.constrain()
if cy == t.cy ||
direction > 0 && t.offset >= maxOffset ||
direction < 0 && t.offset <= minOffset {
break
}
moved = true
}
req(reqList)
case actOffsetUp, actOffsetDown:
Expand Down

0 comments on commit 9c94f9c

Please sign in to comment.