mirror of
https://github.com/anotherhadi/spilltea.git
synced 2026-05-20 01:32:33 +02:00
e8e64eff12
Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
151 lines
3.0 KiB
Go
151 lines
3.0 KiB
Go
package scope
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"charm.land/bubbles/v2/help"
|
|
"charm.land/bubbles/v2/key"
|
|
"charm.land/bubbles/v2/textarea"
|
|
tea "charm.land/bubbletea/v2"
|
|
"charm.land/lipgloss/v2"
|
|
"github.com/anotherhadi/spilltea/internal/keys"
|
|
"github.com/anotherhadi/spilltea/internal/style"
|
|
)
|
|
|
|
const (
|
|
fieldNone = -1
|
|
fieldWhitelist = 0
|
|
fieldBlacklist = 1
|
|
)
|
|
|
|
const (
|
|
minTaH = 3
|
|
maxTaH = 12
|
|
fixedH = 8 // (blank + label + desc + blank) x2
|
|
)
|
|
|
|
type ScopeChangedMsg struct {
|
|
Whitelist []string
|
|
Blacklist []string
|
|
}
|
|
|
|
type Model struct {
|
|
focusIdx int
|
|
|
|
wlTextarea textarea.Model
|
|
blTextarea textarea.Model
|
|
|
|
innerH int
|
|
width int
|
|
height int
|
|
|
|
help help.Model
|
|
}
|
|
|
|
func New(name, path string) Model {
|
|
wl := style.NewTextarea(true)
|
|
wl.Placeholder = "one pattern per line..."
|
|
|
|
bl := style.NewTextarea(true)
|
|
bl.Placeholder = "one pattern per line..."
|
|
bl.Blur()
|
|
|
|
return Model{
|
|
focusIdx: fieldNone,
|
|
wlTextarea: wl,
|
|
blTextarea: bl,
|
|
help: style.NewHelp(),
|
|
}
|
|
}
|
|
|
|
func (m Model) Init() tea.Cmd { return nil }
|
|
|
|
func (m *Model) SetScope(whitelist, blacklist []string) {
|
|
m.wlTextarea.SetValue(strings.Join(whitelist, "\n"))
|
|
m.blTextarea.SetValue(strings.Join(blacklist, "\n"))
|
|
}
|
|
|
|
func (m *Model) SetSize(w, h int) {
|
|
m.width = w
|
|
m.height = h
|
|
m.syncLayout()
|
|
}
|
|
|
|
func (m *Model) syncLayout() {
|
|
if m.width == 0 {
|
|
return
|
|
}
|
|
m.help.SetWidth(m.width - 2)
|
|
|
|
statusH := strings.Count(m.renderStatusBar(), "\n") + 1
|
|
panelH := m.height - statusH
|
|
m.innerH = max(1, style.PanelContentH(panelH))
|
|
|
|
taH := (m.innerH - fixedH) / 2
|
|
if taH < minTaH {
|
|
taH = minTaH
|
|
}
|
|
if taH > maxTaH {
|
|
taH = maxTaH
|
|
}
|
|
// width - 2 (panel border) - 1 (leading space in view) - 3 (right margin + cursor)
|
|
taW := max(1, m.width-6)
|
|
m.wlTextarea.SetWidth(taW)
|
|
m.wlTextarea.SetHeight(taH)
|
|
m.blTextarea.SetWidth(taW)
|
|
m.blTextarea.SetHeight(taH)
|
|
}
|
|
|
|
func (m Model) IsEditing() bool {
|
|
return m.focusIdx == fieldWhitelist || m.focusIdx == fieldBlacklist
|
|
}
|
|
|
|
func (m *Model) scopeChangedCmd() tea.Cmd {
|
|
wl := parseLines(m.wlTextarea.Value())
|
|
bl := parseLines(m.blTextarea.Value())
|
|
return func() tea.Msg {
|
|
return ScopeChangedMsg{Whitelist: wl, Blacklist: bl}
|
|
}
|
|
}
|
|
|
|
func parseLines(s string) []string {
|
|
var out []string
|
|
for _, line := range strings.Split(s, "\n") {
|
|
if t := strings.TrimSpace(line); t != "" {
|
|
out = append(out, t)
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
func (m Model) renderStatusBar() string {
|
|
return lipgloss.NewStyle().Padding(0, 1).Render(
|
|
m.help.View(formKeyMap{focusIdx: m.focusIdx}),
|
|
)
|
|
}
|
|
|
|
type formKeyMap struct {
|
|
focusIdx int
|
|
}
|
|
|
|
func (k formKeyMap) ShortHelp() []key.Binding {
|
|
cycle := keys.Keys.Global.CycleFocus
|
|
hlp := keys.Keys.Global.Help
|
|
|
|
switch k.focusIdx {
|
|
case fieldWhitelist, fieldBlacklist:
|
|
esc := keys.Keys.Global.Escape
|
|
escBinding := key.NewBinding(key.WithKeys(esc.Keys()...), key.WithHelp(esc.Help().Key, "unfocus"))
|
|
return []key.Binding{
|
|
key.NewBinding(key.WithKeys("enter"), key.WithHelp("enter", "new line")),
|
|
escBinding,
|
|
cycle,
|
|
}
|
|
}
|
|
return []key.Binding{cycle, hlp}
|
|
}
|
|
|
|
func (k formKeyMap) FullHelp() [][]key.Binding {
|
|
return [][]key.Binding{k.ShortHelp()}
|
|
}
|