diff --git a/internal/parser.go b/internal/parser.go index 3683a2e..628b625 100644 --- a/internal/parser.go +++ b/internal/parser.go @@ -7,9 +7,12 @@ import ( // Parse parses the passed format string and applies styles, returning a styled string. func Parse(format string) string { - var tempToken = make([]byte, 0, 50) var resParts = make([]string, 0, 50) - var formatSlice = make([]string, 0, 5) + + var err error + + var tempTokenStartIndex int + var tempTokenEndIndex int var lastToken string @@ -26,17 +29,18 @@ func Parse(format string) string { var needCheckFormatGroupStyle bool inText = true + formatLen := len(format) - for index := 0; index < len(format); index++ { + for index := 0; index < formatLen; index++ { s := format[index] if inText { // find {{ - if s == '{' && index+1 < len(format) && format[index+1] == '{' { - if len(tempToken) != 0 { - resParts = append(resParts, string(tempToken)) - tempToken = tempToken[:0] - } + if s == '{' && index+1 < formatLen && format[index+1] == '{' { + tempTokenEndIndex = index + resParts = append(resParts, format[tempTokenStartIndex:tempTokenEndIndex]) + + tempTokenStartIndex = index + 2 inFormatGroup = true inFormat = false @@ -55,7 +59,7 @@ func Parse(format string) string { if needCheckFormatGroupStyle { needCheckFormatGroupStyle = false - if !(s == ':' && index+1 < len(format) && format[index+1] == ':' && index+2 < len(format) && format[index+2] != ' ') { + if !(s == ':' && index+1 < formatLen && format[index+1] == ':' && index+2 < formatLen && format[index+2] != ' ') { lastIsFormatGroup = false if lastToken != "" { @@ -65,16 +69,16 @@ func Parse(format string) string { } // :: - if inEndFormatGroup && s == ':' && index+1 < len(format) && format[index+1] == ':' && index+2 < len(format) && format[index+2] != ' ' { + if inEndFormatGroup && s == ':' && index+1 < formatLen && format[index+1] == ':' && index+2 < formatLen && format[index+2] != ' ' { inFormatGroup = false inFormat = true inText = false inStartFormat = true + tempTokenStartIndex = index + 2 continue } - tempToken = append(tempToken, s) continue } @@ -85,7 +89,7 @@ func Parse(format string) string { continue } - if s == '}' && index+1 < len(format) && format[index+1] == '}' { + if s == '}' && index+1 < formatLen && format[index+1] == '}' { inFormatGroup = false inFormat = false inText = true @@ -94,13 +98,11 @@ func Parse(format string) string { lastIsFormatGroup = true needCheckFormatGroupStyle = true - lastToken = string(tempToken) + tempTokenEndIndex = index - tempToken = tempToken[:0] + lastToken = format[tempTokenStartIndex:tempTokenEndIndex] continue } - - tempToken = append(tempToken, s) continue } @@ -112,21 +114,30 @@ func Parse(format string) string { } if s == '|' { - formatSlice = append(formatSlice, string(tempToken)) - tempToken = tempToken[:0] + tempTokenEndIndex = index + + singleFormat := format[tempTokenStartIndex:tempTokenEndIndex] + lastToken, err = ApplyStyle(lastToken, singleFormat) + if err != nil { + log.Fatalf("Error parse style string in '%s' format string: %v", format, err) + } + + tempTokenStartIndex = index + 1 continue } if !(s >= 'a' && s <= 'z' || s >= 'A' && s <= 'Z') && s != '|' && !(s >= '0' && s <= '9') && s != '#' { - formatSlice = append(formatSlice, string(tempToken)) + tempTokenEndIndex = index - lastToken = groupStyle(format, lastToken, formatSlice) - resParts = append(resParts, lastToken) + singleFormat := format[tempTokenStartIndex:tempTokenEndIndex] + lastToken, err = ApplyStyle(lastToken, singleFormat) + if err != nil { + log.Fatalf("Error parse style string in '%s' format string: %v", format, err) + } - tempToken = tempToken[:0] - tempToken = append(tempToken, s) + tempTokenStartIndex = index - formatSlice = formatSlice[:0] + resParts = append(resParts, lastToken) inFormatGroup = false inFormat = false @@ -136,28 +147,17 @@ func Parse(format string) string { lastIsFormatGroup = false continue } - - tempToken = append(tempToken, s) continue } } if lastIsFormatGroup { - formatSlice = append(formatSlice, string(tempToken)) - lastToken = groupStyle(format, lastToken, formatSlice) + singleFormat := format[tempTokenStartIndex:] + lastToken, _ = ApplyStyle(lastToken, singleFormat) resParts = append(resParts, lastToken) } else { - resParts = append(resParts, string(tempToken)) + resParts = append(resParts, format[tempTokenStartIndex:]) } return strings.Join(resParts, "") } - -func groupStyle(format string, token string, styles []string) string { - styleText, err := StyleBuilder(styles, token) - if err != nil { - log.Fatalf("Error parse style string in '%s' format string: %v", format, err) - } - - return styleText -} diff --git a/internal/style.go b/internal/style.go index cbb39f9..24c27aa 100644 --- a/internal/style.go +++ b/internal/style.go @@ -3,8 +3,6 @@ package internal import ( "fmt" "strings" - - "github.com/gookit/color" ) // StyleBuilder is a function that returns a styled string based on the supplied style. @@ -13,43 +11,49 @@ func StyleBuilder(styles []string, text string) (string, error) { return "", fmt.Errorf("style string is empty") } - var colors = make([]color.Color, 0, len(styles)) - color.New() - + var err error for _, style := range styles { - if isHex(style) { - err := checkHex(style) - if err != nil { - return "", err - } - text = hexForegroundColorFunc(style, text) - continue + text, err = ApplyStyle(text, style) + if err != nil { + return "", err } + } + + return text, nil +} - if isBackgroundHex(style) { - rawHex := strings.TrimPrefix(style, "bg") - err := checkHex(rawHex) - if err != nil { - return "", err - } - text = hexBackgroundColorFunc(style, text) - continue +// StyleBuilder is a function that apply a style for string. +func ApplyStyle(text, style string) (string, error) { + if isHex(style) { + err := checkHex(style) + if err != nil { + return "", err } + text = hexForegroundColorFunc(style, text) + return text, nil + } + + if isBackgroundHex(style) { + rawHex := strings.TrimPrefix(style, "bg") + err := checkHex(rawHex) + if err != nil { + return "", err + } + text = hexBackgroundColorFunc(style, text) + return text, nil + } - clr, ok := Map[style] + clr, ok := Map[style] + if !ok { + customStyleFunc, ok := CustomMap[style] if !ok { - customStyleFunc, ok := CustomMap[style] - if !ok { - return "", fmt.Errorf("unknown style %s", style) - } - text = customStyleFunc(text) - continue + return "", fmt.Errorf("unknown style %s", style) } - colors = append(colors, clr) + text = customStyleFunc(text) + return text, nil } - colorStyle := color.New(colors...) - return colorStyle.Sprint(text), nil + return clr.Sprint(text), nil } func isHex(val string) bool { diff --git a/tests/parser_test.go b/tests/parser_test.go index 09e59d5..b9c7f82 100644 --- a/tests/parser_test.go +++ b/tests/parser_test.go @@ -11,13 +11,13 @@ func TestParse(t *testing.T) { return cfmt.Sprintf("{{%s}}::red|underline", s) }) - cfmt.Println("{{こんにちは, correct group}}::code") + cfmt.Println("{{こんにちは, correct group}}::code sdas") cfmt.Println("{{привет, correct group}}::red|underline and {{other}}::red") cfmt.Print("{{error group}} \n") cfmt.Print("{{overline group}}::overline\n") cfmt.Print("{{reverse group, こんにちは}}::reverse\n") - cfmt.Print(cfmt.Sprintln("{{faint group}}::faint")) + cfmt.Print(cfmt.Sprintln("{{faint group}}::faint sfafs")) cfmt.Println(cfmt.Sprint("{{blink group}}::blink")) - cfmt.Printf("{{hex %s}}::#ff00ff\n", "color group") - cfmt.Printf(cfmt.Sprintf("{{background color %s}}::bg#ffff00", "hex color")) + cfmt.Printf("{{hex %s}}::#ff00ff sfas\n", "color group") + cfmt.Printf(cfmt.Sprintf("{{background color %s}}::bg#ffff00\n", "hex color")) }