Repository: fatih/color (language: go)

Issue:
using underline with a different fg color breaks it
I'm trying to pretty print a markdown file. The file uses `{{ some-text }}` in it for indicating variables, im removing the `{{`/`}}` and underline the inner text, and i'm also making the entire line cyan. But it seems, cyan get's removed after the first occurrence of the underlined word.
An example image:
![image](https://github.com/fatih/color/assets/91675932/5b87e5e9-dd33-438a-a896-397e3bd57bfc)

The part of the code is somewhat like this
```go
var underline = color.New(color.Underline).Sprint

line = highLightVariable(line)
line = color.CyanString(line)
fmt.Println(line)

func highLightVariable(line string) string {
	lines := strings.Split(line, "}}")
	lines = lo.Map(lines, func(line string, _ int) string {
		l := strings.Split(line, "{{")
		if len(l) > 1 {
			l[1] = underline(l[1])
		}
		return strings.Join(l, "{{")
	})
	line = strings.Join(lines, "}}")
	line = strings.ReplaceAll(line, "{{", "")
	line = strings.ReplaceAll(line, "}}", "")
	return line
}
```
the cyan colors stops after the first underlined word, even tho consequent words to have underlines.

In case, the full code is needed, check [this](https://github.com/Yakiyo/tilde/blob/b900c4f990fac58bc90daa77c0f39039eeccc85f/render/format.go#L31)


Discussion / hints:
After the second format is applied (underline in your case), color appends a reset [0m.
see this example:
![image](https://github.com/fatih/color/assets/2430354/3a0a9757-873f-4142-b5f3-4c45e9f51c44)
and the corresponding raw text :
`[36mword1 word2  [4mword3[0m word4 [1mword5[0m[0m`

color should be reappling any other format set before the underline.

Maybe instead of applying a generic reset [0m, color should apply the specific reset for the specified format.
for instance, to reset the underline [4m, color should use [24m. 
seems to me that the problem is in the unformat function (line 380) 
I will be submitting a branch 'issue_206' to resolve this issue. 

Fix patch:
diff --git a/color.go b/color.go
index 4d8b711..c423428 100644
--- a/color.go
+++ b/color.go
@@ -65,6 +65,29 @@ const (
 	CrossedOut
 )
 
+const (
+	ResetBold Attribute = iota + 22
+	ResetItalic
+	ResetUnderline
+	ResetBlinking
+	_
+	ResetReversed
+	ResetConcealed
+	ResetCrossedOut
+)
+
+var mapResetAttributes map[Attribute]Attribute = map[Attribute]Attribute{
+	Bold:         ResetBold,
+	Faint:        ResetBold,
+	Italic:       ResetItalic,
+	Underline:    ResetUnderline,
+	BlinkSlow:    ResetBlinking,
+	BlinkRapid:   ResetBlinking,
+	ReverseVideo: ResetReversed,
+	Concealed:    ResetConcealed,
+	CrossedOut:   ResetCrossedOut,
+}
+
 // Foreground text colors
 const (
 	FgBlack Attribute = iota + 30
@@ -377,7 +400,18 @@ func (c *Color) format() string {
 }
 
 func (c *Color) unformat() string {
-	return fmt.Sprintf("%s[%dm", escape, Reset)
+	//return fmt.Sprintf("%s[%dm", escape, Reset)
+	//for each element in sequence let's use the speficic reset escape, ou the generic one if not found
+	format := make([]string, len(c.params))
+	for i, v := range c.params {
+		format[i] = strconv.Itoa(int(Reset))
+		ra, ok := mapResetAttributes[v]
+		if ok {
+			format[i] = strconv.Itoa(int(ra))
+		}
+	}
+
+	return fmt.Sprintf("%s[%sm", escape, strings.Join(format, ";"))
 }
 
 // DisableColor disables the color output. Useful to not change any existing


Test patch:
diff --git a/color_test.go b/color_test.go
index ce80232..a8cc887 100644
--- a/color_test.go
+++ b/color_test.go
@@ -469,3 +469,38 @@ func readRaw(t *testing.T, r io.Reader) string {
 
 	return string(out)
 }
+
+func TestIssue206_1(t *testing.T) {
+	//visual test, go test -v .
+	//to  see the string with escape codes, use go test -v . > c:\temp\test.txt
+	var underline = New(Underline).Sprint
+
+	var line = fmt.Sprintf("%s %s %s %s", "word1", underline("word2"), "word3", underline("word4"))
+
+	line = CyanString(line)
+
+	fmt.Println(line)
+
+	var result = fmt.Sprintf("%v", line)
+	const expectedResult = "\x1b[36mword1 \x1b[4mword2\x1b[24m word3 \x1b[4mword4\x1b[24m\x1b[0m"
+
+	if !bytes.Equal([]byte(result), []byte(expectedResult)) {
+		t.Errorf("Expecting %v, got '%v'\n", expectedResult, result)
+	}
+}
+
+func TestIssue206_2(t *testing.T) {
+	var underline = New(Underline).Sprint
+	var bold = New(Bold).Sprint
+
+	var line = fmt.Sprintf("%s %s", GreenString(underline("underlined regular green")), RedString(bold("bold red")))
+
+	fmt.Println(line)
+
+	var result = fmt.Sprintf("%v", line)
+	const expectedResult = "\x1b[32m\x1b[4munderlined regular green\x1b[24m\x1b[0m \x1b[31m\x1b[1mbold red\x1b[22m\x1b[0m"
+
+	if !bytes.Equal([]byte(result), []byte(expectedResult)) {
+		t.Errorf("Expecting %v, got '%v'\n", expectedResult, result)
+	}
+}