buildr/internal/cmd/pager.go
Peter 1261932bdc
All checks were successful
continuous-integration/drone/push Build is passing
refactor: apply golangci-lint findings
2023-06-22 19:16:00 +02:00

129 lines
2.3 KiB
Go

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()
}