diff options
| author | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-07-24 13:07:37 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-07-24 13:07:37 +0200 |
| commit | a675a983424f1f8d103fc12d55ef4f7129a92d62 (patch) | |
| tree | b9483bf09f03cb9047a548289556c73a9343bbb0 /internal/tui | |
| parent | 55a5c793d04b55892fcddfc753d8526bd5748f03 (diff) | |
| download | lectio-a675a983424f1f8d103fc12d55ef4f7129a92d62.tar.gz lectio-a675a983424f1f8d103fc12d55ef4f7129a92d62.zip | |
qol: tui jump-to-date (d) + lectio --citation/--week + hide bt for traditional web; v0.10.0
Diffstat (limited to 'internal/tui')
| -rw-r--r-- | internal/tui/tui.go | 55 | ||||
| -rw-r--r-- | internal/tui/tui_test.go | 40 |
2 files changed, 94 insertions, 1 deletions
diff --git a/internal/tui/tui.go b/internal/tui/tui.go index c58db6d..5f7fb52 100644 --- a/internal/tui/tui.go +++ b/internal/tui/tui.go @@ -32,6 +32,9 @@ type Model struct { height int loading bool err error + + jumping bool // date-entry ("d") mode is active + jumpBuf string // the date being typed in jump mode } // readingsMsg carries a successful fetch's sections and DayInfo back to @@ -179,6 +182,9 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m, nil case tea.KeyMsg: + if m.jumping { + return m.updateJump(msg) + } switch msg.String() { case "q", "ctrl+c": return m, tea.Quit @@ -200,6 +206,10 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.loading = true m.err = nil return m, m.fetchCmd(true) + case "d": + m.jumping = true + m.jumpBuf = "" + return m, nil case "j", "down": m.scroll = m.scrollTo(m.scroll + 1) return m, nil @@ -223,6 +233,45 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m, nil } +// updateJump handles keys while the "d" date-jump prompt is active: digits and +// "-" build the buffer, Enter parses YYYY-MM-DD and navigates (invalid input +// just cancels), Esc cancels, Backspace edits, Ctrl+C quits. Any other key is +// ignored so the prompt stays modal. +func (m Model) updateJump(msg tea.KeyMsg) (tea.Model, tea.Cmd) { + switch msg.Type { + case tea.KeyCtrlC: + return m, tea.Quit + case tea.KeyEsc: + m.jumping = false + m.jumpBuf = "" + return m, nil + case tea.KeyEnter: + buf := m.jumpBuf + m.jumping = false + m.jumpBuf = "" + if t, err := time.Parse("2006-01-02", buf); err == nil { + m.date = t.Format("2006-01-02") + m.loading = true + m.err = nil + return m, m.fetchCmd(false) + } + return m, nil + case tea.KeyBackspace: + if r := []rune(m.jumpBuf); len(r) > 0 { + m.jumpBuf = string(r[:len(r)-1]) + } + return m, nil + case tea.KeyRunes: + for _, c := range msg.Runes { + if (c >= '0' && c <= '9') || c == '-' { + m.jumpBuf += string(c) + } + } + return m, nil + } + return m, nil +} + // headerLines is how many lines the top header block renders as: 1 (just // the "lectio DATE [version]" bar) or 2 when a day-info line (the // celebration name, optionally with its temporal Season) is shown beneath @@ -295,7 +344,11 @@ func (m Model) View() string { if line := m.dayInfoLine(); line != "" { header += "\n" + line } - footer := footerStyle.Width(w).Render(i18n.Get(m.cfg.UILanguage).FooterKeys) + footerText := i18n.Get(m.cfg.UILanguage).FooterKeys + if m.jumping { + footerText = i18n.Get(m.cfg.UILanguage).JumpPrompt + ": " + m.jumpBuf + } + footer := footerStyle.Width(w).Render(footerText) bodyLines := m.bodyLines(innerW) diff --git a/internal/tui/tui_test.go b/internal/tui/tui_test.go index 330259d..f99c4ac 100644 --- a/internal/tui/tui_test.go +++ b/internal/tui/tui_test.go @@ -5,6 +5,8 @@ import ( "strings" "testing" + tea "github.com/charmbracelet/bubbletea" + "github.com/lukaszkasprzak/lectio/internal/config" "github.com/lukaszkasprzak/lectio/internal/liturgy" ) @@ -161,3 +163,41 @@ func TestFooterKeysLocalised(t *testing.T) { t.Errorf("pl View() footer missing %q: %q", "q wyjście", out) } } + +func TestJumpToDate(t *testing.T) { + send := func(m Model, s string) Model { + for _, r := range s { + nm, _ := m.Update(tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune{r}}) + m = nm.(Model) + } + return m + } + + m := New(config.Default(), "2026-07-22", "wuj") + m = send(m, "d") + if !m.jumping { + t.Fatal("'d' did not enter jump mode") + } + m = send(m, "2026-01-02") + if m.jumpBuf != "2026-01-02" { + t.Fatalf("jumpBuf = %q", m.jumpBuf) + } + nm, _ := m.Update(tea.KeyMsg{Type: tea.KeyEnter}) + m = nm.(Model) + if m.jumping { + t.Error("still in jump mode after Enter") + } + if m.date != "2026-01-02" { + t.Errorf("date = %q, want 2026-01-02", m.date) + } + + // Esc cancels without changing the date. + m2 := New(config.Default(), "2026-07-22", "wuj") + m2 = send(m2, "d") + m2 = send(m2, "2099") + nm2, _ := m2.Update(tea.KeyMsg{Type: tea.KeyEsc}) + m2 = nm2.(Model) + if m2.jumping || m2.jumpBuf != "" || m2.date != "2026-07-22" { + t.Errorf("esc did not cancel cleanly: jumping=%v buf=%q date=%q", m2.jumping, m2.jumpBuf, m2.date) + } +} |
