okami.mom/albedo
git clone https://git.nkp.pet/okami.mom/albedo
f7fcae1
main
1package main 2 3import ( 4 tea"charm.land/bubbletea/v2" 5"context" 6"example.com/charm-tui-worked/internal/display" 7"fmt" 8"strings" 9) 10 11type lineMsg string 12type closedMsg struct {} 13 14func waitForLine (ctx context.Context ,ch <- chan string ) tea.Cmd { 15return func () tea.Msg { 16line ,ok := receive (ctx ,ch ) 17if ! ok { 18return closedMsg {} 19 } 20return lineMsg (line ) 21 } 22} 23 24type model struct { 25ctx context.Context 26cancel context.CancelFunc 27events <- chan string 28history history 29width ,height int 30ended bool 31} 32 33func (m * model )rows ()int {return display .BodyRows (m .height ,1 ,2 ) } 34func (m * model )Init () tea.Cmd {return waitForLine (m .ctx ,m .events ) } 35func (m * model )Update (msg tea.Msg ) (tea.Model , tea.Cmd ) { 36switch msg := msg .(type ) { 37case tea.WindowSizeMsg : 38m .width = max (0 ,msg .Width ) 39m .height = max (0 ,msg .Height ) 40m .history .resize (m .rows ()) 41case tea.KeyPressMsg : 42switch msg .String () { 43case "q" ,"ctrl+c" : 44m .cancel () 45return m ,tea .Quit 46case "up" ,"k" : 47m .history .scroll (- 1 ,m .rows ()) 48case "down" ,"j" : 49m .history .scroll (1 ,m .rows ()) 50case "end" : 51m .history .latest (m .rows ()) 52 } 53case lineMsg : 54if m .ended { 55return m ,nil 56 } 57m .history .append (string (msg ),m .rows ()) 58return m ,waitForLine (m .ctx ,m .events )// Exactly one successor listener. 59case closedMsg : 60m .ended = true 61return m ,nil // Never re-arm a closed stream. 62 } 63return m ,nil 64} 65func (m * model )View () tea.View { 66v := tea .NewView ("" ) 67v .AltScreen = true 68if m .width <= 0 || m .height <= 0 { 69return v 70 } 71if m .width < 20 || m .height < 5 { 72v .Content = display .Line ("resize · q quit" ,m .width ) 73return v 74 } 75state := "following" 76if ! m .history .follow { 77state = fmt .Sprintf ("reading · %d new · end follows" ,m .history .unseen ) 78 } 79if m .history .expired { 80state = "old anchor evicted · end follows" 81 } 82if m .ended { 83state += " · stream ended" 84 } 85state += fmt .Sprintf (" · %d evicted" ,m .history .first ) 86lines := m .history .visible (m .rows ()) 87for i := range lines { 88lines [i ]= display .SingleLine (lines [i ]) 89 } 90v .Content = strings .Join ([]string { 91display .Line ("worker events · retain last 32 records" ,m .width ), 92display .FillRows (lines ,m .width ,m .rows ()), 93display .Line (state ,m .width ), 94display .Line ("↑/↓ scroll · end latest · q quit" ,m .width ), 95 },"\n" ) 96return v 97}