summaryrefslogtreecommitdiff
path: root/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'main.go')
-rw-r--r--main.go155
1 files changed, 1 insertions, 154 deletions
diff --git a/main.go b/main.go
index aa716e5..e73b06f 100644
--- a/main.go
+++ b/main.go
@@ -3,176 +3,23 @@
package main
import (
- "database/sql"
- "errors"
- "fmt"
"log"
"net/http"
- "regexp"
- "strings"
"time"
- "github.com/charmbracelet/bubbles/textinput"
- "github.com/charmbracelet/bubbles/viewport"
tea "github.com/charmbracelet/bubbletea"
_ "github.com/mattn/go-sqlite3"
- "github.com/microcosm-cc/bluemonday"
- "github.com/muesli/reflow/wordwrap"
)
const (
rawDictionary = "/home/david/work/french-wiktionary-flashcards/raw-wiktextract-data.jsonl"
- dictionary = "/home/david/work/french-wiktionary-flashcards/raw-wiktextract-data.sqlite3"
+ dictionary = "dictionary.sqlite3"
apiURL = "http://localhost:8765"
deckName = "Français"
modelName = "Basic-830ae"
)
-type model struct {
- wordInput textinput.Model
- err error
- currentWord string
- currentDefinition string
- db *sql.DB
- c *http.Client
- wordAddStatus string
- p bluemonday.Policy
- vp viewport.Model
-}
-
-type (
- errMsg error
- definitionMsg string
- wordAddedMsg string
-)
-
-func initialModel(c *http.Client, db *sql.DB) model {
- ti := textinput.New()
- ti.Placeholder = ""
- ti.Focus()
- ti.CharLimit = 156
- ti.Width = 36
- vp := viewport.New(80, 30)
-
- return model{
- wordInput: ti,
- err: nil,
- db: db,
- c: c,
- wordAddStatus: "",
- p: *bluemonday.StrictPolicy(),
- vp: vp,
- }
-}
-
-func (m model) Init() tea.Cmd {
- return textinput.Blink
-}
-
-func lookupWord(db *sql.DB, word string) tea.Cmd {
- return func() tea.Msg {
- var definition string
- row := db.QueryRow(`select definition from words where word = ? limit 1`, word)
- err := row.Scan(&definition)
- if err != nil {
- if errors.Is(err, sql.ErrNoRows) {
- return definitionMsg("")
- }
- return errMsg(fmt.Errorf("looking up '%s': %s", word, err))
- }
- return definitionMsg(definition)
- }
-}
-
-func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
- var cmd tea.Cmd
-
- var textPickerLongerCmds []tea.Cmd
-
- switch msg := msg.(type) {
- case definitionMsg:
- m.currentDefinition = string(msg)
- m.err = nil
- m.vp.SetContent(formatDefinitionForDisplay(m.p, m.currentDefinition, m.vp.Width))
- return m, nil
- case wordAddedMsg:
- m.wordAddStatus = fmt.Sprintf("✅ Added '%s' to Anki", string(msg))
- m.currentWord = ""
- m.currentDefinition = ""
- m.wordInput.SetValue("")
- m.vp.SetContent("")
- m.err = nil
- case tea.WindowSizeMsg:
- // headerHeight is the height of everything above the definition window.
- headerHeight := 11
- m.vp.Width = msg.Width
- m.vp.Height = msg.Height - headerHeight
- m.vp.SetContent(formatDefinitionForDisplay(m.p, m.currentDefinition, m.vp.Width))
- case tea.KeyMsg:
- switch msg.Type {
- case tea.KeyCtrlC:
- return m, tea.Quit
- case tea.KeyEsc:
- m.currentWord = ""
- m.currentDefinition = ""
- m.wordInput.SetValue("")
- m.vp.SetContent("")
- case tea.KeyEnter:
- return m, addCard(m.c, m.currentWord, m.currentDefinition)
- }
-
- case errMsg:
- m.err = msg
- return m, nil
- }
-
- if m.wordInput.Value() != m.currentWord {
- m.currentWord = m.wordInput.Value()
- textPickerLongerCmds = append(textPickerLongerCmds, lookupWord(m.db, m.currentWord))
- }
-
- var vpCmd tea.Cmd
- m.vp, vpCmd = m.vp.Update(msg)
- textPickerLongerCmds = append(textPickerLongerCmds, vpCmd)
-
- m.wordInput, cmd = m.wordInput.Update(msg)
- textPickerLongerCmds = append(textPickerLongerCmds, cmd)
- return m, tea.Batch(textPickerLongerCmds...)
-}
-
-var whitespaceTrimmerRe = regexp.MustCompile(`^[ \t]*$`)
-
-func (m model) View() string {
- return fmt.Sprintf(
- "\x1b[1;30;42mLook up a word:\x1b[0m\n\n%s\n\n\x1b[1;30;42mStatus:\x1b[0m %s\n\n%s\n\n%s\n%s",
- m.wordInput.View(),
- formatStatus(m.err, m.wordAddStatus),
- "(ctrl-c to quit, esc to clear, enter to add to Anki)",
- "\x1b[1;30;42mCurrent definition:\x1b[0m\n",
- m.vp.View(),
- ) + "\n"
-}
-
-func formatDefinitionForDisplay(policy bluemonday.Policy, definition string, maxWidth int) string {
- str := strings.ReplaceAll(definition, "<li class=sense>", "<li class=sense>- ")
- str = strings.ReplaceAll(str, "\t<ul><li><i>", "\n\t<ul><li><i>\x1b[3;39;49m")
- str = strings.ReplaceAll(str, "</i></li></ul></li>", "</i></li></ul></li>\x1b[0m")
- str = policy.Sanitize(str)
- str = strings.ReplaceAll(str, "\t- ", "\x1b[0;33;49m•\x1b[0m ")
-
- width := min(maxWidth, 80)
-
- return wordwrap.String(str, width)
-}
-
-func formatStatus(lastError error, lastSuccess string) string {
- if lastError == nil {
- return lastSuccess
- }
- return fmt.Sprintf("\x1b[0;31;49m%s\x1b[0m", lastError.Error())
-}
-
func main() {
db, err := setupDatabase()
if err != nil {