tag-style color rendering fails if lines contain tag like content
System (please complete the following information):
- OS:
linux - GO Version:
1.18.1 - Pkg Version:
1.5.2
ENV info on the terminal (by command env | grep -i TERM):
COLORTERM=truecolor
TERM_PROGRAM_VERSION=3.2a
TERM=tmux-256color
TERM_PROGRAM=tmux
Describe the bug
I am using tag-style color rendeing to colorize tabular data. If multiple lines contain something like this: <none> then only the first colorziation works, subsequent ones are not replaced but printed as is.
To Reproduce
package main
import (
"github.com/gookit/color"
)
func main() {
test1 := `FAILS:
one <bg=lightGreen;fg=black>two</> <three>
foo <bg=lightGreen;fg=black>two</> <four>
`
test2 := `WORKS:
one <bg=lightGreen;fg=black>two <three></>
foo <bg=lightGreen;fg=black>two <four></>
`
test3 := `WORKS:
one <bg=lightGreen;fg=black>two</> three
foo <bg=lightGreen;fg=black>two</> four
`
color.Print(test1)
color.Print(test2)
color.Print(test3)
}
Expected behavior
The colorziation should work independently from other non color-tag content.
Screenshots
See screenshot attached.

** Edited to add **
The problem occurs ONLY if the "tagged" content appears outside the colorization. If it's inside, it works. Sample code and screenshot updated.
https://github.com/gookit/color/pull/53 fixes the issue for me.
hi @TLINDEN
FAILS:
one <bg=lightGreen;fg=black>two</> <three>
foo <bg=lightGreen;fg=black>two</> <four>
On fails, will match: <bg=lightGreen;fg=black>two</> <three>\nfoo <bg=lightGreen;fg=black>two</> ... Maybe is right, because color support match like <info> contents </>
If change regex s to m, will be not match mulit line contents:
foo <bg=lightGreen;fg=black>
two
</>
But then, there's still an issue, since <three> is no valid color tag. However - even if it were, the color module shall throw an error because there's no matching </> closing tag for it. And it's also too greedy, from my understanding as a user, it should be:
- match an opening tag, either
<$name>or<bg|fg...> - match the smallest possible part til the next part
- match the closing tag
</>
Or, if we translate the example into HTML:
one <b>two</b> <three>
foo <b>two</b> <four>
You'll get: one two <three> foo two <four>
But not: one two <three> foo two <four>
Now, I see that the s flag needs to be there in order to be able to match color tags spanning multiple lines. And since GO doesn't support negative lookahead lookups (which would fix it!), how can both cases be satisfied?
Ok, while I still think that this behavior is somewhat buggy, I resolved my issue by using regexp.ReplaceAllStringFunc() and inside I am using the color.Style.Sprint() function directly. That way I don't have to cope with any disambiguities.
So, from my point of view the case could be closed. Thanks for the fast response!
Thanks you I didn't think of a good way :)
Maybe ... can direct limit all color tag name. eg: info|red|yellow....
But then, there's still an issue, since
<three>is no valid color tag. However - even if it were, the color module shall throw an error because there's no matching</>closing tag for it. And it's also too greedy, from my understanding as a user, it should be:
- match an opening tag, either
<$name>or<bg|fg...>- match the smallest possible part til the next part
- match the closing tag
</>Or, if we translate the example into HTML:
one <b>two</b> <three> foo <b>two</b> <four>You'll get: one two
foo two But not: one two
foo two Now, I see that the
sflag needs to be there in order to be able to match color tags spanning multiple lines. And since GO doesn't support negative lookahead lookups (which would fix it!), how can both cases be satisfied?