package cmd import ( "bytes" "context" "io" "os" "os/exec" "strings" "code.icb4dc0.de/buildr/buildr/internal/tui" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/glamour" "github.com/muesli/termenv" ) var ( _ Pager = (*TUIPager)(nil) _ Pager = (*CommandPager)(nil) ) func NewTUIPager(title string) (*TUIPager, error) { renderer, err := glamour.NewTermRenderer( glamour.WithStyles(glamour.DraculaStyleConfig), glamour.WithEmoji(), glamour.WithAutoStyle(), ) if err != nil { return nil, err } return &TUIPager{ title: title, renderer: renderer, }, nil } type TUIPager struct { renderer *glamour.TermRenderer title string } func (t *TUIPager) Write(p []byte) (n int, err error) { return t.renderer.Write(p) } func (t *TUIPager) Display() error { if err := t.renderer.Close(); err != nil { return err } builder := new(strings.Builder) _, _ = io.Copy(builder, t.renderer) tuiProgram := tea.NewProgram( tui.NewPager(t.title, builder.String()), tea.WithAltScreen(), ) _, err := tuiProgram.Run() return err } func NewCmdPager(ctx context.Context, pagerCmd string, colorize bool) (p *CommandPager, err error) { var ( renderer *glamour.TermRenderer buf *bytes.Buffer ) if colorize { renderer, err = glamour.NewTermRenderer( glamour.WithStyles(glamour.DraculaStyleConfig), glamour.WithColorProfile(termenv.TrueColor), glamour.WithEmoji(), glamour.WithAutoStyle(), ) if err != nil { return nil, err } } else { buf = bytes.NewBuffer(nil) } split := strings.Split(pagerCmd, " ") var ( executable = split[0] args []string ) if len(split) > 1 { args = split[1:] } return &CommandPager{ cmd: exec.CommandContext(ctx, executable, args...), renderer: renderer, buf: buf, }, nil } type CommandPager struct { cmd *exec.Cmd renderer *glamour.TermRenderer buf *bytes.Buffer } func (c *CommandPager) Write(p []byte) (n int, err error) { if c.renderer != nil { return c.renderer.Write(p) } return c.buf.Write(p) } func (c *CommandPager) Display() error { if c.renderer != nil { if err := c.renderer.Close(); err != nil { return err } c.cmd.Stdin = c.renderer } else { c.cmd.Stdin = c.buf } c.cmd.Stdout = os.Stdout c.cmd.Stderr = os.Stderr return c.cmd.Run() }