mirror of
https://github.com/zoriya/bubbles.git
synced 2026-08-05 12:46:14 +00:00
chore(viewport): make horizontal scroll API better match vertical scroll API
This commit is contained in:
+24
-22
@@ -39,6 +39,13 @@ type Model struct {
|
||||
// YOffset is the vertical scroll position.
|
||||
YOffset int
|
||||
|
||||
// xOffset is the horizontal scroll position.
|
||||
xOffset int
|
||||
|
||||
// horizontalStep is the number of columns we move left or right during a
|
||||
// default horizontal scroll.
|
||||
horizontalStep int
|
||||
|
||||
// YPosition is the position of the viewport in relation to the terminal
|
||||
// window. It's used in high performance rendering only.
|
||||
YPosition int
|
||||
@@ -59,10 +66,6 @@ type Model struct {
|
||||
// Deprecated: high performance rendering is now deprecated in Bubble Tea.
|
||||
HighPerformanceRendering bool
|
||||
|
||||
// horizontal step represents the step of indent we add with one move left or right.
|
||||
horizontalStep int
|
||||
|
||||
indent int
|
||||
initialized bool
|
||||
lines []string
|
||||
longestLineWidth int
|
||||
@@ -138,8 +141,8 @@ func (m Model) visibleLines() (lines []string) {
|
||||
|
||||
cutLines := make([]string, len(lines))
|
||||
for i, line := range lines {
|
||||
if m.indent > 0 {
|
||||
line = ansi.TruncateLeft(line, m.indent, "")
|
||||
if m.xOffset > 0 {
|
||||
line = ansi.TruncateLeft(line, m.xOffset, "")
|
||||
}
|
||||
line = ansi.Truncate(line, m.Width, "")
|
||||
cutLines[i] = line
|
||||
@@ -311,9 +314,9 @@ func ViewUp(m Model, lines []string) tea.Cmd {
|
||||
return tea.ScrollUp(lines, top, bottom)
|
||||
}
|
||||
|
||||
// SetHorizontalStep is a setter for `horizontalStep`.
|
||||
// Must be set before `MoveLeft` or `MoveRight` is used.
|
||||
// If 0 or negative, left/right movement doesn't work.
|
||||
// SetHorizontalStep sets the amount of cells that the viewport moves in the
|
||||
// default viewport keymapping. If set to 0 or less, horizontal scrolling is
|
||||
// disabled.
|
||||
func (m *Model) SetHorizontalStep(n int) {
|
||||
if n < 0 {
|
||||
n = 0
|
||||
@@ -322,27 +325,26 @@ func (m *Model) SetHorizontalStep(n int) {
|
||||
m.horizontalStep = n
|
||||
}
|
||||
|
||||
// MoveLeft moves all lines to set runes left.
|
||||
// If current indent is 0, it doesn't work.
|
||||
func (m *Model) MoveLeft() {
|
||||
m.indent -= m.horizontalStep
|
||||
if m.indent < 0 {
|
||||
m.indent = 0
|
||||
// MoveLeft moves the viewport to the left by the given number of columns.
|
||||
func (m *Model) MoveLeft(cols int) {
|
||||
m.xOffset -= cols
|
||||
if m.xOffset < 0 {
|
||||
m.xOffset = 0
|
||||
}
|
||||
}
|
||||
|
||||
// MoveRight moves all lines to set runes right.
|
||||
func (m *Model) MoveRight() {
|
||||
// MoveRight moves viewport to the right by the given number of columns.
|
||||
func (m *Model) MoveRight(cols int) {
|
||||
// prevents over scrolling to the right
|
||||
if m.indent >= m.longestLineWidth-m.Width {
|
||||
if m.xOffset >= m.longestLineWidth-m.Width {
|
||||
return
|
||||
}
|
||||
m.indent += m.horizontalStep
|
||||
m.xOffset += cols
|
||||
}
|
||||
|
||||
// Resets lines indent to zero.
|
||||
func (m *Model) ResetIndent() {
|
||||
m.indent = 0
|
||||
m.xOffset = 0
|
||||
}
|
||||
|
||||
// Update handles standard message-based viewport updates.
|
||||
@@ -401,10 +403,10 @@ func (m Model) updateAsModel(msg tea.Msg) (Model, tea.Cmd) {
|
||||
}
|
||||
|
||||
case key.Matches(msg, m.KeyMap.Left):
|
||||
m.MoveLeft()
|
||||
m.MoveLeft(m.horizontalStep)
|
||||
|
||||
case key.Matches(msg, m.KeyMap.Right):
|
||||
m.MoveRight()
|
||||
m.MoveRight(m.horizontalStep)
|
||||
}
|
||||
|
||||
case tea.MouseMsg:
|
||||
|
||||
+30
-28
@@ -91,28 +91,28 @@ func TestMoveLeft(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
m := New(10, 10)
|
||||
if m.indent != zeroPosition {
|
||||
t.Errorf("default indent should be %d, got %d", zeroPosition, m.indent)
|
||||
if m.xOffset != zeroPosition {
|
||||
t.Errorf("default indent should be %d, got %d", zeroPosition, m.xOffset)
|
||||
}
|
||||
|
||||
m.MoveLeft()
|
||||
if m.indent != zeroPosition {
|
||||
t.Errorf("indent should be %d, got %d", zeroPosition, m.indent)
|
||||
m.MoveLeft(m.horizontalStep)
|
||||
if m.xOffset != zeroPosition {
|
||||
t.Errorf("indent should be %d, got %d", zeroPosition, m.xOffset)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("move", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
m := New(10, 10)
|
||||
if m.indent != zeroPosition {
|
||||
t.Errorf("default indent should be %d, got %d", zeroPosition, m.indent)
|
||||
if m.xOffset != zeroPosition {
|
||||
t.Errorf("default indent should be %d, got %d", zeroPosition, m.xOffset)
|
||||
}
|
||||
|
||||
m.indent = defaultHorizontalStep * 2
|
||||
m.MoveLeft()
|
||||
m.xOffset = defaultHorizontalStep * 2
|
||||
m.MoveLeft(m.horizontalStep)
|
||||
newIndent := defaultHorizontalStep
|
||||
if m.indent != newIndent {
|
||||
t.Errorf("indent should be %d, got %d", newIndent, m.indent)
|
||||
if m.xOffset != newIndent {
|
||||
t.Errorf("indent should be %d, got %d", newIndent, m.xOffset)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -127,14 +127,14 @@ func TestMoveRight(t *testing.T) {
|
||||
|
||||
m := New(10, 10)
|
||||
m.SetContent("Some line that is longer than width")
|
||||
if m.indent != zeroPosition {
|
||||
t.Errorf("default indent should be %d, got %d", zeroPosition, m.indent)
|
||||
if m.xOffset != zeroPosition {
|
||||
t.Errorf("default indent should be %d, got %d", zeroPosition, m.xOffset)
|
||||
}
|
||||
|
||||
m.MoveRight()
|
||||
m.MoveRight(m.horizontalStep)
|
||||
newIndent := defaultHorizontalStep
|
||||
if m.indent != newIndent {
|
||||
t.Errorf("indent should be %d, got %d", newIndent, m.indent)
|
||||
if m.xOffset != newIndent {
|
||||
t.Errorf("indent should be %d, got %d", newIndent, m.xOffset)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -148,11 +148,11 @@ func TestResetIndent(t *testing.T) {
|
||||
zeroPosition := 0
|
||||
|
||||
m := New(10, 10)
|
||||
m.indent = 500
|
||||
m.xOffset = 500
|
||||
|
||||
m.ResetIndent()
|
||||
if m.indent != zeroPosition {
|
||||
t.Errorf("indent should be %d, got %d", zeroPosition, m.indent)
|
||||
if m.xOffset != zeroPosition {
|
||||
t.Errorf("indent should be %d, got %d", zeroPosition, m.xOffset)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -196,7 +196,7 @@ func TestVisibleLines(t *testing.T) {
|
||||
|
||||
m := New(10, 10)
|
||||
list := m.visibleLines()
|
||||
m.indent = 5
|
||||
m.xOffset = 5
|
||||
|
||||
if len(list) != 0 {
|
||||
t.Errorf("list should be empty, got %d", len(list))
|
||||
@@ -274,10 +274,10 @@ func TestVisibleLines(t *testing.T) {
|
||||
}
|
||||
|
||||
// move right
|
||||
m.MoveRight()
|
||||
m.MoveRight(m.horizontalStep)
|
||||
list = m.visibleLines()
|
||||
|
||||
newPrefix := perceptPrefix[m.indent:]
|
||||
newPrefix := perceptPrefix[m.xOffset:]
|
||||
if !strings.HasPrefix(list[0], newPrefix) {
|
||||
t.Errorf("first list item has to have prefix %s, get %s", newPrefix, list[0])
|
||||
}
|
||||
@@ -287,7 +287,7 @@ func TestVisibleLines(t *testing.T) {
|
||||
}
|
||||
|
||||
// move left
|
||||
m.MoveLeft()
|
||||
m.MoveLeft(m.horizontalStep)
|
||||
list = m.visibleLines()
|
||||
if !strings.HasPrefix(list[0], perceptPrefix) {
|
||||
t.Errorf("first list item has to have prefix %s", perceptPrefix)
|
||||
@@ -301,6 +301,8 @@ func TestVisibleLines(t *testing.T) {
|
||||
t.Run("list: with 2 cells symbols: horizontal scroll", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const horizontalStep = 5
|
||||
|
||||
initList := []string{
|
||||
"あいうえお",
|
||||
"Aあいうえお",
|
||||
@@ -327,7 +329,7 @@ func TestVisibleLines(t *testing.T) {
|
||||
}
|
||||
|
||||
// move right
|
||||
m.MoveRight()
|
||||
m.MoveRight(horizontalStep)
|
||||
list = m.visibleLines()
|
||||
|
||||
for i := range list {
|
||||
@@ -338,7 +340,7 @@ func TestVisibleLines(t *testing.T) {
|
||||
}
|
||||
|
||||
// move left
|
||||
m.MoveLeft()
|
||||
m.MoveLeft(horizontalStep)
|
||||
list = m.visibleLines()
|
||||
for i := range list {
|
||||
if list[i] != initList[i] {
|
||||
@@ -347,8 +349,8 @@ func TestVisibleLines(t *testing.T) {
|
||||
}
|
||||
|
||||
// move left second times do not change lites if indent == 0
|
||||
m.indent = 0
|
||||
m.MoveLeft()
|
||||
m.xOffset = 0
|
||||
m.MoveLeft(horizontalStep)
|
||||
list = m.visibleLines()
|
||||
for i := range list {
|
||||
if list[i] != initList[i] {
|
||||
@@ -368,7 +370,7 @@ func TestRightOverscroll(t *testing.T) {
|
||||
m.SetContent(content)
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
m.MoveRight()
|
||||
m.MoveRight(m.horizontalStep)
|
||||
}
|
||||
|
||||
visibleLines := m.visibleLines()
|
||||
|
||||
Reference in New Issue
Block a user