Skip to content

Commit

Permalink
Fix a bug where viewport y-offset could be negative
Browse files Browse the repository at this point in the history
  • Loading branch information
meowgorithm committed Jan 19, 2022
1 parent 7a6d306 commit daba232
Showing 1 changed file with 13 additions and 8 deletions.
21 changes: 13 additions & 8 deletions viewport/viewport.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,13 @@ func (m Model) AtTop() bool {
// AtBottom returns whether or not the viewport is at or past the very bottom
// position.
func (m Model) AtBottom() bool {
return m.YOffset >= len(m.lines)-m.Height
return m.YOffset >= m.maxYOffset()
}

// PastBottom returns whether or not the viewport is scrolled beyond the last
// line. This can happen when adjusting the viewport height.
func (m Model) PastBottom() bool {
return m.YOffset > len(m.lines)-m.Height
return m.YOffset > m.maxYOffset()
}

// ScrollPercent returns the amount scrolled as a float between 0 and 1.
Expand All @@ -108,6 +108,12 @@ func (m *Model) SetContent(s string) {
}
}

// maxYOffset returns the maximum possible value of the y-offset based on the
// viewport's content and set height.
func (m Model) maxYOffset() int {
return max(0, len(m.lines)-m.Height)
}

// visibleLines returns the lines that should currently be visible in the
// viewport.
func (m Model) visibleLines() (lines []string) {
Expand All @@ -131,7 +137,7 @@ func (m Model) scrollArea() (top, bottom int) {

// SetYOffset sets the Y offset.
func (m *Model) SetYOffset(n int) {
m.YOffset = clamp(n, 0, len(m.lines)-m.Height)
m.YOffset = clamp(n, 0, m.maxYOffset())
}

// ViewDown moves the view down by the number of lines in the viewport.
Expand Down Expand Up @@ -213,12 +219,10 @@ func (m *Model) GotoTop() (lines []string) {

// GotoBottom sets the viewport to the bottom position.
func (m *Model) GotoBottom() (lines []string) {
m.SetYOffset(len(m.lines) - m.Height)
m.SetYOffset(m.maxYOffset())
return m.visibleLines()
}

// COMMANDS

// Sync tells the renderer where the viewport will be located and requests
// a render of the current state of the viewport. It should be called for the
// first render and after a window resize.
Expand Down Expand Up @@ -357,9 +361,10 @@ func (m Model) View() string {
return m.Style.Render(strings.Join(lines, "\n") + extraLines)
}

// ETC

func clamp(v, low, high int) int {
if high < low {
low, high = high, low
}
return min(high, max(low, v))
}

Expand Down

0 comments on commit daba232

Please sign in to comment.