1066c0bc7d
Search uses existing parse grammar ?prefix — type `?query #tag` in capture bar to filter entities client-side. Substring match on body+title+description with AND tag filtering. Esc clears search. Absorb via m key on fluid entities — opens source picker showing all other entities, enter merges source into target. Uses existing store.Absorb() backend.
92 lines
1.5 KiB
Go
92 lines
1.5 KiB
Go
package tui
|
||
|
||
import (
|
||
"github.com/charmbracelet/bubbles/textinput"
|
||
tea "github.com/charmbracelet/bubbletea"
|
||
|
||
"github.com/lerko/nib/internal/db"
|
||
"github.com/lerko/nib/internal/parse"
|
||
)
|
||
|
||
type inputResult struct {
|
||
entity *db.Entity
|
||
query bool
|
||
body string
|
||
tags []string
|
||
}
|
||
|
||
type inputModel struct {
|
||
ti textinput.Model
|
||
active bool
|
||
}
|
||
|
||
func newInputModel() inputModel {
|
||
ti := textinput.New()
|
||
ti.Placeholder = "capture a thought…"
|
||
ti.Prompt = inputPromptStyle.Render("› ")
|
||
ti.CharLimit = 500
|
||
return inputModel{ti: ti}
|
||
}
|
||
|
||
func (i *inputModel) focus() {
|
||
i.active = true
|
||
i.ti.Focus()
|
||
}
|
||
|
||
func (i *inputModel) reset() {
|
||
i.active = false
|
||
i.ti.SetValue("")
|
||
i.ti.Blur()
|
||
}
|
||
|
||
func (i inputModel) submit() *inputResult {
|
||
val := i.ti.Value()
|
||
if val == "" {
|
||
return nil
|
||
}
|
||
|
||
parsed, err := parse.Parse(val)
|
||
if err != nil {
|
||
return nil
|
||
}
|
||
|
||
if parsed.Query {
|
||
return &inputResult{
|
||
query: true,
|
||
body: parsed.Body,
|
||
tags: parsed.FilterTags,
|
||
}
|
||
}
|
||
|
||
e := &db.Entity{
|
||
Body: parsed.Body,
|
||
Title: parsed.Title,
|
||
Glyph: db.Glyph(parsed.Glyph),
|
||
Tags: parsed.Tags,
|
||
}
|
||
if parsed.TimeAnchor != nil {
|
||
e.TimeAnchor = parsed.TimeAnchor
|
||
}
|
||
if parsed.CardSuffix != nil {
|
||
ct := db.CardType(*parsed.CardSuffix)
|
||
e.CardType = &ct
|
||
}
|
||
if parsed.Pin {
|
||
e.Pinned = true
|
||
}
|
||
if parsed.Description != nil {
|
||
e.Description = parsed.Description
|
||
}
|
||
|
||
return &inputResult{entity: e}
|
||
}
|
||
|
||
func (i inputModel) updateKey(msg tea.KeyMsg) inputModel {
|
||
i.ti, _ = i.ti.Update(msg)
|
||
return i
|
||
}
|
||
|
||
func (i inputModel) view(width int) string {
|
||
return i.ti.View()
|
||
}
|