@@ -33,18 +33,19 @@ const (
34// DiffView represents a view for displaying differences between two files.
34// DiffView represents a view for displaying differences between two files.
35type DiffView struct {
35type DiffView struct {
36− layout layout
36+ layout layout
37− before file
37+ before file
38− after file
38+ after file
39− contextLines int
39+ contextLines int
40− lineNumbers bool
40+ lineNumbers bool
41− height int
41+ height int
42− width int
42+ width int
43− xOffset int
43+ xOffset int
44− yOffset int
44+ yOffset int
45− style Style
46+ style Style
46− tabWidth int
47+ tabWidth int
47− chromaStyle *chroma.Style
48+ chromaStyle *chroma.Style
49 isComputed bool
50 isComputed bool
@@ -53,6 +54,7 @@ type DiffView struct {
54 splitHunks []splitHunk
55 splitHunks []splitHunk
56 codeWidth int
58 codeWidth int
57 fullCodeWidth int // with leading symbols
59 fullCodeWidth int // with leading symbols
58 extraColOnAfter bool // add extra column on after panel
60 extraColOnAfter bool // add extra column on after panel
@@ -138,6 +140,12 @@ func (dv *DiffView) YOffset(yOffset int) *DiffView {
138 return dv
140 return dv
143+// InfiniteYScroll allows the YOffset to scroll beyond the last line.
144+func (dv *DiffView) InfiniteYScroll(infiniteYScroll bool) *DiffView {
145+ dv.infiniteYScroll = infiniteYScroll
141// TabWidth sets the tab width. Only relevant for code that contains tabs, like
149// TabWidth sets the tab width. Only relevant for code that contains tabs, like
142// Go code.
150// Go code.
143func (dv *DiffView) TabWidth(tabWidth int) *DiffView {
151func (dv *DiffView) TabWidth(tabWidth int) *DiffView {
@@ -161,6 +169,8 @@ func (dv *DiffView) String() string {
161 dv.convertDiffToSplit()
169 dv.convertDiffToSplit()
162 dv.adjustStyles()
170 dv.adjustStyles()
163 dv.detectNumDigits()
171 dv.detectNumDigits()
172+ dv.detectTotalLines()
173+ dv.preventInfiniteYScroll()
165 if dv.width <= 0 {
175 if dv.width <= 0 {
166 dv.detectCodeWidth()
176 dv.detectCodeWidth()
@@ -251,6 +261,37 @@ func (dv *DiffView) detectNumDigits() {
264+func (dv *DiffView) detectTotalLines() {
269+ for _, h := range dv.unified.Hunks {
270+ dv.totalLines += 1 + len(h.Lines)
273+ for _, h := range dv.splitHunks {
274+ dv.totalLines += 1 + len(h.lines)
279+func (dv *DiffView) preventInfiniteYScroll() {
280+ if dv.infiniteYScroll {
284+ // clamp yOffset to prevent scrolling beyond the last line
286+ maxYOffset := max(0, dv.totalLines-dv.height)
287+ dv.yOffset = min(dv.yOffset, maxYOffset)
289+ // if no height limit, ensure yOffset doesn't exceed total lines
290+ dv.yOffset = min(dv.yOffset, max(0, dv.totalLines-1))
292+ dv.yOffset = max(0, dv.yOffset) // ensure yOffset is not negative
254// detectCodeWidth calculates the maximum width of code lines in the diff view.
295// detectCodeWidth calculates the maximum width of code lines in the diff view.
255func (dv *DiffView) detectCodeWidth() {
296func (dv *DiffView) detectCodeWidth() {
256 switch dv.layout {
297 switch dv.layout {