add ui for showing multiple sections as pager

This commit is contained in:
2026-01-04 06:07:59 +00:00
parent dcf3b72215
commit bc646f1aba
+40 -10
View File
@@ -7,6 +7,7 @@ repetition in mend
package main package main
import ( import (
"fmt"
"os" "os"
"regexp" "regexp"
"strings" "strings"
@@ -15,6 +16,7 @@ import (
"github.com/charmbracelet/bubbles/viewport" "github.com/charmbracelet/bubbles/viewport"
tea "github.com/charmbracelet/bubbletea" tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/glamour" "github.com/charmbracelet/glamour"
"github.com/charmbracelet/lipgloss"
"github.com/yuin/goldmark" "github.com/yuin/goldmark"
"github.com/yuin/goldmark/ast" "github.com/yuin/goldmark/ast"
"github.com/yuin/goldmark/text" "github.com/yuin/goldmark/text"
@@ -36,9 +38,10 @@ const (
type NoteView struct { type NoteView struct {
// the actual content // the actual content
path string path string
rawContent string // full content for editing rawContent string // full content for editing
sections []Section sections []Section
currentSectionIndex int
// display layer // display layer
err error err error
loading bool loading bool
@@ -89,7 +92,7 @@ func (m *NoteView) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) { switch msg := msg.(type) {
case tea.WindowSizeMsg: case tea.WindowSizeMsg:
m.vp.Width = msg.Width m.vp.Width = msg.Width
m.vp.Height = msg.Height m.vp.Height = msg.Height - 1
m.textarea.SetWidth(msg.Width) m.textarea.SetWidth(msg.Width)
m.textarea.SetHeight(msg.Height) m.textarea.SetHeight(msg.Height)
return m, nil return m, nil
@@ -132,6 +135,20 @@ func (m *NoteView) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case "pgdown": case "pgdown":
m.vp.PageDown() m.vp.PageDown()
return m, nil return m, nil
case "left", "a":
if m.currentSectionIndex > 0 {
m.currentSectionIndex--
m.vp.SetContent(m.renderNote())
m.vp.GotoTop()
}
return m, nil
case "right", "d":
if m.currentSectionIndex < len(m.sections)-1 {
m.currentSectionIndex++
m.vp.SetContent(m.renderNote())
m.vp.GotoTop()
}
return m, nil
} }
var cmd tea.Cmd var cmd tea.Cmd
m.vp, cmd = m.vp.Update(msg) m.vp, cmd = m.vp.Update(msg)
@@ -144,6 +161,7 @@ func (m *NoteView) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.path = msg.path m.path = msg.path
m.isEditing = false m.isEditing = false
m.loading = true m.loading = true
m.currentSectionIndex = 0
return m, fetchContent(msg.path) return m, fetchContent(msg.path)
case loadedNote: case loadedNote:
@@ -151,6 +169,7 @@ func (m *NoteView) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.rawContent = msg.rawContent m.rawContent = msg.rawContent
m.sections = msg.sections m.sections = msg.sections
m.err = msg.err m.err = msg.err
m.currentSectionIndex = 0
m.viewState = StateTitleOnly m.viewState = StateTitleOnly
m.vp.SetContent(m.renderNote()) m.vp.SetContent(m.renderNote())
@@ -171,6 +190,9 @@ func (m NoteView) View() string {
if m.loading { if m.loading {
return "loading..." return "loading..."
} }
if m.path == "" {
return ""
}
if m.err != nil { if m.err != nil {
return "Error: " + m.err.Error() return "Error: " + m.err.Error()
@@ -180,7 +202,17 @@ func (m NoteView) View() string {
return m.textarea.View() return m.textarea.View()
} }
return m.vp.View() page := m.currentSectionIndex + 1
total := len(m.sections)
var footer string
if total == 0 {
footer = "No sections"
} else {
footer = fmt.Sprintf("%d/%d", page, total)
}
footer = lipgloss.NewStyle().Width(m.vp.Width).Align(lipgloss.Right).Render(footer)
return m.vp.View() + "\n" + footer
} }
func fetchContent(path string) tea.Cmd { func fetchContent(path string) tea.Cmd {
@@ -283,8 +315,8 @@ func extractHints(content string) []string {
func (m NoteView) renderNote() string { func (m NoteView) renderNote() string {
var titleText, contentText string var titleText, contentText string
if len(m.sections) > 0 { if len(m.sections) > 0 {
titleText = m.sections[0].Title titleText = m.sections[m.currentSectionIndex].Title
contentText = m.sections[0].Content contentText = m.sections[m.currentSectionIndex].Content
} else { } else {
contentText = m.rawContent contentText = m.rawContent
} }
@@ -302,9 +334,7 @@ func (m NoteView) renderNote() string {
body, err2 = m.mdRenderer.Render(contentText) body, err2 = m.mdRenderer.Render(contentText)
case StateHints: case StateHints:
var currentHints []string var currentHints []string
if len(m.sections) > 0 { currentHints = m.sections[m.currentSectionIndex].Hints
currentHints = m.sections[0].Hints
}
if len(currentHints) == 0 { if len(currentHints) == 0 {
body = "No hints available." body = "No hints available."