summaryrefslogtreecommitdiff
path: root/internal/slider/slider.go
blob: bfbc06924a4a6752528f94cb4b2a3c6d4c097cd1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package slider

import (
	"fmt"

	"github.com/charmbracelet/bubbles/key"
	"github.com/charmbracelet/bubbles/progress"
	tea "github.com/charmbracelet/bubbletea"
)

type Model struct {
	label    byte
	progress progress.Model
	max      int
	current  int
	mappings keybinds
}

func New(label byte, maxVal int, opts ...progress.Option) Model {
	slider := Model{
		label: label,
		progress: progress.New(
			progress.WithoutPercentage(),
		),
		max:      maxVal,
		current:  maxVal / 2,
		mappings: newKeybinds(),
	}
	for _, opt := range opts {
		opt(&slider.progress)
	}
	return slider
}

func (m Model) Title() string { return fmt.Sprintf("%c", m.label) }

func (m Model) Init() tea.Cmd {
	// Triggering a frame message Update here will force the progress bar to
	// render immediately. This is necessary because progress bars only render
	// when their state changes. Without this, there is a disrepancy between
	// the initial state of the progress bar and the initial state of the slider.

	// There's no sugar-coating it: This is a hack. But it works...
	_, cmd := m.Update(progress.FrameMsg{})
	return cmd
}

func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
	cmds := []tea.Cmd{}
	keys := newKeybinds()

	switch msg := msg.(type) {
	case tea.KeyMsg:
		switch {
		case key.Matches(msg, keys.incRegular):
			m.IncPcnt(0.05)
		case key.Matches(msg, keys.decRegular):
			m.DecPcnt(0.05)
		case key.Matches(msg, keys.incPrecise):
			m.Inc(1)
		case key.Matches(msg, keys.decPrecise):
			m.Dec(1)
		}
		return m, m.progress.SetPercent(m.Pcnt())
	case progress.FrameMsg:
		if m.progress.Percent() != m.Pcnt() {
			cmds = append(cmds, m.progress.SetPercent(m.Pcnt()))
		}
		progressModel, cmd := m.progress.Update(msg)
		m.progress = progressModel.(progress.Model)
		cmds = append(cmds, cmd)
	default:
	}
	return m, tea.Batch(cmds...)
}

func (m Model) ViewValue(current int) string {
	return fmt.Sprintf("(%3d/%d)", current, m.max)
}

func (m Model) View() string {
	return fmt.Sprintf("%v: %v %v", m.Title(), m.progress.View(), m.ViewValue(m.current))
}