177 lines
5.1 KiB
Go
177 lines
5.1 KiB
Go
package pterm
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/gookit/color"
|
|
|
|
"github.com/pterm/pterm/internal"
|
|
)
|
|
|
|
// RGB color model is an additive color model in which red, green, and blue light are added together in various ways to reproduce a broad array of colors.
|
|
// The name of the model comes from the initials of the three additive primary colors, red, green, and blue.
|
|
// https://en.wikipedia.org/wiki/RGB_color_model
|
|
type RGB struct {
|
|
R uint8
|
|
G uint8
|
|
B uint8
|
|
}
|
|
|
|
// GetValues returns the RGB values separately.
|
|
func (p RGB) GetValues() (r, g, b uint8) {
|
|
return p.R, p.G, p.B
|
|
}
|
|
|
|
// NewRGB returns a new RGB.
|
|
func NewRGB(r, g, b uint8) RGB {
|
|
return RGB{R: r, G: g, B: b}
|
|
}
|
|
|
|
// NewRGBFromHEX converts a HEX and returns a new RGB.
|
|
func NewRGBFromHEX(hex string) (RGB, error) {
|
|
hex = strings.ToLower(hex)
|
|
hex = strings.ReplaceAll(hex, "#", "")
|
|
hex = strings.ReplaceAll(hex, "0x", "")
|
|
|
|
if len(hex) == 3 {
|
|
hex = string([]byte{hex[0], hex[0], hex[1], hex[1], hex[2], hex[2]})
|
|
}
|
|
if len(hex) != 6 {
|
|
return RGB{}, ErrHexCodeIsInvalid
|
|
}
|
|
|
|
i64, err := strconv.ParseInt(hex, 16, 32)
|
|
if err != nil {
|
|
return RGB{}, err
|
|
}
|
|
c := int(i64)
|
|
|
|
return RGB{
|
|
R: uint8(c >> 16),
|
|
G: uint8((c & 0x00FF00) >> 8),
|
|
B: uint8(c & 0x0000FF),
|
|
}, nil
|
|
}
|
|
|
|
// Fade fades one RGB value (over other RGB values) to another RGB value, by giving the function a minimum, maximum and current value.
|
|
func (p RGB) Fade(min, max, current float32, end ...RGB) RGB {
|
|
if min < 0 {
|
|
max -= min
|
|
current -= min
|
|
min = 0
|
|
}
|
|
if len(end) == 1 {
|
|
return RGB{
|
|
R: uint8(internal.MapRangeToRange(min, max, float32(p.R), float32(end[0].R), current)),
|
|
G: uint8(internal.MapRangeToRange(min, max, float32(p.G), float32(end[0].G), current)),
|
|
B: uint8(internal.MapRangeToRange(min, max, float32(p.B), float32(end[0].B), current)),
|
|
}
|
|
} else if len(end) > 1 {
|
|
f := (max - min) / float32(len(end))
|
|
tempCurrent := current
|
|
if f > current {
|
|
return p.Fade(min, f, current, end[0])
|
|
} else {
|
|
for i := 0; i < len(end)-1; i++ {
|
|
tempCurrent -= f
|
|
if f > tempCurrent {
|
|
return end[i].Fade(min, min+f, tempCurrent, end[i+1])
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return p
|
|
}
|
|
|
|
// Sprint formats using the default formats for its operands and returns the resulting string.
|
|
// Spaces are added between operands when neither is a string.
|
|
func (p RGB) Sprint(a ...interface{}) string {
|
|
return color.RGB(p.R, p.G, p.B).Sprint(a...)
|
|
}
|
|
|
|
// Sprintln formats using the default formats for its operands and returns the resulting string.
|
|
// Spaces are always added between operands and a newline is appended.
|
|
func (p RGB) Sprintln(a ...interface{}) string {
|
|
return p.Sprint(Sprintln(a...))
|
|
}
|
|
|
|
// Sprintf formats according to a format specifier and returns the resulting string.
|
|
func (p RGB) Sprintf(format string, a ...interface{}) string {
|
|
return p.Sprint(Sprintf(format, a...))
|
|
}
|
|
|
|
// Sprintfln formats according to a format specifier and returns the resulting string.
|
|
// Spaces are always added between operands and a newline is appended.
|
|
func (p RGB) Sprintfln(format string, a ...interface{}) string {
|
|
return p.Sprintf(format, a...) + "\n"
|
|
}
|
|
|
|
// Print formats using the default formats for its operands and writes to standard output.
|
|
// Spaces are added between operands when neither is a string.
|
|
// It returns the number of bytes written and any write error encountered.
|
|
func (p RGB) Print(a ...interface{}) *TextPrinter {
|
|
Print(p.Sprint(a...))
|
|
tp := TextPrinter(p)
|
|
return &tp
|
|
}
|
|
|
|
// Println formats using the default formats for its operands and writes to standard output.
|
|
// Spaces are always added between operands and a newline is appended.
|
|
// It returns the number of bytes written and any write error encountered.
|
|
func (p RGB) Println(a ...interface{}) *TextPrinter {
|
|
Print(p.Sprintln(a...))
|
|
tp := TextPrinter(p)
|
|
return &tp
|
|
}
|
|
|
|
// Printf formats according to a format specifier and writes to standard output.
|
|
// It returns the number of bytes written and any write error encountered.
|
|
func (p RGB) Printf(format string, a ...interface{}) *TextPrinter {
|
|
Print(p.Sprintf(format, a...))
|
|
tp := TextPrinter(p)
|
|
return &tp
|
|
}
|
|
|
|
// Printfln formats according to a format specifier and writes to standard output.
|
|
// Spaces are always added between operands and a newline is appended.
|
|
// It returns the number of bytes written and any write error encountered.
|
|
func (p RGB) Printfln(format string, a ...interface{}) *TextPrinter {
|
|
Print(p.Sprintfln(format, a...))
|
|
tp := TextPrinter(p)
|
|
return &tp
|
|
}
|
|
|
|
// PrintOnError prints every error which is not nil.
|
|
// If every error is nil, nothing will be printed.
|
|
// This can be used for simple error checking.
|
|
func (p RGB) PrintOnError(a ...interface{}) *TextPrinter {
|
|
for _, arg := range a {
|
|
if err, ok := arg.(error); ok {
|
|
if err != nil {
|
|
p.Println(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
tp := TextPrinter(p)
|
|
return &tp
|
|
}
|
|
|
|
// PrintOnErrorf wraps every error which is not nil and prints it.
|
|
// If every error is nil, nothing will be printed.
|
|
// This can be used for simple error checking.
|
|
func (p RGB) PrintOnErrorf(format string, a ...interface{}) *TextPrinter {
|
|
for _, arg := range a {
|
|
if err, ok := arg.(error); ok {
|
|
if err != nil {
|
|
p.Println(fmt.Errorf(format, err))
|
|
}
|
|
}
|
|
}
|
|
|
|
tp := TextPrinter(p)
|
|
return &tp
|
|
}
|