enbas/internal/printer/printer.go
Dan Anglin 3d20adfa57
chore: REUSE.toml
- Replace .reuse/dep5 with the new REUSE.toml file.
- Add licensing information to REUSE.toml and remove the licensing
  headers from the source files.
2024-08-01 04:01:38 +01:00

186 lines
3.7 KiB
Go

package printer
import (
"os"
"os/exec"
"regexp"
"strings"
"time"
)
const (
minTerminalWidth = 40
noMediaDescription = "This media attachment has no description."
symbolBullet = "\u2022"
symbolPollMeter = "\u2501"
symbolSuccess = "\u2714"
symbolFailure = "\u2717"
symbolImage = "\uf03e"
symbolLiked = "\uf51f"
symbolNotLiked = "\uf41e"
symbolBookmarked = "\uf47a"
symbolNotBookmarked = "\uf461"
symbolBoosted = "\u2BAD"
dateFormat = "02 Jan 2006"
dateTimeFormat = "02 Jan 2006, 15:04 (MST)"
)
type theme struct {
reset string
boldblue string
boldmagenta string
green string
boldgreen string
grey string
red string
boldred string
yellow string
boldyellow string
}
type Printer struct {
theme theme
noColor bool
lineWrapCharacterLimit int
pager string
statusSeparator string
}
func NewPrinter(
noColor bool,
pager string,
lineWrapCharacterLimit int,
) *Printer {
theme := theme{
reset: "\033[0m",
boldblue: "\033[34;1m",
boldmagenta: "\033[35;1m",
green: "\033[32m",
boldgreen: "\033[32;1m",
grey: "\033[90m",
red: "\033[31m",
boldred: "\033[31;1m",
yellow: "\033[33m",
boldyellow: "\033[33;1m",
}
if lineWrapCharacterLimit < minTerminalWidth {
lineWrapCharacterLimit = minTerminalWidth
}
return &Printer{
theme: theme,
noColor: noColor,
lineWrapCharacterLimit: lineWrapCharacterLimit,
pager: pager,
statusSeparator: strings.Repeat("\u2501", lineWrapCharacterLimit),
}
}
func (p Printer) PrintSuccess(text string) {
success := p.theme.boldgreen + symbolSuccess + p.theme.reset
if p.noColor {
success = symbolSuccess
}
printToStdout(success + " " + text + "\n")
}
func (p Printer) PrintFailure(text string) {
failure := p.theme.boldred + symbolFailure + p.theme.reset
if p.noColor {
failure = symbolFailure
}
printToStderr(failure + " " + text + "\n")
}
func (p Printer) PrintInfo(text string) {
printToStdout(text)
}
func (p Printer) headerFormat(text string) string {
if p.noColor {
return text
}
return p.theme.boldblue + text + p.theme.reset
}
func (p Printer) fieldFormat(text string) string {
if p.noColor {
return text
}
return p.theme.green + text + p.theme.reset
}
func (p Printer) fullDisplayNameFormat(displayName, acct string) string {
// use this pattern to remove all emoji strings
pattern := regexp.MustCompile(`\s:[A-Za-z0-9_]*:`)
var builder strings.Builder
if p.noColor {
builder.WriteString(pattern.ReplaceAllString(displayName, ""))
} else {
builder.WriteString(p.theme.boldmagenta + pattern.ReplaceAllString(displayName, "") + p.theme.reset)
}
builder.WriteString(" (@" + acct + ")")
return builder.String()
}
func (p Printer) formatDate(date time.Time) string {
return date.Local().Format(dateFormat)
}
func (p Printer) formatDateTime(date time.Time) string {
return date.Local().Format(dateTimeFormat)
}
func (p Printer) print(text string) {
if p.pager == "" {
printToStdout(text)
return
}
cmdSplit := strings.Split(p.pager, " ")
pager := new(exec.Cmd)
if len(cmdSplit) == 1 {
pager = exec.Command(cmdSplit[0]) //nolint:gosec
} else {
pager = exec.Command(cmdSplit[0], cmdSplit[1:]...) //nolint:gosec
}
pipe, err := pager.StdinPipe()
if err != nil {
printToStdout(text)
return
}
pager.Stdout = os.Stdout
pager.Stderr = os.Stderr
_ = pager.Start()
defer func() {
_ = pipe.Close()
_ = pager.Wait()
}()
_, _ = pipe.Write([]byte(text))
}
func printToStdout(text string) {
os.Stdout.WriteString(text)
}
func printToStderr(text string) {
os.Stderr.WriteString(text)
}