mirror of
https://github.com/walles/moar.git
synced 2024-12-02 09:15:46 +03:00
44a064c024
Fixes #37 and fixes #34.
151 lines
3.6 KiB
Go
151 lines
3.6 KiB
Go
package twin
|
|
|
|
import "fmt"
|
|
|
|
// Create using NewColor16(), NewColor256 or NewColor24Bit(), or use
|
|
// ColorDefault.
|
|
type Color uint32
|
|
type ColorType uint8
|
|
|
|
const (
|
|
// Default foreground / background color
|
|
colorTypeDefault ColorType = iota
|
|
|
|
// https://en.wikipedia.org/wiki/ANSI_escape_code#3-bit_and_4-bit
|
|
colorType16
|
|
|
|
// https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit
|
|
colorType256
|
|
|
|
// RGB: https://en.wikipedia.org/wiki/ANSI_escape_code#24-bit
|
|
colorType24bit
|
|
)
|
|
|
|
// Reset to default foreground / background color
|
|
var ColorDefault = newColor(colorTypeDefault, 0)
|
|
|
|
// From: https://en.wikipedia.org/wiki/ANSI_escape_code#3-bit_and_4-bit
|
|
var colorNames16 = map[int]string{
|
|
0: "0 black",
|
|
1: "1 red",
|
|
2: "2 green",
|
|
3: "3 yellow (orange)",
|
|
4: "4 blue",
|
|
5: "5 magenta",
|
|
6: "6 cyan",
|
|
7: "7 white (light gray)",
|
|
8: "8 bright black (dark gray)",
|
|
9: "9 bright red",
|
|
10: "10 bright green",
|
|
11: "11 bright yellow",
|
|
12: "12 bright blue",
|
|
13: "13 bright magenta",
|
|
14: "14 bright cyan",
|
|
15: "15 bright white",
|
|
}
|
|
|
|
func newColor(colorType ColorType, value uint32) Color {
|
|
return Color(value | (uint32(colorType) << 24))
|
|
}
|
|
|
|
// Four bit colors as defined here:
|
|
// https://en.wikipedia.org/wiki/ANSI_escape_code#3-bit_and_4-bit
|
|
func NewColor16(colorNumber0to15 int) Color {
|
|
return newColor(colorType16, uint32(colorNumber0to15))
|
|
}
|
|
|
|
func NewColor256(colorNumber uint8) Color {
|
|
return newColor(colorType256, uint32(colorNumber))
|
|
}
|
|
|
|
func NewColor24Bit(red uint8, green uint8, blue uint8) Color {
|
|
return newColor(colorType24bit, (uint32(red)<<16)+(uint32(green)<<8)+(uint32(blue)<<0))
|
|
}
|
|
|
|
func NewColorHex(rgb uint32) Color {
|
|
return newColor(colorType24bit, rgb)
|
|
}
|
|
|
|
func (color Color) colorType() ColorType {
|
|
return ColorType(color >> 24)
|
|
}
|
|
|
|
func (color Color) colorValue() uint32 {
|
|
return uint32(color & 0xff_ff_ff)
|
|
}
|
|
|
|
// Render color into an ANSI string.
|
|
//
|
|
// Ref: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters
|
|
func (color Color) ansiString(foreground bool) string {
|
|
value := color.colorValue()
|
|
|
|
fgBgMarker := "3"
|
|
if !foreground {
|
|
fgBgMarker = "4"
|
|
}
|
|
|
|
if color.colorType() == colorType16 {
|
|
if value < 8 {
|
|
return fmt.Sprint("\x1b[", fgBgMarker, value, "m")
|
|
} else if value <= 15 {
|
|
fgBgMarker := "9"
|
|
if !foreground {
|
|
fgBgMarker = "10"
|
|
}
|
|
return fmt.Sprint("\x1b[", fgBgMarker, value-8, "m")
|
|
}
|
|
}
|
|
|
|
if color.colorType() == colorType256 {
|
|
if value <= 255 {
|
|
return fmt.Sprint("\x1b[", fgBgMarker, "8;5;", value, "m")
|
|
}
|
|
}
|
|
|
|
if color.colorType() == colorType24bit {
|
|
red := (value & 0xff0000) >> 16
|
|
green := (value & 0xff00) >> 8
|
|
blue := value & 0xff
|
|
|
|
return fmt.Sprint("\x1b[", fgBgMarker, "8;2;", red, ";", green, ";", blue, "m")
|
|
}
|
|
|
|
if color.colorType() == colorTypeDefault {
|
|
return fmt.Sprint("\x1b[", fgBgMarker, "9m")
|
|
}
|
|
|
|
panic(fmt.Errorf("unhandled color type=%d value=%#x", color.colorType(), value))
|
|
}
|
|
|
|
func (color Color) ForegroundAnsiString() string {
|
|
// FIXME: Test this function with all different color types.
|
|
return color.ansiString(true)
|
|
}
|
|
|
|
func (color Color) BackgroundAnsiString() string {
|
|
// FIXME: Test this function with all different color types.
|
|
return color.ansiString(false)
|
|
}
|
|
|
|
func (color Color) String() string {
|
|
switch color.colorType() {
|
|
case colorTypeDefault:
|
|
return "Default color"
|
|
|
|
case colorType16:
|
|
return colorNames16[int(color.colorValue())]
|
|
|
|
case colorType256:
|
|
if color.colorValue() < 16 {
|
|
return colorNames16[int(color.colorValue())]
|
|
}
|
|
return fmt.Sprintf("#%02x", color.colorValue())
|
|
|
|
case colorType24bit:
|
|
return fmt.Sprintf("#%06x", color.colorValue())
|
|
}
|
|
|
|
panic(fmt.Errorf("unhandled color type %d", color.colorType()))
|
|
}
|