package main import ( "flag" "fmt" "os" "path/filepath" "strings" "github.com/charmbracelet/bubbles/textinput" tea "github.com/charmbracelet/bubbletea" "github.com/sahilm/fuzzy" ) const help = `go-sh-manymanuals: TODO TODO Options: -h output help ` // minCharsUntilFilter is the minimum amount of characters that are // required before the filtering logic commences actually filtering. const minCharsUntilFilter = 2 var helpFlag bool type Configuration struct { ManualDir string } func handleCliFlags() { flag.BoolVar(&helpFlag, "h", false, "output help") flag.Parse() } type model struct { filterInput textinput.Model // fuzzy search interface datasheets []string // all datasheets under cwd dataSheetsView []string // filtered view on all datasheets } func initialModel() model { input := textinput.New() input.Focus() var ds []string // TODO(d1): handle error in interface? _ = filepath.Walk(".", func(path string, info os.FileInfo, err error) error { if err != nil { return err } name := info.Name() if strings.HasSuffix(name, "pdf") { ds = append(ds, name) } return nil }) return model{ filterInput: input, datasheets: ds, dataSheetsView: ds, } } func (m model) Init() tea.Cmd { // TODO(d1): implement reading all PDFs in cwd // https://stackoverflow.com/a/67214584 // requires error reporting also return textinput.Blink } func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { var cmd tea.Cmd if m.filterInput.Focused() { var matched []string search := m.filterInput.Value() if len(search) >= minCharsUntilFilter { matches := fuzzy.Find(search, m.datasheets) for _, match := range matches { matched = append(matched, match.Str) } if len(matches) > 0 { m.dataSheetsView = matched } else { m.dataSheetsView = m.datasheets } } else { m.dataSheetsView = m.datasheets } } switch msg := msg.(type) { case tea.KeyMsg: switch msg.String() { case "ctrl+c", "q": return m, tea.Quit } } m.filterInput, cmd = m.filterInput.Update(msg) return m, cmd } func (m model) View() string { body := strings.Builder{} body.WriteString(strings.Join(m.dataSheetsView, "\n") + "\n") body.WriteString(m.filterInput.View() + "\n") return body.String() } func main() { handleCliFlags() if helpFlag { fmt.Printf(help) os.Exit(0) } p := tea.NewProgram(initialModel(), tea.WithAltScreen()) if err := p.Start(); err != nil { fmt.Printf("oops, something went wrong: %v", err) os.Exit(1) } }