Skip to content

Commit b1e9a91

Browse files
author
Kilian Drechsler
committed
Implemented Lines(), fixed Move methode
- made CurserOffset public because its config - Implemented Lines and changed View to use Lines - fixed Move methode to honore the Cursor-borders
1 parent 029e0a6 commit b1e9a91

File tree

1 file changed

+53
-17
lines changed

1 file changed

+53
-17
lines changed

list/list.go

Lines changed: 53 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package list
22

33
import (
4-
"bytes"
54
"fmt"
65
tea "github.com/charmbracelet/bubbletea"
76
"github.com/muesli/reflow/ansi"
@@ -15,11 +14,12 @@ import (
1514
type Model struct {
1615
focus bool
1716

18-
listItems []item
19-
curIndex int // curser
20-
visibleOffset int // begin of the visible lines
21-
lineCurserOffset int // offset or margin between the cursor and the viewport(visible) border
22-
less func(k, l string) bool // function used for sorting
17+
listItems []item
18+
curIndex int // curser
19+
visibleOffset int // begin of the visible lines
20+
less func(k, l string) bool // function used for sorting
21+
22+
CurserOffset int // offset or margin between the cursor and the viewport(visible) border
2323

2424
Width int
2525
Height int
@@ -66,9 +66,14 @@ func View(model tea.Model) string {
6666
if !ok {
6767
return "could not perform assertion on model"
6868
}
69+
return strings.Join(m.Lines(), "\n")
70+
}
6971

72+
// Lines returns the Visible lines of the list items
73+
// used to display the current user interface
74+
func (m *Model) Lines() []string {
7075
// check visible area
71-
height := m.Height - 1 // TODO question: why does the first line get cut of, if i ommit the -1?
76+
height := m.Height
7277
width := m.Width
7378
offset := m.visibleOffset
7479
if height*width <= 0 {
@@ -123,7 +128,7 @@ func View(model tea.Model) string {
123128
}
124129

125130
var visLines int
126-
var holeString bytes.Buffer
131+
stringLines := make([]string, 0, height)
127132
out:
128133
// Handle list items, start at first visible and go till end of list or visible (break)
129134
for index := offset; index < len(m.listItems); index++ {
@@ -174,8 +179,7 @@ out:
174179
line := fmt.Sprintf("%s%s", linePrefix, item.wrapedLines[0])
175180

176181
// Highlight and write first line
177-
holeString.WriteString(style.Styled(line))
178-
holeString.WriteString("\n")
182+
stringLines = append(stringLines, style.Styled(line))
179183
visLines++
180184

181185
// Only write lines that are visible
@@ -195,17 +199,16 @@ out:
195199
padLine := fmt.Sprintf("%s%s", wrapPrefix, line)
196200

197201
// Highlight and write wraped line
198-
holeString.WriteString(style.Styled(padLine))
199-
holeString.WriteString("\n")
202+
stringLines = append(stringLines, style.Styled(padLine))
200203
visLines++
201204

202205
// Only write lines that are visible
203-
if visLines >= height {
206+
if visLines > height {
204207
break out
205208
}
206209
}
207210
}
208-
return holeString.String()
211+
return stringLines
209212
}
210213

211214
// lineNumber returns line number of the given index
@@ -315,24 +318,57 @@ func (m *Model) Up() error {
315318

316319
// Move moves the cursor by amount, does nothing if amount is 0
317320
// and returns error != nil if amount gos beyond list borders
321+
// or if the CurserOffset is greater than half of the display height
318322
func (m *Model) Move(amount int) error {
323+
// do nothing
319324
if amount == 0 {
320325
return nil
321326
}
327+
var err error
328+
curOff := m.CurserOffset
329+
visOff := m.visibleOffset
330+
height := m.Height
331+
if curOff >= height/2 {
332+
curOff = 0
333+
err = fmt.Errorf("cursor offset must be less than halfe of the display height: setting it to zero")
334+
}
335+
322336
target := m.curIndex + amount
323337
if !m.CheckWithinBorder(target) {
324338
return fmt.Errorf("Cant move outside the list: %d", target)
325339
}
340+
// move visible part of list if Curser is going beyond border.
341+
lowerBorder := height + visOff - curOff
342+
upperBorder := visOff + curOff
343+
344+
direction := 1
345+
if amount < 0 {
346+
direction = -1
347+
}
348+
349+
// visible Down movement
350+
if direction > 0 && target > lowerBorder {
351+
visOff = target - (height - curOff)
352+
}
353+
// visible Up movement
354+
if direction < 0 && target < upperBorder {
355+
visOff = target-curOff
356+
}
357+
// dont go infront of list begin
358+
if visOff < 0 {
359+
visOff = 0
360+
}
326361
m.curIndex = target
327-
return nil
362+
m.visibleOffset = visOff
363+
return err
328364
}
329365

330366
// NewModel returns a Model with some save/sane defaults
331367
func NewModel() Model {
332368
p := termenv.ColorProfile()
333369
style := termenv.Style{}.Background(p.Color("#ff0000"))
334370
return Model{
335-
lineCurserOffset: 5,
371+
CurserOffset: 5,
336372

337373
Wrap: true,
338374

@@ -422,7 +458,7 @@ func (m *Model) Top() {
422458
func (m *Model) Bottom() {
423459
end := len(m.listItems) - 1
424460
m.curIndex = end
425-
maxVisItems := m.Height - m.lineCurserOffset
461+
maxVisItems := m.Height - m.CurserOffset
426462
var visLines, smallestVisIndex int
427463
for c := end; visLines < maxVisItems; c-- {
428464
if c < 0 {

0 commit comments

Comments
 (0)