1package ui
2
3import (
4 "context"
5 "fmt"
6 "log/slog"
7
8 "github.com/gdamore/tcell/v2"
9 "github.com/rivo/tview"
10 "github.com/urfave/cli/v2"
11
12 "git.gabrielgio.me/dict/db"
13)
14
15const (
16 memory = ":memory:"
17)
18
19var UICommand = &cli.Command{
20 Name: "ui",
21 Usage: "interactive dictionary",
22 Flags: []cli.Flag{
23 &cli.StringFlag{
24 Name: "filename",
25 Value: "main.dict",
26 Usage: "Dictionary database location",
27 },
28 },
29 Action: func(cCtx *cli.Context) error {
30 name := cCtx.String("lang")
31 return Run(context.Background(), name)
32 },
33}
34
35func Run(ctx context.Context, name string) error {
36 db, err := db.Open(memory)
37 if err != nil {
38 return err
39 }
40
41 err = db.Restore(ctx, name)
42 if err != nil {
43 return err
44 }
45
46 textView := tview.NewTextView().
47 SetDynamicColors(true).
48 SetRegions(true)
49
50 input := tview.NewInputField().
51 SetChangedFunc(func(v string) {
52 textView.Clear()
53
54 words, err := db.SelectDict(ctx, v, 100)
55 if err != nil {
56 return
57 }
58
59 lastWord := ""
60 for _, w := range words {
61
62 if lastWord == w.Word {
63 fmt.Fprintf(textView, "%s\n", w.Line)
64 } else if lastWord == "" {
65 fmt.Fprintf(textView, "[bold]%s[normal]\n", w.Word)
66 fmt.Fprintf(textView, "%s\n", w.Line)
67 } else {
68 fmt.Fprintf(textView, "\n[bold]%s[normal]\n", w.Word)
69 fmt.Fprintf(textView, "%s\n", w.Line)
70 }
71
72 lastWord = w.Word
73 }
74 }).
75 SetAutocompleteFunc(func(v string) []string {
76 if len(v) == 0 {
77 return []string{}
78 }
79
80 vs, err := db.SelectSpell(ctx, v)
81 if err != nil {
82 slog.Error("Error select spelling", "error", err)
83 return []string{}
84 }
85
86 return vs
87 })
88
89 input.SetDoneFunc(func(key tcell.Key) {
90 textView.Clear()
91 input.SetText("")
92 })
93
94 grid := tview.NewGrid().
95 SetRows(1, 0, 3).
96 AddItem(input, 0, 0, 1, 3, 0, 0, false).
97 AddItem(textView, 1, 0, 1, 3, 0, 0, false)
98
99 err = tview.NewApplication().
100 SetRoot(grid, true).
101 SetFocus(input).
102 Run()
103
104 return err
105}