Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 21 additions & 48 deletions cmd/readis/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/glamour"
"github.com/charmbracelet/lipgloss"
"github.com/muesli/termenv"
)

// appCtx and appCancel manage the application lifecycle context.
Expand All @@ -42,18 +41,12 @@ type model struct {
totalKeys int64

windowHeight, windowWidth int
hasDarkBg bool
}

type totalKeysMsg int64

type refreshTotalKeysMsg struct{}

type fetchContentMsg struct {
content string
keyName string
}

func tickTotalKeys() tea.Cmd {
return tea.Tick(5*time.Second, func(time.Time) tea.Msg {
return refreshTotalKeysMsg{}
Expand Down Expand Up @@ -103,12 +96,11 @@ func (m *model) resizeViews() {
m.viewport = viewport.New(viewportWidth, viewportHeight)
m.viewport.Style = viewportStyle.Width(viewportWidth)
m.viewport.YPosition = headerHeight
m.setViewportContent(appCtx)
}

func newModel(d *data.Data) *model {
m := &model{
hasDarkBg: termenv.HasDarkBackground(),
}
m := &model{}

km := ui.NewListKeyMap()
m.data = d
Expand Down Expand Up @@ -186,13 +178,6 @@ func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m, nil
case refreshTotalKeysMsg:
return m, tea.Batch(m.refreshTotalKeys, tickTotalKeys())
case fetchContentMsg:
if m.keylist.SelectedItem() != nil {
if sel, ok := m.keylist.SelectedItem().(keyItem); ok && sel.Name == msg.keyName {
m.viewport.SetContent(msg.content)
}
}
return m, nil
case tea.KeyMsg:
util.Debug("key pressed: ", msg.String())
switch msg.String() {
Expand All @@ -216,7 +201,7 @@ func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case "up", "down", "left", "?", "home", "end", "pgdown", "pgup":
m.keylist, cmd = m.keylist.Update(msg)
m.resizeViews()
return m, tea.Batch(cmd, m.fetchContent())
return m, tea.Batch(cmd)
case "ctrl+t", "right":
// If on the last page and the current scan is complete,
// then we can scan for the next page of results.
Expand All @@ -226,8 +211,7 @@ func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}
m.keylist, cmd = m.keylist.Update(msg)
m.resizeViews()
cmds = append(cmds, cmd, m.fetchContent())
return m, tea.Batch(cmds...)
return m, tea.Batch(append(cmds, cmd)...)
}
case tea.WindowSizeMsg:
// WindowSizeMsg is sent before the first render and then again every resize.
Expand All @@ -244,7 +228,7 @@ func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {

if m.viewport.VisibleLineCount() == 0 {
// On new searches, update the viewport with the first list item.
cmds = append(cmds, m.fetchContent())
m.setViewportContent(appCtx)
}

// Only pass user input to the textinput; filter terminal response garbage.
Expand Down Expand Up @@ -340,43 +324,32 @@ func (m *model) resultsView() string {
)
}

func (m *model) fetchContent() tea.Cmd {
if m.keylist.SelectedItem() == nil {
return nil
}
selectedKey, ok := m.keylist.SelectedItem().(keyItem)
if !ok {
return nil
}

d := m.data
key := selectedKey.Key
width := m.viewport.Width
hasDarkBg := m.hasDarkBg

return func() tea.Msg {
markdown, err := d.Fetch(appCtx, key)
if err != nil {
return fetchContentMsg{content: err.Error(), keyName: key.Name}
func (m *model) setViewportContent(ctx context.Context) {
if m.keylist.SelectedItem() != nil {
selectedKey, ok := m.keylist.SelectedItem().(keyItem)
if !ok {
return
}

style := "light"
if hasDarkBg {
style = "dark"
markdown, err := m.data.Fetch(ctx, selectedKey.Key)
if err != nil {
m.viewport.SetContent(err.Error())
return
}
renderer, err := glamour.NewTermRenderer(
glamour.WithStandardStyle(style),
glamour.WithWordWrap(width),
glamour.WithAutoStyle(),
glamour.WithWordWrap(m.viewport.Width),
)
if err != nil {
return fetchContentMsg{content: err.Error(), keyName: key.Name}
m.viewport.SetContent(err.Error())
return
}

str, err := renderer.Render(markdown)
if err != nil {
return fetchContentMsg{content: err.Error(), keyName: key.Name}
m.viewport.SetContent(err.Error())
return
}
return fetchContentMsg{content: str, keyName: key.Name}
m.viewport.SetContent(str)
}
}

Expand Down
Binary file modified docs/demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ go 1.26.0
require (
github.com/charmbracelet/bubbles v1.0.0
github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834
github.com/muesli/termenv v0.16.0
github.com/redis/go-redis/v9 v9.17.3
github.com/testcontainers/testcontainers-go/modules/redis v0.40.0
)
Expand Down Expand Up @@ -67,6 +66,7 @@ require (
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/muesli/reflow v0.3.0 // indirect
github.com/muesli/termenv v0.16.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
Expand Down