package ui import ( "context" "fmt" "log/slog" "github.com/gdamore/tcell/v2" "github.com/rivo/tview" "github.com/urfave/cli/v2" "git.gabrielgio.me/dict/db" ) const ( memory = ":memory:" ) var UICommand = &cli.Command{ Name: "ui", Usage: "interactive dictionary", Flags: []cli.Flag{ &cli.StringFlag{ Name: "database", Value: "main.dict", Usage: "Dictionary database location", }, }, Action: func(cCtx *cli.Context) error { name := cCtx.String("database") return Run(context.Background(), name) }, } func Run(ctx context.Context, name string) error { db, err := db.Open(memory) if err != nil { return err } err = db.Restore(ctx, name) if err != nil { return err } textView := tview.NewTextView(). SetDynamicColors(true). SetRegions(true) input := tview.NewInputField(). SetChangedFunc(func(v string) { textView.Clear() words, err := db.SelectDict(ctx, v, 100) if err != nil { return } lastWord := "" for _, w := range words { if lastWord == w.Word { fmt.Fprintf(textView, "%s\n", w.Line) } else if lastWord == "" { fmt.Fprintf(textView, "[bold]%s[normal]\n", w.Word) fmt.Fprintf(textView, "%s\n", w.Line) } else { fmt.Fprintf(textView, "\n[bold]%s[normal]\n", w.Word) fmt.Fprintf(textView, "%s\n", w.Line) } lastWord = w.Word } }). SetAutocompleteFunc(func(v string) []string { if len(v) == 0 { return []string{} } vs, err := db.SelectSpell(ctx, v) if err != nil { slog.Error("Error select spelling", "error", err) return []string{} } return vs }) input.SetDoneFunc(func(key tcell.Key) { if key == tcell.KeyEscape { textView.Clear() input.SetText("") } }) grid := tview.NewGrid(). SetRows(1, 0, 3). AddItem(input, 0, 0, 1, 3, 0, 0, false). AddItem(textView, 1, 0, 1, 3, 0, 0, false) err = tview.NewApplication(). SetRoot(grid, true). SetFocus(input). Run() return err }