2019-06-16 10:14:30 +03:00
|
|
|
|
package m
|
|
|
|
|
|
|
|
|
|
import (
|
2019-10-27 23:40:30 +03:00
|
|
|
|
"fmt"
|
2019-06-16 21:57:03 +03:00
|
|
|
|
"log"
|
2019-10-30 22:29:29 +03:00
|
|
|
|
"os"
|
2019-06-16 10:14:30 +03:00
|
|
|
|
"regexp"
|
2019-10-28 22:18:07 +03:00
|
|
|
|
"strconv"
|
2019-06-16 10:14:30 +03:00
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
|
|
"github.com/gdamore/tcell"
|
|
|
|
|
)
|
|
|
|
|
|
2019-06-17 22:39:57 +03:00
|
|
|
|
const _TabSize = 4
|
|
|
|
|
|
2019-10-30 21:52:49 +03:00
|
|
|
|
var manPageBold = tcell.StyleDefault.Bold(true)
|
|
|
|
|
var manPageUnderline = tcell.StyleDefault.Underline(true)
|
|
|
|
|
|
2019-06-16 21:57:03 +03:00
|
|
|
|
// Token is a rune with a style to be written to a cell on screen
|
2019-06-16 10:14:30 +03:00
|
|
|
|
type Token struct {
|
|
|
|
|
Rune rune
|
|
|
|
|
Style tcell.Style
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-30 22:29:29 +03:00
|
|
|
|
// SetManPageFormatFromEnv parses LESS_TERMCAP_xx environment variables and
|
|
|
|
|
// adapts the moar output accordingly.
|
2019-11-27 20:43:46 +03:00
|
|
|
|
func SetManPageFormatFromEnv() {
|
2019-10-30 22:29:29 +03:00
|
|
|
|
// Requested here: https://github.com/walles/moar/issues/14
|
|
|
|
|
|
|
|
|
|
lessTermcapMd := os.Getenv("LESS_TERMCAP_md")
|
|
|
|
|
if lessTermcapMd != "" {
|
2019-11-27 20:43:46 +03:00
|
|
|
|
manPageBold = _TermcapToStyle(lessTermcapMd)
|
2019-10-30 22:29:29 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lessTermcapUs := os.Getenv("LESS_TERMCAP_us")
|
|
|
|
|
if lessTermcapUs != "" {
|
2019-11-27 20:43:46 +03:00
|
|
|
|
manPageUnderline = _TermcapToStyle(lessTermcapUs)
|
2019-10-30 22:29:29 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-05 10:32:06 +03:00
|
|
|
|
// Used from tests
|
|
|
|
|
func _ResetManPageFormatForTesting() {
|
|
|
|
|
manPageBold = tcell.StyleDefault.Bold(true)
|
|
|
|
|
manPageUnderline = tcell.StyleDefault.Underline(true)
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-27 20:43:46 +03:00
|
|
|
|
func _TermcapToStyle(termcap string) tcell.Style {
|
2019-10-30 22:29:29 +03:00
|
|
|
|
// Add a character to be sure we have one to take the format from
|
2019-11-27 20:43:46 +03:00
|
|
|
|
tokens, _ := TokensFromString(termcap + "x")
|
2019-10-30 22:29:29 +03:00
|
|
|
|
return tokens[len(tokens)-1].Style
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-30 16:06:33 +03:00
|
|
|
|
// TokensFromString turns a (formatted) string into a series of tokens,
|
|
|
|
|
// and an unformatted string
|
2019-11-27 20:43:46 +03:00
|
|
|
|
func TokensFromString(s string) ([]Token, *string) {
|
2019-06-16 10:14:30 +03:00
|
|
|
|
var tokens []Token
|
|
|
|
|
|
2019-06-18 20:08:35 +03:00
|
|
|
|
styleBrokenUtf8 := tcell.StyleDefault.Background(7).Foreground(1)
|
|
|
|
|
|
2019-11-27 20:43:46 +03:00
|
|
|
|
for _, styledString := range _StyledStringsFromString(s) {
|
2019-06-27 22:39:46 +03:00
|
|
|
|
for _, token := range _TokensFromStyledString(styledString) {
|
|
|
|
|
switch token.Rune {
|
2019-06-18 20:08:35 +03:00
|
|
|
|
|
|
|
|
|
case '\x09': // TAB
|
2019-06-17 22:39:57 +03:00
|
|
|
|
for {
|
|
|
|
|
tokens = append(tokens, Token{
|
|
|
|
|
Rune: ' ',
|
|
|
|
|
Style: styledString.Style,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
if (len(tokens))%_TabSize == 0 {
|
|
|
|
|
// We arrived at the next tab stop
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-06-18 20:08:35 +03:00
|
|
|
|
|
|
|
|
|
case '<27>': // Go's broken-UTF8 marker
|
|
|
|
|
tokens = append(tokens, Token{
|
|
|
|
|
Rune: '?',
|
|
|
|
|
Style: styleBrokenUtf8,
|
|
|
|
|
})
|
|
|
|
|
|
2019-06-27 22:39:46 +03:00
|
|
|
|
case '\x08': // Backspace
|
2019-06-17 22:39:57 +03:00
|
|
|
|
tokens = append(tokens, Token{
|
2019-06-27 22:39:46 +03:00
|
|
|
|
Rune: '<',
|
|
|
|
|
Style: styleBrokenUtf8,
|
2019-06-17 22:39:57 +03:00
|
|
|
|
})
|
2019-06-27 22:39:46 +03:00
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
tokens = append(tokens, token)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-19 19:28:58 +03:00
|
|
|
|
var stringBuilder strings.Builder
|
|
|
|
|
stringBuilder.Grow(len(tokens))
|
2019-06-30 16:06:33 +03:00
|
|
|
|
for _, token := range tokens {
|
2019-11-19 19:28:58 +03:00
|
|
|
|
stringBuilder.WriteRune(token.Rune)
|
2019-06-30 16:06:33 +03:00
|
|
|
|
}
|
2019-11-19 19:28:58 +03:00
|
|
|
|
plainString := stringBuilder.String()
|
2019-06-30 16:06:33 +03:00
|
|
|
|
return tokens, &plainString
|
2019-06-27 22:39:46 +03:00
|
|
|
|
}
|
|
|
|
|
|
2019-11-27 22:59:27 +03:00
|
|
|
|
func _ConsumeBold(runes []rune, index int) (int, *Token) {
|
|
|
|
|
if index+2 >= len(runes) {
|
|
|
|
|
// Not enough runes left for a bold
|
|
|
|
|
return index, nil
|
|
|
|
|
}
|
2019-06-27 22:39:46 +03:00
|
|
|
|
|
2019-11-27 22:59:27 +03:00
|
|
|
|
if runes[index+1] != '\b' {
|
|
|
|
|
// No backspace in the middle, never mind
|
|
|
|
|
return index, nil
|
|
|
|
|
}
|
2019-06-27 22:39:46 +03:00
|
|
|
|
|
2019-11-27 22:59:27 +03:00
|
|
|
|
if runes[index] != runes[index+2] {
|
|
|
|
|
// First and last rune not the same, never mind
|
|
|
|
|
return index, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We have a match!
|
|
|
|
|
return index + 3, &Token{
|
|
|
|
|
Rune: runes[index],
|
|
|
|
|
Style: manPageBold,
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-06-27 22:39:46 +03:00
|
|
|
|
|
2019-11-27 22:59:27 +03:00
|
|
|
|
func _ConsumeUnderline(runes []rune, index int) (int, *Token) {
|
|
|
|
|
if index+2 >= len(runes) {
|
|
|
|
|
// Not enough runes left for a underline
|
|
|
|
|
return index, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if runes[index+1] != '\b' {
|
|
|
|
|
// No backspace in the middle, never mind
|
|
|
|
|
return index, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if runes[index] != '_' {
|
|
|
|
|
// No underline, never mind
|
|
|
|
|
return index, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We have a match!
|
|
|
|
|
return index + 3, &Token{
|
|
|
|
|
Rune: runes[index+2],
|
|
|
|
|
Style: manPageUnderline,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func _TokensFromStyledString(styledString _StyledString) []Token {
|
|
|
|
|
runes := []rune(styledString.String)
|
|
|
|
|
tokens := make([]Token, 0, len(runes))
|
|
|
|
|
|
|
|
|
|
for index := 0; index < len(runes); index++ {
|
|
|
|
|
nextIndex, token := _ConsumeBold(runes, index)
|
|
|
|
|
if nextIndex != index {
|
|
|
|
|
tokens = append(tokens, *token)
|
|
|
|
|
index = nextIndex - 1
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nextIndex, token = _ConsumeUnderline(runes, index)
|
|
|
|
|
if nextIndex != index {
|
|
|
|
|
tokens = append(tokens, *token)
|
|
|
|
|
index = nextIndex - 1
|
|
|
|
|
continue
|
2019-06-16 10:14:30 +03:00
|
|
|
|
}
|
2019-06-27 22:39:46 +03:00
|
|
|
|
|
|
|
|
|
tokens = append(tokens, Token{
|
2019-11-27 22:59:27 +03:00
|
|
|
|
Rune: runes[index],
|
2019-06-27 22:39:46 +03:00
|
|
|
|
Style: styledString.Style,
|
|
|
|
|
})
|
2019-06-16 10:14:30 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return tokens
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type _StyledString struct {
|
|
|
|
|
String string
|
|
|
|
|
Style tcell.Style
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-27 20:43:46 +03:00
|
|
|
|
func _StyledStringsFromString(s string) []_StyledString {
|
2019-06-16 10:14:30 +03:00
|
|
|
|
// This function was inspired by the
|
|
|
|
|
// https://golang.org/pkg/regexp/#Regexp.Split source code
|
|
|
|
|
|
|
|
|
|
pattern := regexp.MustCompile("\x1b\\[([0-9;]*m)")
|
|
|
|
|
|
|
|
|
|
matches := pattern.FindAllStringIndex(s, -1)
|
|
|
|
|
styledStrings := make([]_StyledString, 0, len(matches)+1)
|
|
|
|
|
|
|
|
|
|
style := tcell.StyleDefault
|
|
|
|
|
|
|
|
|
|
beg := 0
|
|
|
|
|
end := 0
|
|
|
|
|
for _, match := range matches {
|
|
|
|
|
end = match[0]
|
|
|
|
|
|
2019-06-16 10:23:25 +03:00
|
|
|
|
if end > beg {
|
2019-06-27 22:39:46 +03:00
|
|
|
|
// Found non-zero length string
|
2019-06-16 10:14:30 +03:00
|
|
|
|
styledStrings = append(styledStrings, _StyledString{
|
|
|
|
|
String: s[beg:end],
|
|
|
|
|
Style: style,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
matchedPart := s[match[0]:match[1]]
|
2019-11-27 20:43:46 +03:00
|
|
|
|
style = _UpdateStyle(style, matchedPart)
|
2019-06-16 10:14:30 +03:00
|
|
|
|
|
|
|
|
|
beg = match[1]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if end != len(s) {
|
|
|
|
|
styledStrings = append(styledStrings, _StyledString{
|
|
|
|
|
String: s[beg:],
|
|
|
|
|
Style: style,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return styledStrings
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// _UpdateStyle parses a string of the form "ESC[33m" into changes to style
|
2019-11-27 20:43:46 +03:00
|
|
|
|
func _UpdateStyle(style tcell.Style, escapeSequence string) tcell.Style {
|
2019-10-27 11:15:16 +03:00
|
|
|
|
numbers := strings.Split(escapeSequence[2:len(escapeSequence)-1], ";")
|
|
|
|
|
index := 0
|
|
|
|
|
for index < len(numbers) {
|
|
|
|
|
number := numbers[index]
|
|
|
|
|
index++
|
2019-10-28 23:54:57 +03:00
|
|
|
|
switch strings.TrimLeft(number, "0") {
|
|
|
|
|
case "":
|
2019-06-16 10:14:30 +03:00
|
|
|
|
style = tcell.StyleDefault
|
2019-06-16 21:57:03 +03:00
|
|
|
|
|
2019-06-16 21:58:19 +03:00
|
|
|
|
case "1":
|
|
|
|
|
style = style.Bold(true)
|
|
|
|
|
|
Support SGR 4, underline
diff --git m/ansiTokenizer.go m/ansiTokenizer.go
index 365b76a..7161bc6 100644
--- m/ansiTokenizer.go
+++ m/ansiTokenizer.go
@@ -179,6 +179,9 @@ func _UpdateStyle(logger *log.Logger, style tcell.Style, escapeSequence string)
case "1":
style = style.Bold(true)
+ case "4":
+ style = style.Underline(true)
+
case "7":
style = style.Reverse(true)
@@ -226,7 +229,7 @@ func _UpdateStyle(logger *log.Logger, style tcell.Style, escapeSequence string)
style = style.Background(tcell.ColorDefault)
default:
- logger.Printf("Unrecognized ANSI SGI code <%s>", number)
+ logger.Printf("Unrecognized ANSI SGR code <%s>", number)
}
}
Change-Id: I0527cbaff8b53cf25c99876789d69412af5ca118
2019-09-25 14:41:50 +03:00
|
|
|
|
case "4":
|
|
|
|
|
style = style.Underline(true)
|
|
|
|
|
|
2019-06-16 22:39:27 +03:00
|
|
|
|
case "7":
|
|
|
|
|
style = style.Reverse(true)
|
|
|
|
|
|
|
|
|
|
case "27":
|
|
|
|
|
style = style.Reverse(false)
|
|
|
|
|
|
2019-06-16 21:57:03 +03:00
|
|
|
|
// Foreground colors
|
2019-06-16 10:14:30 +03:00
|
|
|
|
case "30":
|
2019-06-16 22:26:04 +03:00
|
|
|
|
style = style.Foreground(0)
|
2019-06-16 10:14:30 +03:00
|
|
|
|
case "31":
|
2019-06-16 22:26:04 +03:00
|
|
|
|
style = style.Foreground(1)
|
2019-06-16 10:14:30 +03:00
|
|
|
|
case "32":
|
2019-06-16 22:26:04 +03:00
|
|
|
|
style = style.Foreground(2)
|
2019-06-16 10:14:30 +03:00
|
|
|
|
case "33":
|
2019-06-16 22:26:04 +03:00
|
|
|
|
style = style.Foreground(3)
|
2019-06-16 10:14:30 +03:00
|
|
|
|
case "34":
|
2019-06-16 22:26:04 +03:00
|
|
|
|
style = style.Foreground(4)
|
2019-06-16 10:14:30 +03:00
|
|
|
|
case "35":
|
2019-06-16 22:26:04 +03:00
|
|
|
|
style = style.Foreground(5)
|
2019-06-16 10:14:30 +03:00
|
|
|
|
case "36":
|
2019-06-16 22:26:04 +03:00
|
|
|
|
style = style.Foreground(6)
|
2019-06-16 10:14:30 +03:00
|
|
|
|
case "37":
|
2019-06-16 22:26:04 +03:00
|
|
|
|
style = style.Foreground(7)
|
2019-10-27 11:15:16 +03:00
|
|
|
|
case "38":
|
|
|
|
|
var err error = nil
|
|
|
|
|
var color *tcell.Color
|
2019-10-27 23:40:30 +03:00
|
|
|
|
index, color, err = consumeCompositeColor(numbers, index-1)
|
2019-10-27 11:15:16 +03:00
|
|
|
|
if err != nil {
|
2019-11-27 20:43:46 +03:00
|
|
|
|
log.Printf("Foreground: %s", err.Error())
|
2019-10-27 11:15:16 +03:00
|
|
|
|
return style
|
|
|
|
|
}
|
|
|
|
|
style = style.Foreground(*color)
|
2019-07-15 14:34:42 +03:00
|
|
|
|
case "39":
|
|
|
|
|
style = style.Foreground(tcell.ColorDefault)
|
2019-06-16 21:57:03 +03:00
|
|
|
|
|
|
|
|
|
// Background colors
|
|
|
|
|
case "40":
|
2019-06-16 22:26:04 +03:00
|
|
|
|
style = style.Background(0)
|
2019-06-16 21:57:03 +03:00
|
|
|
|
case "41":
|
2019-06-16 22:26:04 +03:00
|
|
|
|
style = style.Background(1)
|
2019-06-16 21:57:03 +03:00
|
|
|
|
case "42":
|
2019-06-16 22:26:04 +03:00
|
|
|
|
style = style.Background(2)
|
2019-06-16 21:57:03 +03:00
|
|
|
|
case "43":
|
2019-06-16 22:26:04 +03:00
|
|
|
|
style = style.Background(3)
|
2019-06-16 21:57:03 +03:00
|
|
|
|
case "44":
|
2019-06-16 22:26:04 +03:00
|
|
|
|
style = style.Background(4)
|
2019-06-16 21:57:03 +03:00
|
|
|
|
case "45":
|
2019-06-16 22:26:04 +03:00
|
|
|
|
style = style.Background(5)
|
2019-06-16 21:57:03 +03:00
|
|
|
|
case "46":
|
2019-06-16 22:26:04 +03:00
|
|
|
|
style = style.Background(6)
|
2019-06-16 21:57:03 +03:00
|
|
|
|
case "47":
|
2019-06-16 22:26:04 +03:00
|
|
|
|
style = style.Background(7)
|
2019-10-27 11:15:16 +03:00
|
|
|
|
case "48":
|
|
|
|
|
var err error = nil
|
|
|
|
|
var color *tcell.Color
|
2019-10-27 23:40:30 +03:00
|
|
|
|
index, color, err = consumeCompositeColor(numbers, index-1)
|
2019-10-27 11:15:16 +03:00
|
|
|
|
if err != nil {
|
2019-11-27 20:43:46 +03:00
|
|
|
|
log.Printf("Background: %s", err.Error())
|
2019-10-27 11:15:16 +03:00
|
|
|
|
return style
|
|
|
|
|
}
|
|
|
|
|
style = style.Background(*color)
|
2019-07-15 14:34:42 +03:00
|
|
|
|
case "49":
|
|
|
|
|
style = style.Background(tcell.ColorDefault)
|
2019-06-16 21:57:03 +03:00
|
|
|
|
|
|
|
|
|
default:
|
2019-11-27 20:43:46 +03:00
|
|
|
|
log.Printf("Unrecognized ANSI SGR code <%s>", number)
|
2019-06-16 10:14:30 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return style
|
|
|
|
|
}
|
2019-10-27 11:15:16 +03:00
|
|
|
|
|
2019-10-27 23:40:30 +03:00
|
|
|
|
// numbers is a list of numbers from a ANSI SGR string
|
2019-10-27 11:15:16 +03:00
|
|
|
|
// index points to either 38 or 48 in that string
|
|
|
|
|
//
|
|
|
|
|
// This method will return:
|
|
|
|
|
// * The first index in the string that this function did not consume
|
|
|
|
|
// * A color value that can be applied to a style
|
2019-10-27 23:40:30 +03:00
|
|
|
|
func consumeCompositeColor(numbers []string, index int) (int, *tcell.Color, error) {
|
2019-10-28 22:09:08 +03:00
|
|
|
|
baseIndex := index
|
2019-10-27 23:40:30 +03:00
|
|
|
|
if numbers[index] != "38" && numbers[index] != "48" {
|
|
|
|
|
err := fmt.Errorf(
|
|
|
|
|
"Unknown start of color sequence <%s>, expected 38 (foreground) or 48 (background): <CSI %sm>",
|
|
|
|
|
numbers[index],
|
2019-10-28 22:09:08 +03:00
|
|
|
|
strings.Join(numbers[baseIndex:], ";"))
|
|
|
|
|
return -1, nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
index++
|
|
|
|
|
if index >= len(numbers) {
|
|
|
|
|
err := fmt.Errorf(
|
|
|
|
|
"Incomplete color sequence: <CSI %sm>",
|
|
|
|
|
strings.Join(numbers[baseIndex:], ";"))
|
2019-10-27 23:40:30 +03:00
|
|
|
|
return -1, nil, err
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-28 22:18:07 +03:00
|
|
|
|
if numbers[index] == "5" {
|
2019-10-28 22:30:04 +03:00
|
|
|
|
// Handle 8 bit color
|
2019-10-28 22:18:07 +03:00
|
|
|
|
index++
|
|
|
|
|
if index >= len(numbers) {
|
|
|
|
|
err := fmt.Errorf(
|
|
|
|
|
"Incomplete 8 bit color sequence: <CSI %sm>",
|
|
|
|
|
strings.Join(numbers[baseIndex:], ";"))
|
|
|
|
|
return -1, nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
colorNumber, err := strconv.Atoi(numbers[index])
|
|
|
|
|
if err != nil {
|
|
|
|
|
return -1, nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
colorValue := tcell.Color(colorNumber)
|
|
|
|
|
return index + 1, &colorValue, nil
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-28 22:21:39 +03:00
|
|
|
|
if numbers[index] == "2" {
|
2019-10-28 22:30:04 +03:00
|
|
|
|
// Handle 24 bit color
|
|
|
|
|
rIndex := index + 1
|
|
|
|
|
gIndex := index + 2
|
|
|
|
|
bIndex := index + 3
|
|
|
|
|
if bIndex >= len(numbers) {
|
|
|
|
|
err := fmt.Errorf(
|
|
|
|
|
"Incomplete 24 bit color sequence, expected N8;2;R;G;Bm: <CSI %sm>",
|
|
|
|
|
strings.Join(numbers[baseIndex:], ";"))
|
|
|
|
|
return -1, nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rValueX, err := strconv.ParseInt(numbers[rIndex], 10, 32)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return -1, nil, err
|
|
|
|
|
}
|
|
|
|
|
rValue := int32(rValueX)
|
|
|
|
|
|
|
|
|
|
gValueX, err := strconv.Atoi(numbers[gIndex])
|
|
|
|
|
if err != nil {
|
|
|
|
|
return -1, nil, err
|
|
|
|
|
}
|
|
|
|
|
gValue := int32(gValueX)
|
|
|
|
|
|
|
|
|
|
bValueX, err := strconv.Atoi(numbers[bIndex])
|
|
|
|
|
if err != nil {
|
|
|
|
|
return -1, nil, err
|
|
|
|
|
}
|
|
|
|
|
bValue := int32(bValueX)
|
|
|
|
|
|
|
|
|
|
colorValue := tcell.NewRGBColor(rValue, gValue, bValue)
|
|
|
|
|
return bIndex + 1, &colorValue, nil
|
2019-10-28 22:21:39 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err := fmt.Errorf(
|
|
|
|
|
"Unknown color type <%s>, expected 5 (8 bit color) or 2 (24 bit color): <CSI %sm>",
|
|
|
|
|
numbers[index],
|
|
|
|
|
strings.Join(numbers[baseIndex:], ";"))
|
|
|
|
|
return -1, nil, err
|
2019-10-27 11:15:16 +03:00
|
|
|
|
}
|