bbuck/dragon-mud

View on GitHub
color/colors.go

Summary

Maintainability
A
0 mins
Test Coverage
package color
 
import (
"bytes"
"strings"
 
"github.com/mgutz/ansi"
)
 
const (
// ColorCodeOpen is the rune that denotes the beginning of the color code.
ColorCodeOpen = '{'
 
// ColorCodeClose is the rune that denotes the end of the color code.
ColorCodeClose = '}'
 
// ColorCodeEscape is the rune that denotes an escaped ColorCodeOpen
ColorCodeEscape = '\\'
)
 
// ColorizeFunc is a function that takes a string and returns a string with
// ANSI color escape codes in it.
type ColorizeFunc func(string) string
 
var (
noopColorFunc = ColorizeFunc(func(text string) string {
return text
})
colorFuncMap = make(map[string]ColorizeFunc)
commonPatterns = []string{
"black", "black+h",
"red", "red+h",
"green", "green+h",
"yellow", "yellow+h",
"blue", "blue+h",
"magenta", "magenta+h",
"cyan", "cyan+h",
"white", "white+h",
"reset",
}
)
 
func init() {
// we preload common color patterns to avoid processing these color codes
// during runtime
for _, pattern := range commonPatterns {
getColorFunction(pattern)
}
}
 
func getColorFunction(code string) ColorizeFunc {
var (
colorFunc ColorizeFunc
ok bool
)
 
if colorFunc, ok = colorFuncMap[code]; ok {
return colorFunc
}
 
colorFunc = ColorizeFunc(ansi.ColorFunc(code))
colorFuncMap[code] = colorFunc
 
return colorFunc
}
 
// ColorizeWithCode takes a color code and text string and returns the string
// with the appropriate color codes in it.
func ColorizeWithCode(code, text string) string {
return getColorFunction(code)(text)
}
 
// Colorize processes all colors in a given text block and returns a new string
// with all readable codes translated to ANSI codes.
func Colorize(text string) string {
final := new(bytes.Buffer)
toColor := new(bytes.Buffer)
prevColorFunc := noopColorFunc
for len(text) > 0 {
startIndex := strings.IndexRune(text, ColorCodeOpen)
switch {
// if it's escaped, skip it.
case startIndex > 0 && rune(text[startIndex-1]) == ColorCodeEscape:
toColor.WriteString(text[:startIndex-1])
toColor.WriteRune(ColorCodeOpen)
text = text[startIndex+1:]
continue
case startIndex < 0:
toColor.WriteString(text)
final.WriteString(prevColorFunc(toColor.String()))
text = ""
default:
toColor.WriteString(text[:startIndex])
final.WriteString(prevColorFunc(toColor.String()))
toColor = new(bytes.Buffer)
text = text[startIndex+1:]
endIndex := strings.IndexRune(text, ColorCodeClose)
prevColorFunc = getColorFunction(text[:endIndex])
text = text[endIndex+1:]
}
}
 
return final.String()
}
 
// Purge will remove color codes from the given string.
func Purge(text string) string {
final := new(bytes.Buffer)
for len(text) > 0 {
startIndex := strings.IndexRune(text, ColorCodeOpen)
switch {
case startIndex >= 0:
if startIndex > 0 && text[startIndex-1] == ColorCodeEscape {
final.WriteString(text[:startIndex-1])
final.WriteRune(ColorCodeOpen)
text = text[startIndex+1:]
continue
} else if startIndex > 0 {
final.WriteString(text[:startIndex])
}
 
endIndex := strings.IndexRune(text, ColorCodeClose)
text = text[endIndex+1:]
default:
final.WriteString(text)
text = ""
}
}
 
return final.String()
}
 
// Escape will replace all ANSI escape codes with text equivalents so strings
// can be printed with color codes.
func Escape(text string) string {
return strings.Replace(text, "\033", "\\033", -1)
}