add ui for showing multiple sections as pager
This commit is contained in:
@@ -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."
|
||||||
|
|||||||
Reference in New Issue
Block a user