package main import ( "os" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/bubbles/viewport" ) type TUIModel struct { State *BrowserState Viewport viewport.Model inited bool } func NewTUIModel(state *BrowserState) *TUIModel { return &TUIModel{State: state} } func (model *TUIModel) Init() tea.Cmd { return nil } func (model *TUIModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case tea.KeyMsg: switch msg.String() { case "ctrl+c", "q": return model, tea.Quit case "g": model.Viewport.GotoTop() return model, nil case "G": model.Viewport.GotoBottom() return model, nil } case tea.WindowSizeMsg: model.inited = true model.Viewport.Width = msg.Width model.Viewport.Height = msg.Height - 1 } var cmd tea.Cmd model.Viewport, cmd = model.Viewport.Update(msg) return model, cmd } func (model *TUIModel) View() string { return model.Viewport.View() } func runTUI(state *BrowserState, args []string) { model := NewTUIModel(state) state.Printer = (*TUIPrinter)(model) if len(args) > 0 { if err := Go(state, args[0]); err != nil { writeError(err.Error()) } } p := tea.NewProgram(model, tea.WithAltScreen()) if _, err := p.Run(); err != nil { writeError(err.Error()) os.Exit(1) } } type TUIPrinter TUIModel func (p *TUIPrinter) PrintModal(state *BrowserState, contents []byte) error { (*TUIModel)(p).Viewport.SetContent(string(contents)) return nil } func (p *TUIPrinter) PrintPage(state *BrowserState, body string) error { (*TUIModel)(p).Viewport.SetContent(body) return nil }