tui.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. package tui
  2. import (
  3. "fmt"
  4. "github.com/NimbleMarkets/ntcharts/linechart/streamlinechart"
  5. tea "github.com/charmbracelet/bubbletea"
  6. "github.com/charmbracelet/lipgloss"
  7. )
  8. // Bubbletea model
  9. type Model struct {
  10. width int
  11. Addresses []Address // as defined in internal/tui/types.go
  12. }
  13. func InitialModel(addresses []string) Model {
  14. var model Model
  15. for _, address := range addresses {
  16. var addr Address
  17. addr.max_results = 999
  18. addr.Address = address
  19. model.Addresses = append(model.Addresses, addr)
  20. }
  21. return model
  22. }
  23. func (m Model) Init() tea.Cmd {
  24. return m.Poll
  25. }
  26. func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
  27. switch msg := msg.(type) {
  28. // if case is KeyMsg (keypress)
  29. case tea.WindowSizeMsg:
  30. m.width = msg.Width
  31. for i, address := range m.Addresses {
  32. address.max_results = m.width
  33. m.Addresses[i] = address
  34. }
  35. case tea.KeyMsg:
  36. return m, tea.Quit
  37. case pollMsg:
  38. m.Poll()
  39. }
  40. return m, m.Poll
  41. }
  42. func (m Model) View() string {
  43. var headerStyle = lipgloss.NewStyle().
  44. Bold(true).
  45. Italic(true)
  46. var blockStyle = lipgloss.NewStyle().
  47. Width(m.width).
  48. Align(lipgloss.Center)
  49. output := "Results:\n\n"
  50. for _, address := range m.Addresses {
  51. if len(address.results) == 0 {
  52. output = output + fmt.Sprintf("%s\tloading...\n\n", headerStyle.Render(address.Address))
  53. } else {
  54. output = output + fmt.Sprintf("%s\n\n", blockStyle.Render(headerStyle.Render(address.Address)))
  55. if m.width > 0 {
  56. // Linechart
  57. slc := streamlinechart.New(m.width, 10)
  58. for _, v := range address.results {
  59. slc.Push(v)
  60. }
  61. slc.Draw()
  62. output = output + fmt.Sprintf("%s\n\n", slc.View())
  63. }
  64. }
  65. }
  66. return output
  67. }
  68. // A wrapper for the underlying [tui.Address.Poll] function. For each address in
  69. // [tui.Model.Addresses], run its respective Poll function and update [tui.Model]
  70. //
  71. // NOTE(async): this function fully blocks execution of the current thread.
  72. func (m Model) Poll() tea.Msg {
  73. for i, element := range m.Addresses {
  74. element.Poll()
  75. m.Addresses[i] = element
  76. }
  77. return true
  78. }