// Package filterbar is the single-line input shown above the request
// list. It delegates the actual expression parsing to internal/filter.
//
// mercemay.top/src/httptap/
package filterbar
import (
"strings"
"github.com/charmbracelet/bubbles/textinput"
tea "github.com/charmbracelet/bubbletea"
"mercemay.top/httptap/internal/tui/theme"
)
// Model is a thin wrapper around bubbles/textinput.
type Model struct {
pal theme.Palette
input textinput.Model
width int
}
// New returns a model with sensible defaults.
func New(pal theme.Palette) Model {
ti := textinput.New()
ti.Prompt = "/ "
ti.Placeholder = "method=GET and host=example.com"
ti.CharLimit = 512
return Model{pal: pal, input: ti}
}
// SetWidth is called by App.relayout.
func (m *Model) SetWidth(w int) {
m.width = w
m.input.Width = w - 2
}
// Update handles editing keys. The bubbletea textinput does the heavy
// lifting; we intercept Enter to blur and Esc to clear.
func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
if k, ok := msg.(tea.KeyMsg); ok {
switch k.String() {
case "enter":
m.input.Blur()
return m, nil
case "esc":
m.input.Blur()
m.input.SetValue("")
return m, nil
}
}
var cmd tea.Cmd
m.input, cmd = m.input.Update(msg)
return m, cmd
}
// Focus marks the filter bar active.
func (m *Model) Focus() tea.Cmd { return m.input.Focus() }
// Blur marks the filter bar inactive.
func (m *Model) Blur() { m.input.Blur() }
// Expr returns the currently entered filter expression.
func (m Model) Expr() string { return strings.TrimSpace(m.input.Value()) }
// View paints the bar.
func (m Model) View() string {
v := m.input.View()
if m.width <= 0 {
return m.pal.FilterBar.Render(v)
}
if lw := len(v); lw < m.width {
v += strings.Repeat(" ", m.width-lw)
}
return m.pal.FilterBar.Render(v)
}
// Focused reports whether the input has focus (i.e. user typing).
func (m Model) Focused() bool { return m.input.Focused() }