photoprism-client-go/vendor/github.com/kris-nova/lolgopher/writer.go

135 lines
2.8 KiB
Go

package lol
import (
"fmt"
"io"
"os"
"strings"
isatty "github.com/mattn/go-isatty"
)
const (
DEFAULT_SPREAD = float64(3.0)
DEFAULT_FREQ = float64(0.1)
DEFAULT_ORIGIN = 0
)
const (
ColorModeTrueColor = iota
ColorMode256
ColorMode0
)
// LolWriter writes a little lol-er.
type Writer struct {
Output io.Writer
ColorMode int
Freq float64
Spread float64
lineIdx int
Origin int
}
var noColor = os.Getenv("TERM") == "dumb" || (!isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd()))
// writeRaw will write a lol'd s to the underlying writer. It does no line
// detection.
func (w *Writer) writeRaw(s string) (int, error) {
c, err := w.getColorer()
if err != nil {
return -1, err
}
nWritten := 0
for _, r := range s {
c.rainbow(w.Freq, float64(w.Origin)+float64(w.lineIdx)/w.Spread)
_, err := w.Output.Write(c.format())
if err != nil {
return nWritten, err
}
n, err := w.Output.Write([]byte(string(r)))
if err != nil {
return nWritten, err
}
_, err = w.Output.Write(c.reset())
if err != nil {
return nWritten, err
}
nWritten += n
w.lineIdx++
}
return nWritten, nil
}
// getColorer will attempt to map the defined color mode, to a colorer{}
func (w *Writer) getColorer() (colorer, error) {
switch w.ColorMode {
case ColorModeTrueColor:
return newTruecolorColorer(), nil
case ColorMode256:
return New256Colorer(), nil
case ColorMode0:
return New0Colorer(), nil
default:
return nil, fmt.Errorf("Invalid colorer: [%d]", w.ColorMode)
}
}
// Write will write a byte slice to the Writer
func (w *Writer) Write(p []byte) (int, error) {
nWritten := 0
ss := strings.Split(string(p), "\n")
for i, s := range ss {
// TODO: strip out pre-existing ANSI codes and expand tabs. Would be
// great to expand tabs in a context aware way (line linux expand
// command).
n, err := w.writeRaw(s)
if err != nil {
return nWritten, err
}
nWritten += n
// Increment the Origin (line count) for each newline. There is a
// newline for every item in this array except the last one.
if i != len(ss)-1 {
n, err := w.Output.Write([]byte("\n"))
if err != nil {
return nWritten, err
}
nWritten += n
w.Origin++
w.lineIdx = 0
}
}
return nWritten, nil
}
// NewLolWriter will return a new io.Writer with a default ColorMode of 256
func NewLolWriter() io.Writer {
colorMode := ColorMode256
if noColor {
colorMode = ColorMode0
}
return &Writer{
Output: stdout,
ColorMode: colorMode,
Freq: DEFAULT_FREQ,
Spread: DEFAULT_SPREAD,
Origin: DEFAULT_ORIGIN,
}
}
// NewTruecolorLolWriter will return a new io.Writer with a default ColorMode of truecolor
func NewTruecolorLolWriter() io.Writer {
colorMode := ColorModeTrueColor
if noColor {
colorMode = ColorMode0
}
return &Writer{
Output: stdout,
ColorMode: colorMode,
}
}