package main import ( "bufio" "bytes" "context" "fmt" "io" "log/slog" "math" "os" "strings" "github.com/rivo/tview" ) const ( memory = ":memory:" ) func run(ctx context.Context, name string) error { db, err := Open(memory) if err != nil { return err } err = db.Restore(ctx, name) if err != nil { return err } list := tview.NewList() input := tview.NewInputField(). SetLabel("S:"). SetChangedFunc(func(v string) { list.Clear() words, err := db.SelectDict(ctx, v, 100) if err != nil { return } for _, w := range words { list.AddItem(w.Word, w.Line, 0, nil) } }). 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 }) grid := tview.NewGrid(). SetRows(1, 0, 3). AddItem(input, 0, 0, 1, 3, 0, 0, false). AddItem(list, 1, 0, 1, 3, 0, 0, false) err = tview.NewApplication(). SetRoot(grid, true). SetFocus(input). Run() return err } func importDict(ctx context.Context, name string) error { db, err := Open(memory) if err != nil { return err } err = db.Migrate(ctx) if err != nil { return err } file, err := os.Open("dict.txt") if err != nil { return err } defer file.Close() count := 0 total, err := LineCounter(file) if err != nil { return err } _, err = file.Seek(0, 0) if err != nil { return err } scanner := bufio.NewScanner(file) for scanner.Scan() { if strings.HasPrefix(scanner.Text(), "#") || scanner.Text() == "" { continue } if err := db.InsertLine(ctx, scanner.Text()); err != nil { return err } count++ if (count % 1234) == 0 { fmt.Print("\033[G\033[K") // move the cursor left and clear the line per := math.Ceil((float64(count) / float64(total)) * 100.0) fmt.Printf("%d/%d (%.0f%%)", count, total, per) } } fmt.Printf("Consolidating") err = db.Consolidade(ctx) if err != nil { return err } err = db.Backup(ctx, name) if err != nil { return err } return nil } func LineCounter(r io.Reader) (int, error) { var count int const lineBreak = '\n' buf := make([]byte, bufio.MaxScanTokenSize) for { bufferSize, err := r.Read(buf) if err != nil && err != io.EOF { return 0, err } var buffPosition int for { i := bytes.IndexByte(buf[buffPosition:], lineBreak) if i == -1 || bufferSize == buffPosition { break } buffPosition += i + 1 count++ } if err == io.EOF { break } } return count, nil }