diff --git a/docs/docs/configuration.md b/docs/docs/configuration.md
index 89401262..03199046 100644
--- a/docs/docs/configuration.md
+++ b/docs/docs/configuration.md
@@ -335,6 +335,17 @@ Oh my Posh mainly supports three different color types being
`darkGray` `lightRed` `lightGreen` `lightYellow` `lightBlue` `lightMagenta` `lightCyan` `lightWhite`
+### Text decorations
+
+You can make use of the following syntax to decorate text:
+
+- `bold`: renders `bold` as bold text
+- `underline`: renders `underline` as underlined text
+- `italic`: renders `italic` as italic text
+- `strikethrough`: renders `strikethrough` as strikethrough text
+
+This can be used in templates and icons/text inside your config.
+
### Hyperlinks
The engine has the ability to render hyperlinks. Your terminal has to support it and the option
diff --git a/src/ansi_color.go b/src/ansi_color.go
index 9608afaf..f2418982 100644
--- a/src/ansi_color.go
+++ b/src/ansi_color.go
@@ -92,6 +92,7 @@ func (a *AnsiColor) writeAndRemoveText(background, foreground, text, textToRemov
}
func (a *AnsiColor) write(background, foreground, text string) {
+ text = a.formats.formatText(text)
// first we match for any potentially valid colors enclosed in <>
match := findAllNamedRegexMatch(`<(?P[^,>]+)?,?(?P[^>]+)?>(?P[^<]*)<\/>`, text)
for i := range match {
diff --git a/src/ansi_formats.go b/src/ansi_formats.go
index 4f205295..e43f5c0b 100644
--- a/src/ansi_formats.go
+++ b/src/ansi_formats.go
@@ -24,6 +24,10 @@ type ansiFormats struct {
escapeRight string
hyperlink string
osc99 string
+ bold string
+ italic string
+ underline string
+ strikethrough string
}
func (a *ansiFormats) init(shell string) {
@@ -45,6 +49,10 @@ func (a *ansiFormats) init(shell string) {
a.escapeRight = "%}"
a.hyperlink = "%%{\x1b]8;;%s\x1b\\%%}%s%%{\x1b]8;;\x1b\\%%}"
a.osc99 = "%%{\x1b]9;9;%s\x1b\\%%}"
+ a.bold = "%%{\x1b[1m%%}%s%%{\x1b[22m%%}"
+ a.italic = "%%{\x1b[3m%%}%s%%{\x1b[23m%%}"
+ a.underline = "%%{\x1b[4m%%}%s%%{\x1b[24m%%}"
+ a.strikethrough = "%%{\x1b[9m%%}%s%%{\x1b[29m%%}"
case bash:
a.linechange = "\\[\x1b[%d%s\\]"
a.left = "\\[\x1b[%dC\\]"
@@ -61,6 +69,10 @@ func (a *ansiFormats) init(shell string) {
a.escapeRight = "\\]"
a.hyperlink = "\\[\x1b]8;;%s\x1b\\\\\\]%s\\[\x1b]8;;\x1b\\\\\\]"
a.osc99 = "\\[\x1b]9;9;%s\x1b\\\\\\]"
+ a.bold = "\\[\x1b[1m\\]%s\\[\x1b[22m\\]"
+ a.italic = "\\[\x1b[3m\\]%s\\[\x1b[23m\\]"
+ a.underline = "\\[\x1b[4m\\]%s\\[\x1b[24m\\]"
+ a.strikethrough = "\\[\x1b[9m\\]%s\\[\x1b[29m\\]"
default:
a.linechange = "\x1b[%d%s"
a.left = "\x1b[%dC"
@@ -77,6 +89,11 @@ func (a *ansiFormats) init(shell string) {
a.escapeRight = ""
a.hyperlink = "\x1b]8;;%s\x1b\\%s\x1b]8;;\x1b\\"
a.osc99 = "\x1b]9;9;%s\x1b\\"
+ a.bold = "\x1b[1m%s\x1b[22m"
+ a.italic = "\x1b[3m%s\x1b[23m"
+ a.underline = "\x1b[4m%s\x1b[24m"
+ a.strikethrough = "\x1b[9m%s\x1b[29m"
+ a.strikethrough = "\x1b[9m%s\x1b[29m"
}
}
@@ -106,3 +123,22 @@ func (a *ansiFormats) generateHyperlink(text string) string {
// replace original text by the new one
return strings.Replace(text, results["all"], hyperlink, 1)
}
+
+func (a *ansiFormats) formatText(text string) string {
+ results := findAllNamedRegexMatch("(?P<(?P[buis])>(?P[^<]+)[buis]>)", text)
+ for _, result := range results {
+ var formatted string
+ switch result["format"] {
+ case "b":
+ formatted = fmt.Sprintf(a.bold, result["text"])
+ case "u":
+ formatted = fmt.Sprintf(a.underline, result["text"])
+ case "i":
+ formatted = fmt.Sprintf(a.italic, result["text"])
+ case "s":
+ formatted = fmt.Sprintf(a.strikethrough, result["text"])
+ }
+ text = strings.Replace(text, result["context"], formatted, 1)
+ }
+ return text
+}
diff --git a/src/ansi_formats_test.go b/src/ansi_formats_test.go
index 1a200d7d..d033004f 100644
--- a/src/ansi_formats_test.go
+++ b/src/ansi_formats_test.go
@@ -77,3 +77,23 @@ func TestGenerateHyperlinkWithUrlNoName(t *testing.T) {
assert.Equal(t, tc.Expected, hyperlinkText)
}
}
+
+func TestFormatText(t *testing.T) {
+ cases := []struct {
+ Case string
+ Text string
+ Expected string
+ }{
+ {Case: "single format", Text: "This is white", Expected: "This \x1b[1mis\x1b[22m white"},
+ {Case: "double format", Text: "This is white, this is orange", Expected: "This \x1b[1mis\x1b[22m white, this \x1b[1mis\x1b[22m orange"},
+ {Case: "underline", Text: "This is white", Expected: "This \x1b[4mis\x1b[24m white"},
+ {Case: "italic", Text: "This is white", Expected: "This \x1b[3mis\x1b[23m white"},
+ {Case: "strikethrough", Text: "This is white", Expected: "This \x1b[9mis\x1b[29m white"},
+ }
+ for _, tc := range cases {
+ a := ansiFormats{}
+ a.init("")
+ formattedText := a.formatText(tc.Text)
+ assert.Equal(t, tc.Expected, formattedText, tc.Case)
+ }
+}