diff options
Diffstat (limited to 'vendor/github.com/MichaelMure/go-term-text/escape_state.go')
-rw-r--r-- | vendor/github.com/MichaelMure/go-term-text/escape_state.go | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/vendor/github.com/MichaelMure/go-term-text/escape_state.go b/vendor/github.com/MichaelMure/go-term-text/escape_state.go new file mode 100644 index 00000000..cec35c26 --- /dev/null +++ b/vendor/github.com/MichaelMure/go-term-text/escape_state.go @@ -0,0 +1,265 @@ +package text + +import ( + "fmt" + "strconv" + "strings" +) + +const Escape = '\x1b' + +type EscapeState struct { + Bold bool + Dim bool + Italic bool + Underlined bool + Blink bool + Reverse bool + Hidden bool + CrossedOut bool + + FgColor Color + BgColor Color +} + +type Color interface { + Codes() []string +} + +func (es *EscapeState) Witness(s string) { + inEscape := false + var start int + + runes := []rune(s) + + for i, r := range runes { + if r == Escape { + inEscape = true + start = i + continue + } + if inEscape { + if r == 'm' { + inEscape = false + es.witnessCode(string(runes[start+1 : i])) + } + continue + } + } +} + +func (es *EscapeState) witnessCode(s string) { + if s == "" { + return + } + if s == "[" { + es.reset() + return + } + if len(s) < 2 { + return + } + if s[0] != '[' { + return + } + + s = s[1:] + split := strings.Split(s, ";") + + dequeue := func() { + split = split[1:] + } + + color := func(ground int) Color { + if len(split) < 1 { + // the whole sequence is broken, ignoring the rest + return nil + } + + subCode := split[0] + dequeue() + + switch subCode { + case "2": + if len(split) < 3 { + return nil + } + r, err := strconv.Atoi(split[0]) + dequeue() + if err != nil { + return nil + } + g, err := strconv.Atoi(split[0]) + dequeue() + if err != nil { + return nil + } + b, err := strconv.Atoi(split[0]) + dequeue() + if err != nil { + return nil + } + return &ColorRGB{ground: ground, R: r, G: g, B: b} + + case "5": + if len(split) < 1 { + return nil + } + index, err := strconv.Atoi(split[0]) + dequeue() + if err != nil { + return nil + } + return &Color256{ground: ground, Index: index} + + } + return nil + } + + for len(split) > 0 { + code, err := strconv.Atoi(split[0]) + if err != nil { + return + } + dequeue() + + switch { + case code == 0: + es.reset() + + case code == 1: + es.Bold = true + case code == 2: + es.Dim = true + case code == 3: + es.Italic = true + case code == 4: + es.Underlined = true + case code == 5: + es.Blink = true + // case code == 6: + case code == 7: + es.Reverse = true + case code == 8: + es.Hidden = true + case code == 9: + es.CrossedOut = true + + case code == 21: + es.Bold = false + case code == 22: + es.Dim = false + case code == 23: + es.Italic = false + case code == 24: + es.Underlined = false + case code == 25: + es.Blink = false + // case code == 26: + case code == 27: + es.Reverse = false + case code == 28: + es.Hidden = false + case code == 29: + es.CrossedOut = false + + case (code >= 30 && code <= 37) || code == 39 || (code >= 90 && code <= 97): + es.FgColor = ColorIndex(code) + + case (code >= 40 && code <= 47) || code == 49 || (code >= 100 && code <= 107): + es.BgColor = ColorIndex(code) + + case code == 38: + es.FgColor = color(code) + if es.FgColor == nil { + return + } + + case code == 48: + es.BgColor = color(code) + if es.BgColor == nil { + return + } + } + } +} + +func (es *EscapeState) reset() { + *es = EscapeState{} +} + +func (es *EscapeState) String() string { + var codes []string + + if es.Bold { + codes = append(codes, strconv.Itoa(1)) + } + if es.Dim { + codes = append(codes, strconv.Itoa(2)) + } + if es.Italic { + codes = append(codes, strconv.Itoa(3)) + } + if es.Underlined { + codes = append(codes, strconv.Itoa(4)) + } + if es.Blink { + codes = append(codes, strconv.Itoa(5)) + } + if es.Reverse { + codes = append(codes, strconv.Itoa(7)) + } + if es.Hidden { + codes = append(codes, strconv.Itoa(8)) + } + if es.CrossedOut { + codes = append(codes, strconv.Itoa(9)) + } + + if es.FgColor != nil { + codes = append(codes, es.FgColor.Codes()...) + } + if es.BgColor != nil { + codes = append(codes, es.BgColor.Codes()...) + } + + if len(codes) == 0 { + return "\x1b[0m" + } + + return fmt.Sprintf("\x1b[%sm", strings.Join(codes, ";")) +} + +type ColorIndex int + +func (cInd ColorIndex) Codes() []string { + return []string{strconv.Itoa(int(cInd))} +} + +type Color256 struct { + ground int + Index int +} + +func (c256 Color256) Codes() []string { + return []string{ + strconv.Itoa(c256.ground), + "5", + strconv.Itoa(c256.Index), + } +} + +type ColorRGB struct { + ground int + R, G, B int +} + +func (cRGB ColorRGB) Codes() []string { + return []string{ + strconv.Itoa(cRGB.ground), + "2", + strconv.Itoa(cRGB.R), + strconv.Itoa(cRGB.G), + strconv.Itoa(cRGB.B), + } +} |