File: queryinput.go

package info (click to toggle)
jqp 0.7.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 292 kB
  • sloc: makefile: 8
file content (124 lines) | stat: -rw-r--r-- 2,700 bytes parent folder | download
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package queryinput

import (
	"container/list"

	"github.com/charmbracelet/bubbles/textinput"
	tea "github.com/charmbracelet/bubbletea"
	"github.com/charmbracelet/lipgloss"

	"github.com/noahgorstein/jqp/tui/theme"
)

type Bubble struct {
	Styles    Styles
	textinput textinput.Model

	history         *list.List
	historyMaxLen   int
	historySelected *list.Element
}

func New(jqtheme theme.Theme) Bubble {
	s := DefaultStyles()
	s.containerStyle.BorderForeground(jqtheme.Primary)
	ti := textinput.New()
	ti.Focus()
	ti.PromptStyle.Height(1)
	ti.TextStyle.Height(1)
	ti.Prompt = lipgloss.NewStyle().Bold(true).Foreground(jqtheme.Secondary).Render("jq > ")

	return Bubble{
		Styles:    s,
		textinput: ti,

		history:       list.New(),
		historyMaxLen: 512,
	}
}

func (b *Bubble) SetBorderColor(color lipgloss.TerminalColor) {
	b.Styles.containerStyle = b.Styles.containerStyle.BorderForeground(color)
}

func (b Bubble) GetInputValue() string {
	return b.textinput.Value()
}

func (b *Bubble) RotateHistory() {
	b.history.PushFront(b.textinput.Value())
	b.historySelected = b.history.Front()
	if b.history.Len() > b.historyMaxLen {
		b.history.Remove(b.history.Back())
	}
}

func (Bubble) Init() tea.Cmd {
	return textinput.Blink
}

func (b *Bubble) SetWidth(width int) {
	b.Styles.containerStyle = b.Styles.containerStyle.Width(width - b.Styles.containerStyle.GetHorizontalFrameSize())
	b.textinput.Width = width - b.Styles.containerStyle.GetHorizontalFrameSize() - 1
}

func (b Bubble) View() string {
	return b.Styles.containerStyle.Render(b.textinput.View())
}

func (b Bubble) Update(msg tea.Msg) (Bubble, tea.Cmd) {
	switch msg := msg.(type) {
	case tea.KeyMsg:
		return b.updateKeyMsg(msg)
	default:
		var cmd tea.Cmd
		b.textinput, cmd = b.textinput.Update(msg)
		return b, cmd
	}
}

func (b *Bubble) SetQuery(query string) {
	b.textinput.SetValue(query)
}

func (b Bubble) updateKeyMsg(msg tea.KeyMsg) (Bubble, tea.Cmd) {
	switch msg.Type {
	case tea.KeyUp:
		return b.handleKeyUp()
	case tea.KeyDown:
		return b.handleKeyDown()
	case tea.KeyEnter:
		b.RotateHistory()
		return b, nil
	default:
		var cmd tea.Cmd
		b.textinput, cmd = b.textinput.Update(msg)
		return b, cmd
	}
}

func (b Bubble) handleKeyUp() (Bubble, tea.Cmd) {
	if b.history.Len() == 0 {
		return b, nil
	}
	n := b.historySelected.Next()
	if n != nil {
		b.textinput.SetValue(n.Value.(string))
		b.textinput.CursorEnd()
		b.historySelected = n
	}
	return b, nil
}

func (b Bubble) handleKeyDown() (Bubble, tea.Cmd) {
	if b.history.Len() == 0 {
		return b, nil
	}
	p := b.historySelected.Prev()
	if p != nil {
		b.textinput.SetValue(p.Value.(string))
		b.textinput.CursorEnd()
		b.historySelected = p
	}
	return b, nil
}