Repository: jesseduffield/lazygit
File: pkg/gui/controllers/scroll_off_margin.go (Go)

Code before:
package controllers

import (
	"github.com/jesseduffield/lazygit/pkg/gui/types"
)

// To be called after pressing up-arrow; checks whether the cursor entered the
// top scroll-off margin, and so the view needs to be scrolled up one line
func checkScrollUp(view types.IViewTrait, scrollOffMargin int, lineIdxBefore int, lineIdxAfter int) {
	startIdx, length := view.ViewPortYBounds()
	// scroll only if the view is tall enough to have room for both the top and
	// bottom scroll-off margins...
	if length > scrollOffMargin*2 &&
		// ... and the "before" position was visible (this could be false if the
		// scroll wheel was used to scroll the selected line out of view)
		lineIdxBefore >= startIdx && lineIdxBefore < startIdx+length {
		marginEnd := startIdx + scrollOffMargin
		// ... and the "after" position is within the top margin (or before it)
		if lineIdxAfter < marginEnd {
			view.ScrollUp(marginEnd - lineIdxAfter)
		}
	}
}

// To be called after pressing down-arrow; checks whether the cursor entered the
// bottom scroll-off margin, and so the view needs to be scrolled down one line
func checkScrollDown(view types.IViewTrait, scrollOffMargin int, lineIdxBefore int, lineIdxAfter int) {
	startIdx, length := view.ViewPortYBounds()
	// scroll only if the view is tall enough to have room for both the top and
	// bottom scroll-off margins...
	if length > scrollOffMargin*2 &&
		// ... and the "before" position was visible (this could be false if the
		// scroll wheel was used to scroll the selected line out of view)
		lineIdxBefore >= startIdx && lineIdxBefore < startIdx+length {
		marginStart := startIdx + length - scrollOffMargin - 1
		// ... and the "after" position is within the bottom margin (or after it)
		if lineIdxAfter > marginStart {
			view.ScrollDown(lineIdxAfter - marginStart)
		}
	}
}


Review comment (suggestion):
I changed the logic here again completely, because the previous one wouldn't work well when section headers are involved.

I pushed a branch `section-headers-in-keybindings-menu-integration` so that you can test the keybindings menu branch combined with this one if you want.

Code after:
			return marginEnd - lineIdxAfter
		}
	}

	return 0
}

func calculateLinesToScrollDown(viewPortStart int, viewPortHeight int, scrollOffMargin int, lineIdxBefore int, lineIdxAfter int) int {
	// Cap the margin to half the view height. This allows setting the config to
	// a very large value to keep the cursor always in the middle of the screen.
	// Use -.5 so that if the height is even, the bottom margin is one line lower
	// than the top margin.
	scrollOffMargin = utils.Min(scrollOffMargin, int((float64(viewPortHeight)-.5)/2))

	// Scroll only if the "before" position was visible (this could be false if
	// the scroll wheel was used to scroll the selected line out of view) ...
	if lineIdxBefore >= viewPortStart && lineIdxBefore < viewPortStart+viewPortHeight {
		marginStart := viewPortStart + viewPortHeight - scrollOffMargin - 1
		// ... and the "after" position is within the bottom margin (or after it)
		if lineIdxAfter > marginStart {
			return lineIdxAfter - marginStart
		}
	}

	return 0
}