diff options
| author | ewy <ewy0@protonmail.com> | 2026-05-02 16:23:36 +0200 |
|---|---|---|
| committer | ewy <ewy0@protonmail.com> | 2026-05-02 16:23:36 +0200 |
| commit | c01a06e38d0b0331f459cd439ce7706ef1556e50 (patch) | |
| tree | 8bee63be92b6301d169be6113dfc3bbf16d37c9e /menu | |
| parent | 1e932e7015ac9d21a1f92ad57cd0c109f58bb29f (diff) | |
* fix infinite loop on not found
* add bash tab completion script (will have install option in the future)
* add search to tui (bound to / and ?)
Diffstat (limited to 'menu')
| -rw-r--r-- | menu/input.go | 47 | ||||
| -rw-r--r-- | menu/model.go | 33 | ||||
| -rw-r--r-- | menu/search.go | 11 | ||||
| -rw-r--r-- | menu/target.go | 9 |
4 files changed, 98 insertions, 2 deletions
diff --git a/menu/input.go b/menu/input.go index cd07543..e2e35b3 100644 --- a/menu/input.go +++ b/menu/input.go @@ -3,8 +3,32 @@ package menu import tea "github.com/charmbracelet/bubbletea" func (m *Model) HandleInput(msg tea.KeyMsg) (tea.Cmd, error) { + + if m.Search.Focused() { + var cmd tea.Cmd + switch msg.String() { + case "ctrl+c": + m.Search.SetValue("") + m.Search.Blur() + case "ctrl+d": + m.Search.Blur() + case "enter": + m.Search.Blur() + default: + result, c := m.Search.Update(msg) + cmd = c + m.Search = result + } + return cmd, nil + } + var cmd tea.Cmd switch msg.String() { + case "/": + m.Search.SetValue("") + fallthrough + case "?": + return m.Search.Focus(), nil case "i", "I": if m.Alt { m.Alt = false @@ -23,6 +47,10 @@ func (m *Model) HandleInput(msg tea.KeyMsg) (tea.Cmd, error) { m.Index-- case "down", "j": m.Index++ + case "n": + m.LeapFilter(1) + case "N": + m.LeapFilter(-1) case "q", "esc", "ctrl+c": m.Cancel = true return tea.Quit, nil @@ -31,11 +59,28 @@ func (m *Model) HandleInput(msg tea.KeyMsg) (tea.Cmd, error) { return tea.Quit, nil } - m.Validate() + _ = m.Validate() return cmd, nil } +func (m *Model) LeapFilter(direction int) { + startIndex := m.Index + for { + m.Index += direction + clamped := m.Validate() + if clamped { + m.Index = startIndex + return + } + + source, target := m.Result() + if m.Highlights(source, target) { + return + } + } +} + func (m *Model) Leap(direction int) { for { source, target := m.Result() diff --git a/menu/model.go b/menu/model.go index aa7b00e..4480c96 100644 --- a/menu/model.go +++ b/menu/model.go @@ -1,6 +1,7 @@ package menu import ( + "github.com/charmbracelet/bubbles/textinput" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/x/term" "github.com/ewy1/pik/model" @@ -9,6 +10,7 @@ import ( "github.com/ewy1/pik/viewport" "github.com/spf13/pflag" "os" + "strings" ) type Model struct { @@ -21,9 +23,31 @@ type Model struct { Height int Alt bool AutoAlt bool + Search textinput.Model Motd string } +func (m *Model) Highlights(src *model.HydratedSource, t model.HydratedTarget) bool { + val := m.Search.Value() + if val == "" { + return false + } + + if strings.Contains(t.Target().Label(), val) { + return true + } + + if strings.Contains(t.Description(src), val) { + return true + } + + if strings.Contains(strings.Join(append(t.Target().Sub(), t.Target().Label()), " "), val) { + return true + } + + return false +} + func (m *Model) Init() tea.Cmd { _, h, err := term.GetSize(0) if err != nil { @@ -79,6 +103,9 @@ func (m *Model) View() string { } result := m.State() result = viewport.Process(result, m.Height) + if m.Search.Focused() { + result = m.AddSearch(result) + } return result } @@ -89,13 +116,16 @@ func (m *Model) Result() (*model.HydratedSource, model.HydratedTarget) { return m.SourceIndices[m.Index], m.Indices[m.Index] } -func (m *Model) Validate() { +func (m *Model) Validate() (clamped bool) { if m.Index < 0 { m.Index = 0 + return true } if m.Index > len(m.Indices)-1 { m.Index = len(m.Indices) - 1 + return true } + return false } var ForcedInlineTerminals = map[string]string{ @@ -117,6 +147,7 @@ func NewModel(st *model.State, hydrators []model.Modder) *Model { SourceIndices: make(map[int]*model.HydratedSource), AutoAlt: !pflag.Lookup("inline").Changed && !isBanned, Motd: motd.One(), + Search: textinput.New(), } idx := 0 for _, src := range st.Sources { diff --git a/menu/search.go b/menu/search.go new file mode 100644 index 0000000..79cc03b --- /dev/null +++ b/menu/search.go @@ -0,0 +1,11 @@ +package menu + +import "strings" + +func (m *Model) AddSearch(croppedInput string) string { + lines := strings.Split(croppedInput, "\n") + lastIndex := len(lines) - 1 + view := m.Search.View() + lines[lastIndex] = view + return strings.Join(lines, "\n") +} diff --git a/menu/target.go b/menu/target.go index f0b35fd..ee31889 100644 --- a/menu/target.go +++ b/menu/target.go @@ -14,6 +14,10 @@ var ( st := lipgloss.NewStyle().Border(lipgloss.OuterHalfBlockBorder(), false, false, false, true) return st }) + TargetHighlightedColor = lipgloss.Color("1") + TargetHighlightedStyle = style.New(func() lipgloss.Style { + return TargetStyle.Get().Foreground(TargetHighlightedColor) + }) SelectedTargetStyle = style.New(func() lipgloss.Style { return TargetStyle.Get().BorderBackground(SelectedTargetBackgroundColor).Background(SelectedTargetBackgroundColor) }) @@ -59,6 +63,11 @@ func (m *Model) Target(src *model.HydratedSource, t model.HydratedTarget, header } selectionStyle := TargetStyle selectionDescriptionStyle := TargetDescriptionStyle + + if m.Highlights(src, t) { + selectionStyle = TargetHighlightedStyle + } + if selected { selectionStyle = SelectedTargetStyle selectionDescriptionStyle = SelectedTargetDescriptionStyle |
