Repository: JanDeDobbeleer/oh-my-posh
Pull request #1223 (2021-11-14 10:05:15)

feat: add template capabilities to multiple segments
### Prerequisites

- [x] I have read and understood the `CONTRIBUTING` guide
- [x] The commit message follows the [conventional commits][cc] guidelines
- [x] Tests for the changes have been added (for bug fixes/features)
- [x] Docs have been added / updated (for bug fixes/features)

### Description

- feat(env): add template properties
- feat(executiontime): add template properties

<!---

Tips:

If you're not comfortable with working with Git, we're working a guide (https://ohmyposh.dev/docs/contributing_git) to help you out.
Oh My Posh advises GitKraken (https://www.gitkraken.com/invite/nQmDPR9D) as your preferred cross platform Git GUI power tool.

-->

[cc]: https://www.conventionalcommits.org/en/v1.0.0/#summary



Patch:
diff --git a/docs/docs/config-overview.md b/docs/docs/config-overview.md
index b694d767..1fdbcba5 100644
--- a/docs/docs/config-overview.md
+++ b/docs/docs/config-overview.md
@@ -344,23 +344,36 @@ This means that for user Bill, who has a user account `Bill` on Windows and `bil
         {
           "type": "git",
           "style": "powerline",
-          "powerline_symbol": "\uE0B0",
           "foreground": "#193549",
-          "background": "#ffeb3b"
+          "foreground_templates": [
+            "{{ if and (gt .Ahead 0) (gt .Behind 0) }}#ffffff{{ end }}"
+          ],
+          "background": "#2e9599",
+          "background_templates": [
+            "{{ if or (.Working.Changed) (.Staging.Changed) }}#f36943{{ end }}",
+            "{{ if and (gt .Ahead 0) (gt .Behind 0) }}#a8216b{{ end }}",
+            "{{ if gt .Ahead 0 }}#35b5ff{{ end }}",
+            "{{ if gt .Behind 0 }}#f89cfa{{ end }}"
+          ],
+          "powerline_symbol": "\uE0B0",
+          "properties": {
+            "fetch_status": true,
+            "branch_max_length": 25,
+            "template": "{{ .HEAD }}{{ .BranchStatus }}"
+          }
         },
         {
           "type": "exit",
           "style": "diamond",
           "foreground": "#ffffff",
           "background": "#00897b",
+          "background_templates": ["{{ if gt .Code 0 }}#e91e63{{ end }}"],
           "leading_diamond": "",
           "trailing_diamond": "\uE0B4",
           "properties": {
-            "display_exit_code": false,
             "always_enabled": true,
-            "error_color": "#e91e63",
-            "color_background": true,
-            "prefix": "<#193549>\uE0B0 \uE23A</>"
+            "template": "\uE23A",
+            "prefix": "<parentBackground>\uE0B0</> "
           }
         }
       ]
diff --git a/docs/docs/segment-environment.md b/docs/docs/segment-environment.md
index 8ddf5c8b..1012c851 100644
--- a/docs/docs/segment-environment.md
+++ b/docs/docs/segment-environment.md
@@ -50,3 +50,7 @@ The segment will show when the value of the environment variable isn't empty.
 ```
 
 - var_name: `string` - the name of the environment variable
+
+## Template Properties
+
+- `.Value`: `string` - the value of the environment variable
diff --git a/docs/docs/segment-executiontime.md b/docs/docs/segment-executiontime.md
index baec7059..e6d30e19 100644
--- a/docs/docs/segment-executiontime.md
+++ b/docs/docs/segment-executiontime.md
@@ -48,3 +48,8 @@ Style specifies the format in which the time will be displayed. The table below
 | houston   | `00:00:00.001` | `00:00:02.1` | `00:03:02.1`  | `04:03:02.1`     |
 | amarillo  | `0.001s`       | `2.1s`       | `182.1s`      | `14,582.1s`      |
 | round     | `1ms`          | `2s`         | `3m 2s`       | `4h 3m`          |
+
+## Template Properties
+
+- `.Ms`: `number` - the execution time in milliseconds
+- `.FormattedMs`: `string` - the formatted value based on the `style` above.
diff --git a/docs/docs/segment-exit.md b/docs/docs/segment-exit.md
index 14ecd45b..6ed4cc21 100644
--- a/docs/docs/segment-exit.md
+++ b/docs/docs/segment-exit.md
@@ -16,26 +16,26 @@ Displays the last exit code or that the last command failed based on the configu
   "style": "diamond",
   "foreground": "#ffffff",
   "background": "#00897b",
+  "background_templates": [
+    "{{ if gt .Code 0 }}#e91e63{{ end }}",
+  ],
   "leading_diamond": "",
   "trailing_diamond": "\uE0B4",
   "properties": {
-    "display_exit_code": false,
     "always_enabled": true,
-    "error_color": "#e91e63",
-    "color_background": true,
-    "prefix": "<#193549>\uE0B0</> \uE23A"
+    "template": "\uE23A",
+    "prefix": "<#193549>\uE0B0</> "
   }
 }
 ```
 
 ## Properties
 
-- display_exit_code: `boolean` - show or hide the exit code - defaults to `true`
 - always_enabled: `boolean` - always show the status - defaults to `false`
-- color_background: `boolean` - color the background or foreground when an error occurs - defaults to `false`
-- error_color: `string` [color][colors] - color to use when an error occurred
-- always_numeric: `boolean` - always display exit code as a number - defaults to `false`
-- success_icon: `string` - displays when there's no error and `"always_enabled": true` - defaults to `""`
-- error_icon: `string` - displays when there's an error - defaults to `""`
 
 [colors]: /docs/config-colors
+
+## Template Properties
+
+- `.Code`: `number` - the last known exit code
+- `.Text`: `string` - the textual meaning linked to exit code (if applicable, otherwise identical to `.Code`)
diff --git a/src/segment_git_deprecated.go b/src/segment_deprecated.go
similarity index 78%
rename from src/segment_git_deprecated.go
rename to src/segment_deprecated.go
index 52404a9a..d2213d0c 100644
--- a/src/segment_git_deprecated.go
+++ b/src/segment_deprecated.go
@@ -6,6 +6,8 @@ import (
 	"strings"
 )
 
+// GIT Segement
+
 const (
 	// DisplayStatus shows the status of the repository
 	DisplayStatus Property = "display_status"
@@ -15,7 +17,6 @@ const (
 	DisplayWorktreeCount Property = "display_worktree_count"
 	// DisplayUpstreamIcon show or hide the upstream icon
 	DisplayUpstreamIcon Property = "display_upstream_icon"
-
 	// LocalWorkingIcon the icon to use as the local working area changes indicator
 	LocalWorkingIcon Property = "local_working_icon"
 	// LocalStagingIcon the icon to use as the local staging area changes indicator
@@ -52,7 +53,7 @@ func (g *git) getBool(property, legacyProperty Property) bool {
 	return g.props.getBool(property, false)
 }
 
-func (g *git) renderDeprecatedString(statusColorsEnabled bool) string {
+func (g *git) deprecatedString(statusColorsEnabled bool) string {
 	if statusColorsEnabled {
 		g.SetStatusColor()
 	}
@@ -129,3 +130,39 @@ func (g *git) colorStatusString(prefix, status, color string) string {
 	}
 	return fmt.Sprintf("<%s>%s %s</>", color, prefix, status)
 }
+
+// EXIT Segment
+
+const (
+	// DisplayExitCode shows or hides the error code
+	DisplayExitCode Property = "display_exit_code"
+	// ErrorColor specify a different foreground color for the error text when using always_show = true
+	ErrorColor Property = "error_color"
+	// AlwaysNumeric shows error codes as numbers
+	AlwaysNumeric Property = "always_numeric"
+	// SuccessIcon displays when there's no error and AlwaysEnabled = true
+	SuccessIcon Property = "success_icon"
+	// ErrorIcon displays when there's an error
+	ErrorIcon Property = "error_icon"
+)
+
+func (e *exit) deprecatedString() string {
+	colorBackground := e.props.getBool(ColorBackground, false)
+	if e.Code != 0 && !colorBackground {
+		e.props.foreground = e.props.getColor(ErrorColor, e.props.foreground)
+	}
+	if e.Code != 0 && colorBackground {
+		e.props.background = e.props.getColor(ErrorColor, e.props.background)
+	}
+	if e.Code == 0 {
+		return e.props.getString(SuccessIcon, "")
+	}
+	errorIcon := e.props.getString(ErrorIcon, "")
+	if !e.props.getBool(DisplayExitCode, true) {
+		return errorIcon
+	}
+	if e.props.getBool(AlwaysNumeric, false) {
+		return fmt.Sprintf("%s%d", errorIcon, e.Code)
+	}
+	return fmt.Sprintf("%s%s", errorIcon, e.Text)
+}
diff --git a/src/segment_envar.go b/src/segment_envar.go
index d403ab26..b5bc65ae 100644
--- a/src/segment_envar.go
+++ b/src/segment_envar.go
@@ -1,9 +1,9 @@
 package main
 
 type envvar struct {
-	props   *properties
-	env     environmentInfo
-	content string
+	props *properties
+	env   environmentInfo
+	Value string
 }
 
 const (
@@ -13,12 +13,12 @@ const (
 
 func (e *envvar) enabled() bool {
 	name := e.props.getString(VarName, "")
-	e.content = e.env.getenv(name)
-	return e.content != ""
+	e.Value = e.env.getenv(name)
+	return e.Value != ""
 }
 
 func (e *envvar) string() string {
-	return e.content
+	return e.Value
 }
 
 func (e *envvar) init(props *properties, env environmentInfo) {
diff --git a/src/segment_executiontime.go b/src/segment_executiontime.go
index 6a32dbaa..439c7505 100644
--- a/src/segment_executiontime.go
+++ b/src/segment_executiontime.go
@@ -9,9 +9,11 @@ import (
 )
 
 type executiontime struct {
-	props  *properties
-	env    environmentInfo
-	output string
+	props *properties
+	env   environmentInfo
+
+	FormattedMs string
+	Ms          int64
 }
 
 // DurationStyle how to display the time
@@ -52,13 +54,13 @@ func (t *executiontime) enabled() bool {
 		return false
 	}
 	style := DurationStyle(t.props.getString(Style, string(Austin)))
-	t.output = t.formatDuration(int64(executionTimeMs), style)
-
-	return t.output != ""
+	t.Ms = int64(executionTimeMs)
+	t.FormattedMs = t.formatDuration(style)
+	return t.FormattedMs != ""
 }
 
 func (t *executiontime) string() string {
-	return t.output
+	return t.FormattedMs
 }
 
 func (t *executiontime) init(props *properties, env environmentInfo) {
@@ -66,103 +68,103 @@ func (t *executiontime) init(props *properties, env environmentInfo) {
 	t.env = env
 }
 
-func (t *executiontime) formatDuration(ms int64, style DurationStyle) string {
+func (t *executiontime) formatDuration(style DurationStyle) string {
 	switch style {
 	case Austin:
-		return t.formatDurationAustin(ms)
+		return t.formatDurationAustin()
 	case Roundrock:
-		return t.formatDurationRoundrock(ms)
+		return t.formatDurationRoundrock()
 	case Dallas:
-		return t.formatDurationDallas(ms)
+		return t.formatDurationDallas()
 	case Galveston:
-		return t.formatDurationGalveston(ms)
+		return t.formatDurationGalveston()
 	case Houston:
-		return t.formatDurationHouston(ms)
+		return t.formatDurationHouston()
 	case Amarillo:
-		return t.formatDurationAmarillo(ms)
+		return t.formatDurationAmarillo()
 	case Round:
-		return t.formatDurationRound(ms)
+		return t.formatDurationRound()
 	default:
 		return fmt.Sprintf("Style: %s is not available", style)
 	}
 }
 
-func (t *executiontime) formatDurationAustin(ms int64) string {
-	if ms < second {
-		return fmt.Sprintf("%dms", ms%second)
+func (t *executiontime) formatDurationAustin() string {
+	if t.Ms < second {
+		return fmt.Sprintf("%dms", t.Ms%second)
 	}
 
-	seconds := float64(ms%minute) / second
+	seconds := float64(t.Ms%minute) / second
 	result := strconv.FormatFloat(seconds, 'f', -1, 64) + "s"
 
-	if ms >= minute {
-		result = fmt.Sprintf("%dm %s", ms/minute%secondsPerMinute, result)
+	if t.Ms >= minute {
+		result = fmt.Sprintf("%dm %s", t.Ms/minute%secondsPerMinute, result)
 	}
-	if ms >= hour {
-		result = fmt.Sprintf("%dh %s", ms/hour%hoursPerDay, result)
+	if t.Ms >= hour {
+		result = fmt.Sprintf("%dh %s", t.Ms/hour%hoursPerDay, result)
 	}
-	if ms >= day {
-		result = fmt.Sprintf("%dd %s", ms/day, result)
+	if t.Ms >= day {
+		result = fmt.Sprintf("%dd %s", t.Ms/day, result)
 	}
 	return result
 }
 
-func (t *executiontime) formatDurationRoundrock(ms int64) string {
-	result := fmt.Sprintf("%dms", ms%second)
-	if ms >= second {
-		result = fmt.Sprintf("%ds %s", ms/second%secondsPerMinute, result)
+func (t *executiontime) formatDurationRoundrock() string {
+	result := fmt.Sprintf("%dms", t.Ms%second)
+	if t.Ms >= second {
+		result = fmt.Sprintf("%ds %s", t.Ms/second%secondsPerMinute, result)
 	}
-	if ms >= minute {
-		result = fmt.Sprintf("%dm %s", ms/minute%minutesPerHour, result)
+	if t.Ms >= minute {
+		result = fmt.Sprintf("%dm %s", t.Ms/minute%minutesPerHour, result)
 	}
-	if ms >= hour {
-		result = fmt.Sprintf("%dh %s", ms/hour%hoursPerDay, result)
+	if t.Ms >= hour {
+		result = fmt.Sprintf("%dh %s", t.Ms/hour%hoursPerDay, result)
 	}
-	if ms >= day {
-		result = fmt.Sprintf("%dd %s", ms/day, result)
+	if t.Ms >= day {
+		result = fmt.Sprintf("%dd %s", t.Ms/day, result)
 	}
 	return result
 }
 
-func (t *executiontime) formatDurationDallas(ms int64) string {
-	seconds := float64(ms%minute) / second
+func (t *executiontime) formatDurationDallas() string {
+	seconds := float64(t.Ms%minute) / second
 	result := strconv.FormatFloat(seconds, 'f', -1, 64)
 
-	if ms >= minute {
-		result = fmt.Sprintf("%d:%s", ms/minute%minutesPerHour, result)
+	if t.Ms >= minute {
+		result = fmt.Sprintf("%d:%s", t.Ms/minute%minutesPerHour, result)
 	}
-	if ms >= hour {
-		result = fmt.Sprintf("%d:%s", ms/hour%hoursPerDay, result)
+	if t.Ms >= hour {
+		result = fmt.Sprintf("%d:%s", t.Ms/hour%hoursPerDay, result)
 	}
-	if ms >= day {
-		result = fmt.Sprintf("%d:%s", ms/day, result)
+	if t.Ms >= day {
+		result = fmt.Sprintf("%d:%s", t.Ms/day, result)
 	}
 	return result
 }
 
-func (t *executiontime) formatDurationGalveston(ms int64) string {
-	result := fmt.Sprintf("%02d:%02d:%02d", ms/hour, ms/minute%minutesPerHour, ms%minute/second)
+func (t *executiontime) formatDurationGalveston() string {
+	result := fmt.Sprintf("%02d:%02d:%02d", t.Ms/hour, t.Ms/minute%minutesPerHour, t.Ms%minute/second)
 	return result
 }
 
-func (t *executiontime) formatDurationHouston(ms int64) string {
+func (t *executiontime) formatDurationHouston() string {
 	milliseconds := ".0"
-	if ms%second > 0 {
+	if t.Ms%second > 0 {
 		// format milliseconds as a string with truncated trailing zeros
-		milliseconds = strconv.FormatFloat(float64(ms%second)/second, 'f', -1, 64)
+		milliseconds = strconv.FormatFloat(float64(t.Ms%second)/second, 'f', -1, 64)
 		// at this point milliseconds looks like "0.5". remove the leading "0"
 		milliseconds = milliseconds[1:]
 	}
 
-	result := fmt.Sprintf("%02d:%02d:%02d%s", ms/hour, ms/minute%minutesPerHour, ms%minute/second, milliseconds)
+	result := fmt.Sprintf("%02d:%02d:%02d%s", t.Ms/hour, t.Ms/minute%minutesPerHour, t.Ms%minute/second, milliseconds)
 	return result
 }
 
-func (t *executiontime) formatDurationAmarillo(ms int64) string {
+func (t *executiontime) formatDurationAmarillo() string {
 	// wholeNumber represents the value to the left of the decimal point (seconds)
-	wholeNumber := ms / second
+	wholeNumber := t.Ms / second
 	// decimalNumber represents the value to the right of the decimal point (milliseconds)
-	decimalNumber := float64(ms%second) / second
+	decimalNumber := float64(t.Ms%second) / second
 
 	// format wholeNumber as a string with thousands separators
 	printer := message.NewPrinter(lang.English)
@@ -180,27 +182,27 @@ func (t *executiontime) formatDurationAmarillo(ms int64) string {
 	return result
 }
 
-func (t *executiontime) formatDurationRound(ms int64) string {
+func (t *executiontime) formatDurationRound() string {
 	toRoundString := func(one, two int64, oneText, twoText string) string {
 		if two == 0 {
 			return fmt.Sprintf("%d%s", one, oneText)
 		}
 		return fmt.Sprintf("%d%s %d%s", one, oneText, two, twoText)
 	}
-	hours := ms / hour % hoursPerDay
-	if ms >= day {
-		return toRoundString(ms/day, hours, "d", "h")
+	hours := t.Ms / hour % hoursPerDay
+	if t.Ms >= day {
+		return toRoundString(t.Ms/day, hours, "d", "h")
 	}
-	minutes := ms / minute % secondsPerMinute
-	if ms >= hour {
+	minutes := t.Ms / minute % secondsPerMinute
+	if t.Ms >= hour {
 		return toRoundString(hours, minutes, "h", "m")
 	}
-	seconds := (ms % minute) / second
-	if ms >= minute {
+	seconds := (t.Ms % minute) / second
+	if t.Ms >= minute {
 		return toRoundString(minutes, seconds, "m", "s")
 	}
-	if ms >= second {
+	if t.Ms >= second {
 		return fmt.Sprintf("%ds", seconds)
 	}
-	return fmt.Sprintf("%dms", ms%second)
+	return fmt.Sprintf("%dms", t.Ms%second)
 }
diff --git a/src/segment_exit.go b/src/segment_exit.go
index 6cd9171d..2944523c 100644
--- a/src/segment_exit.go
+++ b/src/segment_exit.go
@@ -1,24 +1,14 @@
 package main
 
-import "fmt"
+import "strconv"
 
 type exit struct {
 	props *properties
 	env   environmentInfo
-}
 
-const (
-	// DisplayExitCode shows or hides the error code
-	DisplayExitCode Property = "display_exit_code"
-	// ErrorColor specify a different foreground color for the error text when using always_show = true
-	ErrorColor Property = "error_color"
-	// AlwaysNumeric shows error codes as numbers
-	AlwaysNumeric Property = "always_numeric"
-	// SuccessIcon displays when there's no error and AlwaysEnabled = true
-	SuccessIcon Property = "success_icon"
-	// ErrorIcon displays when there's an error
-	ErrorIcon Property = "error_icon"
-)
+	Code int
+	Text string
+}
 
 func (e *exit) enabled() bool {
 	if e.props.getBool(AlwaysEnabled, false) {
@@ -37,28 +27,26 @@ func (e *exit) init(props *properties, env environmentInfo) {
 }
 
 func (e *exit) getFormattedText() string {
-	exitCode := e.getMeaningFromExitCode()
-	colorBackground := e.props.getBool(ColorBackground, false)
-	if e.env.lastErrorCode() != 0 && !colorBackground {
-		e.props.foreground = e.props.getColor(ErrorColor, e.props.foreground)
+	e.Code = e.env.lastErrorCode()
+	e.Text = e.getMeaningFromExitCode()
+	segmentTemplate := e.props.getString(SegmentTemplate, "")
+	if len(segmentTemplate) == 0 {
+		return e.deprecatedString()
 	}
-	if e.env.lastErrorCode() != 0 && colorBackground {
-		e.props.background = e.props.getColor(ErrorColor, e.props.background)
+	template := &textTemplate{
+		Template: segmentTemplate,
+		Context:  e,
+		Env:      e.env,
 	}
-	if e.env.lastErrorCode() == 0 {
-		return e.props.getString(SuccessIcon, "")
+	text, err := template.render()
+	if err != nil {
+		return err.Error()
 	}
-	return fmt.Sprintf("%s%s", e.props.getString(ErrorIcon, ""), exitCode)
+	return text
 }
 
 func (e *exit) getMeaningFromExitCode() string {
-	if !e.props.getBool(DisplayExitCode, true) {
-		return ""
-	}
-	if e.props.getBool(AlwaysNumeric, false) {
-		return fmt.Sprintf("%d", e.env.lastErrorCode())
-	}
-	switch e.env.lastErrorCode() {
+	switch e.Code {
 	case 1:
 		return "ERROR"
 	case 2:
@@ -112,6 +100,6 @@ func (e *exit) getMeaningFromExitCode() string {
 	case 128 + 22:
 		return "SIGTTOU"
 	default:
-		return fmt.Sprintf("%d", e.env.lastErrorCode())
+		return strconv.Itoa(e.Code)
 	}
 }
diff --git a/src/segment_git.go b/src/segment_git.go
index 4b93eaf7..b312c9dc 100644
--- a/src/segment_git.go
+++ b/src/segment_git.go
@@ -206,7 +206,7 @@ func (g *git) string() string {
 	}
 	// legacy render string	if no template
 	// remove this for 6.0
-	return g.renderDeprecatedString(statusColorsEnabled)
+	return g.deprecatedString(statusColorsEnabled)
 }
 
 func (g *git) templateString(segmentTemplate string) string {
diff --git a/themes/agnoster.omp.json b/themes/agnoster.omp.json
index 82d128c3..844e1666 100644
--- a/themes/agnoster.omp.json
+++ b/themes/agnoster.omp.json
@@ -57,7 +57,10 @@
           "style": "powerline",
           "powerline_symbol": "\uE0B0",
           "foreground": "#ffffff",
-          "background": "#ff8080"
+          "background": "#ff8080",
+          "properties": {
+            "template": "{{ .Text }}"
+          }
         }
       ]
     }
diff --git a/themes/avit.omp.json b/themes/avit.omp.json
index af75edfa..d2316775 100644
--- a/themes/avit.omp.json
+++ b/themes/avit.omp.json
@@ -33,7 +33,8 @@
           "style": "plain",
           "foreground": "#C94A16",
           "properties": {
-            "prefix": "x"
+            "template": "x{{ .Text }}",
+            "prefix": ""
           }
         }
       ]
diff --git a/themes/blue-owl.omp.json b/themes/blue-owl.omp.json
index 88a80be2..eb5ff5e2 100644
--- a/themes/blue-owl.omp.json
+++ b/themes/blue-owl.omp.json
@@ -81,7 +81,8 @@
           "foreground": "#ffffff",
           "background": "#910000",
           "properties": {
-            "prefix": "<transparent> \uF12A</> "
+            "prefix": "<transparent> \uF12A</> ",
+            "template": "{{ .Text }}"
           }
         }
       ]
@@ -124,11 +125,11 @@
           "type": "exit",
           "style": "plain",
           "foreground": "#ffffff",
+          "foreground_templates": ["{{ if gt .Code 0 }}#ff0000{{ end }}"],
           "properties": {
-            "prefix": "\u276F",
-            "always_enabled": true,
-            "error_color": "#ff0000",
-            "display_exit_code": false
+            "template": "\u276F",
+            "prefix": "",
+            "always_enabled": true
           }
         }
       ]
diff --git a/themes/blueish.omp.json b/themes/blueish.omp.json
index 29dafacf..ff10404d 100644
--- a/themes/blueish.omp.json
+++ b/themes/blueish.omp.json
@@ -95,14 +95,12 @@
           "style": "diamond",
           "foreground": "#ffffff",
           "background": "#007800",
-          "leading_diamond": "<transparent, #007800>\uE0B0</>",
+          "background_templates": ["{{ if gt .Code 0 }}#f1184c{{ end }}"],
+          "leading_diamond": "<transparent,background>\uE0B0</>",
           "trailing_diamond": "\uE0b0",
           "properties": {
-            "display_exit_code": false,
-            "always_enabled": true,
-            "error_color": "#f1184c",
-            "color_background": true,
-            "prefix": " \ufc8d"
+            "template": "\ufc8d",
+            "always_enabled": true
           }
         }
       ]
diff --git a/themes/cinnamon.omp.json b/themes/cinnamon.omp.json
index 2e94ca5e..0deef5c0 100644
--- a/themes/cinnamon.omp.json
+++ b/themes/cinnamon.omp.json
@@ -52,12 +52,10 @@
             "trailing_diamond": "\uE0B4",
             "foreground": "#ffffff",
             "background": "#491515",
+            "background_templates": ["{{ if gt .Code 0 }}#f1184c{{ end }}"],
             "properties": {
-              "display_exit_code": false,
-              "always_enabled": true,
-              "error_color": "#f1184c",
-              "color_background": true,
-              "prefix": " \uF7d4"
+              "template": "\uF7d4",
+              "always_enabled": true
             }
           }
         ]
diff --git a/themes/craver.omp.json b/themes/craver.omp.json
index 50a9e55e..28abc79e 100644
--- a/themes/craver.omp.json
+++ b/themes/craver.omp.json
@@ -95,11 +95,9 @@
           "powerline_symbol": "\uE0B4",
           "foreground": "#242424",
           "background": "#33DD2D",
+          "background_templates": ["{{ if gt .Code 0 }}#f1184c{{ end }}"],
           "properties": {
-            "display_exit_code": false,
-            "color_background": true,
-            "error_color": "#f1184c",
-            "prefix": " \ufc8d"
+            "template": "\uF7d4"
           }
         }
       ]
diff --git a/themes/darkblood.omp.json b/themes/darkblood.omp.json
index e0fb02a4..3ea567b8 100644
--- a/themes/darkblood.omp.json
+++ b/themes/darkblood.omp.json
@@ -40,6 +40,7 @@
           "style": "plain",
           "foreground": "#ffffff",
           "properties": {
+            "template": "{{ .Text }}",
             "prefix": "<#CB4B16>[x</>",
             "postfix": "<#CB4B16>]</>"
           }
diff --git a/themes/emodipt.omp.json b/themes/emodipt.omp.json
index c7d13741..2f4b3a35 100644
--- a/themes/emodipt.omp.json
+++ b/themes/emodipt.omp.json
@@ -44,7 +44,8 @@
           "style": "plain",
           "foreground": "#C94A16",
           "properties": {
-            "prefix": "x"
+            "template": "x{{ .Text }}",
+            "prefix": ""
           }
         },
         {
diff --git a/themes/fish.omp.json b/themes/fish.omp.json
index 8d831c51..21d979dd 100644
--- a/themes/fish.omp.json
+++ b/themes/fish.omp.json
@@ -10,6 +10,7 @@
           "style": "plain",
           "foreground": "#ffffff",
           "properties": {
+            "template": "{{ .Text }}",
             "postfix": ""
           }
         },
diff --git a/themes/gmay.omp.json b/themes/gmay.omp.json
index e8e4c9b5..331c0aa0 100644
--- a/themes/gmay.omp.json
+++ b/themes/gmay.omp.json
@@ -75,14 +75,12 @@
           "style": "diamond",
           "foreground": "#ffffff",
           "background": "#2e9599",
-          "leading_diamond": "<transparent, #2e9599>\uE0B0</>",
+          "background_templates": ["{{ if gt .Code 0 }}#f1184c{{ end }}"],
+          "leading_diamond": "<transparent,background>\uE0B0</>",
           "trailing_diamond": "\uE0B4",
           "properties": {
-            "display_exit_code": false,
-            "always_enabled": true,
-            "error_color": "#f1184c",
-            "color_background": true,
-            "prefix": " \uFC0C"
+            "template": "\uF7d4",
+            "always_enabled": true
           }
         }
       ]
diff --git a/themes/honukai.omp.json b/themes/honukai.omp.json
index adcbda42..b7250344 100644
--- a/themes/honukai.omp.json
+++ b/themes/honukai.omp.json
@@ -76,7 +76,10 @@
         {
           "type": "exit",
           "style": "plain",
-          "foreground": "#CB4B16"
+          "foreground": "#CB4B16",
+          "properties": {
+            "template": "{{ .Text }}"
+          }
         },
         {
           "type": "text",
diff --git a/themes/iterm2.omp.json b/themes/iterm2.omp.json
index 00fb7b9a..7c4d1580 100644
--- a/themes/iterm2.omp.json
+++ b/themes/iterm2.omp.json
@@ -69,12 +69,10 @@
           "powerline_symbol": "\uE0B0",
           "foreground": "#242424",
           "background": "#33DD2D",
+          "background_templates": ["{{ if gt .Code 0 }}#f1184c{{ end }}"],
           "properties": {
-            "display_exit_code": false,
-            "always_enabled": true,
-            "color_background": true,
-            "error_color": "#f1184c",
-            "prefix": " \ufc8d"
+            "template": "\ufc8d",
+            "always_enabled": true
           }
         }
       ]
diff --git a/themes/jandedobbeleer.omp.json b/themes/jandedobbeleer.omp.json
index e59a9670..2946fb13 100644
--- a/themes/jandedobbeleer.omp.json
+++ b/themes/jandedobbeleer.omp.json
@@ -162,15 +162,14 @@
           "type": "exit",
           "style": "diamond",
           "foreground": "#ffffff",
-          "background": "#2e9599",
+          "background": "#00897b",
+          "background_templates": ["{{ if gt .Code 0 }}#e91e63{{ end }}"],
           "leading_diamond": "",
-          "trailing_diamond": "",
+          "trailing_diamond": "\uE0B4",
           "properties": {
-            "display_exit_code": false,
             "always_enabled": true,
-            "error_color": "#f1184c",
-            "color_background": true,
-            "prefix": "<#83769c>\uE0B0</> "
+            "template": "\uE23A",
+            "prefix": "<parentBackground>\uE0B0</> "
           }
         }
       ]
diff --git a/themes/jblab_2021.omp.json b/themes/jblab_2021.omp.json
index 90230ded..2b528975 100644
--- a/themes/jblab_2021.omp.json
+++ b/themes/jblab_2021.omp.json
@@ -92,8 +92,9 @@
         {
           "background": "#910000",
           "foreground": "#ffffff",
-          "leading_diamond": "<transparent,#910000>\uE0B0</>",
+          "leading_diamond": "<transparent,background>\uE0B0</>",
           "properties": {
+            "template": "{{ .Text }}",
             "prefix": "<transparent> \uF12A</> "
           },
           "style": "diamond",
diff --git a/themes/jonnychipz.omp.json b/themes/jonnychipz.omp.json
index f31d5792..15c659bd 100644
--- a/themes/jonnychipz.omp.json
+++ b/themes/jonnychipz.omp.json
@@ -45,14 +45,13 @@
           "style": "diamond",
           "foreground": "#ffffff",
           "background": "#4707a8",
+          "background_templates": ["{{ if gt .Code 0 }}#f1184c{{ end }}"],
           "leading_diamond": "",
           "trailing_diamond": "\uE0B4",
           "properties": {
-            "display_exit_code": false,
+            "template": " \uE23A",
             "always_enabled": true,
-            "error_color": "#f1184c",
-            "color_background": true,
-            "prefix": "<transparent>\uE0B0</> \uE23A"
+            "prefix": "<transparent>\uE0B0</>"
           }
         }
       ]
diff --git a/themes/jv_sitecorian.omp.json b/themes/jv_sitecorian.omp.json
index 33d9ea4c..31228766 100644
--- a/themes/jv_sitecorian.omp.json
+++ b/themes/jv_sitecorian.omp.json
@@ -99,13 +99,10 @@
           "powerline_symbol": "\uE0B0",
           "foreground": "#ffffff",
           "background": "#4caf50",
-          "background_templates": [],
+          "background_templates": ["{{ if gt .Code 0 }}red{{ end }}"],
           "properties": {
             "always_enabled": true,
-            "success_icon": "\uf469 \u2665 ",
-            "color_background": true,
-            "error_icon": "\uf525 ",
-            "error_color": "red"
+            "template": "{{ if gt .Code 0 }}\uf525{{ else }}\uf469 \u2665{{ end }} "
           }
         }
       ]
diff --git a/themes/marcduiker.omp.json b/themes/marcduiker.omp.json
index 29ba3e97..05aa7dba 100644
--- a/themes/marcduiker.omp.json
+++ b/themes/marcduiker.omp.json
@@ -48,13 +48,11 @@
         {
           "background": "#0095e9",
           "foreground": "#ffffff",
-          "leading_diamond": "<transparent, #0095e9>\uE0B0</>",
+          "background_templates": ["{{ if gt .Code 0 }}#ff0044{{ end }}"],
+          "leading_diamond": "<transparent,background>\uE0B0</>",
           "properties": {
             "always_enabled": true,
-            "color_background": true,
-            "display_exit_code": false,
-            "error_color": "#ff0044",
-            "prefix": " "
+            "template": ""
           },
           "style": "diamond",
           "trailing_diamond": "",
diff --git a/themes/material.omp.json b/themes/material.omp.json
index 85d10253..0588c9f4 100644
--- a/themes/material.omp.json
+++ b/themes/material.omp.json
@@ -40,8 +40,9 @@
           "style": "plain",
           "foreground": "#DCB977",
           "properties": {
-            "prefix": "\uF119",
-            "display_exit_code": false
+            "template": "\uF119",
+            "prefix": " ",
+            "postfix": ""
           }
         },
         {
diff --git a/themes/microverse-power.omp.json b/themes/microverse-power.omp.json
index b076d26f..c9bdad78 100644
--- a/themes/microverse-power.omp.json
+++ b/themes/microverse-power.omp.json
@@ -77,12 +77,10 @@
           "powerline_symbol": "\uE0B0",
           "foreground": "#242424",
           "background": "#33DD2D",
+          "background_templates": ["{{ if gt .Code 0 }}#f1184c{{ end }}"],
           "properties": {
-            "display_exit_code": false,
             "always_enabled": true,
-            "color_background": true,
-            "error_color": "#f1184c",
-            "prefix": " \ufc8d"
+            "template": "\ufc8d"
           }
         }
       ]
diff --git a/themes/mojada.omp.json b/themes/mojada.omp.json
index b2e12351..87bdf67d 100644
--- a/themes/mojada.omp.json
+++ b/themes/mojada.omp.json
@@ -103,10 +103,8 @@
           "style": "plain",
           "foreground": "#ffffff",
           "properties": {
-            "display_exit_code": false,
             "always_enabled": true,
-            "success_icon": "<#00ff00>\uF633</>",
-            "error_icon": "<#ff0000>\uF659</>"
+            "template": "{{ if gt .Code 0 }}\uF659{{ else }}\uF633{{ end }}"
           }
         },
         {
diff --git a/themes/negligible.omp.json b/themes/negligible.omp.json
index b0e430b4..93dfb12b 100644
--- a/themes/negligible.omp.json
+++ b/themes/negligible.omp.json
@@ -107,11 +107,11 @@
           "type": "exit",
           "style": "powerline",
           "foreground": "lightGreen",
+          "foreground_templates": ["{{ if gt .Code 0 }}red{{ end }}"],
           "properties": {
-            "display_exit_code": false,
             "always_enabled": true,
-            "error_color": "red",
-            "prefix": "\u279c"
+            "template": "\u279c",
+            "prefix": ""
           }
         }
       ]
diff --git a/themes/night-owl.omp.json b/themes/night-owl.omp.json
index 7bbb7834..2cdc3fdc 100644
--- a/themes/night-owl.omp.json
+++ b/themes/night-owl.omp.json
@@ -290,11 +290,11 @@
           "type": "exit",
           "style": "plain",
           "foreground": "#22da6e",
+          "foreground_templates": ["{{ if gt .Code 0 }}#ef5350{{ end }}"],
           "properties": {
-            "prefix": "\ue285\ue285",
-            "display_exit_code": false,
-            "always_enabled": true,
-            "error_color": "#ef5350"
+            "template": "\ue285\ue285",
+            "prefix": "",
+            "always_enabled": true
           }
         }
       ]
diff --git a/themes/nu4a.omp.json b/themes/nu4a.omp.json
index 0a41a24f..70d07c2d 100644
--- a/themes/nu4a.omp.json
+++ b/themes/nu4a.omp.json
@@ -73,9 +73,7 @@
           "foreground": "#ffffff",
           "background": "#ff4040",
           "properties": {
-            "display_exit_code": false,
-            "always_enabled": false,
-            "prefix": " \ue70f"
+            "template": "\ue70f"
           }
         },
         {
diff --git a/themes/paradox.omp.json b/themes/paradox.omp.json
index 531aacea..5616d7bb 100644
--- a/themes/paradox.omp.json
+++ b/themes/paradox.omp.json
@@ -58,7 +58,7 @@
           "foreground": "#ffffff",
           "background": "#ff8080",
           "properties": {
-            "prefix": " \uE20F"
+            "template": "\uE20F"
           }
         }
       ]
diff --git a/themes/pararussel.omp.json b/themes/pararussel.omp.json
index 3f245610..93e71719 100644
--- a/themes/pararussel.omp.json
+++ b/themes/pararussel.omp.json
@@ -39,8 +39,8 @@
           "style": "plain",
           "foreground": "#DCB977",
           "properties": {
-            "prefix": "\uF119",
-            "display_exit_code": false
+            "template": "\uF119",
+            "prefix": " "
           }
         }
       ]
diff --git a/themes/plague.omp.json b/themes/plague.omp.json
index b75d9bb1..ecc7d6f9 100644
--- a/themes/plague.omp.json
+++ b/themes/plague.omp.json
@@ -78,13 +78,12 @@
           "style": "plain",
           "foreground": "#ffffff",
           "background": "#2e9599",
+          "background_templates": ["{{ if gt .Code 0 }}#f1184c{{ end }}"],
           "properties": {
-            "display_exit_code": false,
             "always_enabled": true,
-            "error_color": "#f1184c",
-            "color_background": true,
-            "prefix": "<transparent>\uE0B0</> \uE23A ",
-            "postfix": "<#2e9599,transparent>\uE0B4</>"
+            "template": " \uE23A ",
+            "prefix": "<transparent>\uE0B0</>",
+            "postfix": "<background,transparent>\uE0B4</>"
           }
         }
       ]
diff --git a/themes/powerlevel10k_classic.omp.json b/themes/powerlevel10k_classic.omp.json
index 28a9dfb0..3d12375b 100644
--- a/themes/powerlevel10k_classic.omp.json
+++ b/themes/powerlevel10k_classic.omp.json
@@ -88,11 +88,11 @@
           "type": "exit",
           "style": "plain",
           "foreground": "#D4E157",
+          "foreground_templates": ["{{ if gt .Code 0 }}#FF5252{{ end }}"],
           "properties": {
-            "prefix": "\u276F",
-            "always_enabled": true,
-            "error_color": "#FF5252",
-            "display_exit_code": false
+            "template": "\u276F",
+            "prefix": "",
+            "always_enabled": true
           }
         }
       ]
diff --git a/themes/powerlevel10k_modern.omp.json b/themes/powerlevel10k_modern.omp.json
index 018f0b4c..39d8f536 100644
--- a/themes/powerlevel10k_modern.omp.json
+++ b/themes/powerlevel10k_modern.omp.json
@@ -94,11 +94,11 @@
           "type": "exit",
           "style": "plain",
           "foreground": "#D4E157",
+          "foreground_templates": ["{{ if gt .Code 0 }}#FF5252{{ end }}"],
           "properties": {
-            "prefix": "\u276F",
-            "always_enabled": true,
-            "error_color": "#FF5252",
-            "display_exit_code": false
+            "template": "\u276F",
+            "prefix": "",
+            "always_enabled": true
           }
         }
       ]
diff --git a/themes/powerlevel10k_rainbow.omp.json b/themes/powerlevel10k_rainbow.omp.json
index 93c1c0d9..4923f4d6 100644
--- a/themes/powerlevel10k_rainbow.omp.json
+++ b/themes/powerlevel10k_rainbow.omp.json
@@ -170,12 +170,11 @@
           "invert_powerline": true,
           "foreground": "#d3d7cf",
           "background": "#000000",
+          "background_templates": ["{{ if gt .Code 0 }}#cc2222{{ end }}"],
           "properties": {
+            "prefix": " ",
             "always_enabled": true,
-            "display_exit_code": true,
-            "error_color": "#cc2222",
-            "color_background": true,
-            "success_icon": "✔"
+            "template": "{{ if gt .Code 0 }}{{ .Text }}{{ else }}✔{{ end }}"
           }
         },
         {
diff --git a/themes/powerline.omp.json b/themes/powerline.omp.json
index 935b9453..a63d3c78 100644
--- a/themes/powerline.omp.json
+++ b/themes/powerline.omp.json
@@ -52,7 +52,7 @@
           "foreground": "#ffffff",
           "background": "#ff8080",
           "properties": {
-            "prefix": "\uE20F"
+            "template": "\uE20F"
           }
         }
       ]
diff --git a/themes/pure.omp.json b/themes/pure.omp.json
index 4dcd3f64..17a0dc98 100644
--- a/themes/pure.omp.json
+++ b/themes/pure.omp.json
@@ -77,10 +77,10 @@
           "type": "exit",
           "style": "plain",
           "foreground": "#B48EAD",
+          "foreground_templates": ["{{ if gt .Code 0 }}#BF616A{{ end }}"],
           "properties": {
-            "prefix": "\u276f",
-            "display_exit_code": false,
-            "error_color": "#BF616A",
+            "template": "\u276f",
+            "prefix": "",
             "always_enabled": true
           }
         }
diff --git a/themes/robbyrussel.omp.json b/themes/robbyrussel.omp.json
index 3482f715..a6cfa52e 100644
--- a/themes/robbyrussel.omp.json
+++ b/themes/robbyrussel.omp.json
@@ -37,10 +37,11 @@
         {
           "type": "exit",
           "style": "plain",
-          "foreground": "#DCB977",
+          "foreground": "#BF616A",
           "properties": {
-            "prefix": "\u2717",
-            "display_exit_code": false
+            "template": "\u2717",
+            "prefix": " ",
+            "postfix": ""
           }
         }
       ]
diff --git a/themes/schema.json b/themes/schema.json
index 1bf448f1..252d81f4 100644
--- a/themes/schema.json
+++ b/themes/schema.json
@@ -447,6 +447,9 @@
             "properties": {
               "properties": {
                 "properties": {
+                  "template": {
+                    "$ref": "#/definitions/template"
+                  },
                   "var_name": {
                     "type": "string",
                     "title": "Variable Name",
@@ -470,30 +473,14 @@
             "properties": {
               "properties": {
                 "properties": {
-                  "display_exit_code": {
-                    "type": "boolean",
-                    "title": "Display Exit Code",
-                    "description": "Show or hide the exit code",
-                    "default": true
-                  },
                   "always_enabled": {
                     "type": "boolean",
                     "title": "Always Enabled",
                     "description": "Always show the status",
                     "default": false
                   },
-                  "color_background": {
-                    "type": "boolean",
-                    "title": "Color Background",
-                    "description": "Color the background or foreground",
-                    "default": false
-                  },
-                  "error_color": { "$ref": "#/definitions/color" },
-                  "always_numeric": {
-                    "type": "boolean",
-                    "title": "Always Numeric",
-                    "description": "Always display the exit code as a number",
-                    "default": false
+                  "template": {
+                    "$ref": "#/definitions/template"
                   }
                 }
               }
@@ -1607,6 +1594,9 @@
             "properties": {
               "properties": {
                 "properties": {
+                  "template": {
+                    "$ref": "#/definitions/template"
+                  },
                   "always_enabled": {
                     "type": "boolean",
                     "title": "Always Enabled",
diff --git a/themes/slim.omp.json b/themes/slim.omp.json
index 643ad1c8..620855db 100644
--- a/themes/slim.omp.json
+++ b/themes/slim.omp.json
@@ -207,13 +207,10 @@
           "type": "exit",
           "style": "plain",
           "foreground": "#9FD356",
+          "foreground_templates": ["{{ if gt .Code 0 }}#E84855{{ end }}"],
           "properties": {
-            "display_exit_code": true,
-            "always_numeric": true,
             "always_enabled": true,
-            "error_color": "#E84855",
-            "color_background": false,
-            "prefix": " \uf705 "
+            "template": "\uf705 {{ if gt .Code 0 }}{{ .Code }}{{ end }}"
           }
         }
       ]
diff --git a/themes/slimfat.omp.json b/themes/slimfat.omp.json
index ea5f6f91..07f1c2eb 100644
--- a/themes/slimfat.omp.json
+++ b/themes/slimfat.omp.json
@@ -203,13 +203,10 @@
           "type": "exit",
           "style": "plain",
           "foreground": "#9FD356",
+          "foreground_templates": ["{{ if gt .Code 0 }}#E84855{{ end }}"],
           "properties": {
-            "display_exit_code": true,
-            "always_numeric": true,
             "always_enabled": true,
-            "error_color": "#E84855",
-            "color_background": false,
-            "prefix": " \uf705 "
+            "template": "\uf705 {{ if gt .Code 0 }}{{ .Code }}{{ end }}"
           }
         }
       ]
diff --git a/themes/sorin.omp.json b/themes/sorin.omp.json
index e2d33d0f..79fd63fb 100644
--- a/themes/sorin.omp.json
+++ b/themes/sorin.omp.json
@@ -8,7 +8,10 @@
         {
           "type": "exit",
           "style": "plain",
-          "foreground": "#CB4B16"
+          "foreground": "#CB4B16",
+          "properties": {
+            "template": "{{ .Text }}"
+          }
         },
         {
           "type": "root",
diff --git a/themes/star.omp.json b/themes/star.omp.json
index c9031b77..92766b82 100644
--- a/themes/star.omp.json
+++ b/themes/star.omp.json
@@ -48,8 +48,8 @@
           "style": "plain",
           "foreground": "#C94A16",
           "properties": {
-            "prefix": "x",
-            "display_exit_code": false
+            "prefix": "",
+            "template": "x"
           }
         }
       ]
diff --git a/themes/stelbent.minimal.omp.json b/themes/stelbent.minimal.omp.json
index 3f867dd6..a969dcda 100644
--- a/themes/stelbent.minimal.omp.json
+++ b/themes/stelbent.minimal.omp.json
@@ -107,10 +107,7 @@
           "foreground": "#ffffff",
           "background": "#ff8080",
           "properties": {
-            "display_exit_code": false,
-            "prefix": " ",
-            "postfix": " ",
-            "error_icon": "error"
+            "template": "error"
           }
         }
       ]
diff --git a/themes/wopian.omp.json b/themes/wopian.omp.json
index ba801ced..d2bf0ad8 100644
--- a/themes/wopian.omp.json
+++ b/themes/wopian.omp.json
@@ -104,11 +104,11 @@
           "type": "exit",
           "style": "powerline",
           "foreground": "lightGreen",
+          "foreground_templates": ["{{ if gt .Code 0 }}red{{ end }}"],
           "properties": {
-            "display_exit_code": false,
             "always_enabled": true,
-            "error_color": "red",
-            "prefix": "\u279c"
+            "template": "\u279c",
+            "prefix": ""
           }
         }
       ]
diff --git a/themes/xtoys.omp.json b/themes/xtoys.omp.json
index 422fbfc7..451655f2 100644
--- a/themes/xtoys.omp.json
+++ b/themes/xtoys.omp.json
@@ -44,10 +44,12 @@
         {
           "type": "exit",
           "style": "plain",
+          "foreground": "#7FFFD4",
+          "foreground_templates": ["{{ if gt .Code 0 }}#E84855{{ end }}"],
           "properties": {
-            "display_exit_code": false,
             "always_enabled": true,
-            "prefix": "<#66CDAA>\u276F</><#76EEC6>\u276F</><#7FFFD4>\u276F</>"
+            "template": "<#66CDAA>\u276F</><#76EEC6>\u276F</><foreground>\u276F</>",
+            "prefix": ""
           }
         }
       ]
diff --git a/themes/ys.omp.json b/themes/ys.omp.json
index 69b10bfd..2fa1589e 100644
--- a/themes/ys.omp.json
+++ b/themes/ys.omp.json
@@ -80,7 +80,7 @@
           "style": "plain",
           "foreground": "red",
           "properties": {
-            "prefix": " C:",
+            "template": "C:{{ if gt .Code 0 }}{{ .Code }}{{ end }}",
             "always_numeric": true
           }
         }
diff --git a/themes/zash.omp.json b/themes/zash.omp.json
index 1d1993a7..da80cd24 100644
--- a/themes/zash.omp.json
+++ b/themes/zash.omp.json
@@ -50,8 +50,7 @@
           "style": "plain",
           "foreground": "#DCB977",
           "properties": {
-            "prefix": "\uF119",
-            "display_exit_code": false,
+            "template": "\uF119",
             "postfix": ""
           }
         }


Test patch:
diff --git a/src/segment_git_deprecated_test.go b/src/segment_deprecated_test.go
similarity index 81%
rename from src/segment_git_deprecated_test.go
rename to src/segment_deprecated_test.go
index 5bcfe5fe..eb9af49b 100644
--- a/src/segment_git_deprecated_test.go
+++ b/src/segment_deprecated_test.go
@@ -6,6 +6,8 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
+// GIT Segment
+
 func TestGetStatusDetailStringDefault(t *testing.T) {
 	expected := "icon +1"
 	status := &GitStatus{
@@ -257,3 +259,45 @@ func TestStatusColorsWithoutDisplayStatus(t *testing.T) {
 	g.string()
 	assert.Equal(t, expected, g.props.background)
 }
+
+// EXIT Segement
+
+func TestExitWriterDeprecatedString(t *testing.T) {
+	cases := []struct {
+		ExitCode        int
+		Expected        string
+		SuccessIcon     string
+		ErrorIcon       string
+		DisplayExitCode bool
+		AlwaysNumeric   bool
+	}{
+		{ExitCode: 129, Expected: "SIGHUP", DisplayExitCode: true},
+		{ExitCode: 5001, Expected: "5001", DisplayExitCode: true},
+		{ExitCode: 147, Expected: "SIGSTOP", DisplayExitCode: true},
+		{ExitCode: 147, Expected: "", DisplayExitCode: false},
+		{ExitCode: 147, Expected: "147", DisplayExitCode: true, AlwaysNumeric: true},
+		{ExitCode: 0, Expected: "wooopie", SuccessIcon: "wooopie"},
+		{ExitCode: 129, Expected: "err SIGHUP", ErrorIcon: "err ", DisplayExitCode: true},
+		{ExitCode: 129, Expected: "err", ErrorIcon: "err", DisplayExitCode: false},
+	}
+
+	for _, tc := range cases {
+		env := new(MockedEnvironment)
+		env.On("lastErrorCode", nil).Return(tc.ExitCode)
+		props := &properties{
+			foreground: "#111111",
+			background: "#ffffff",
+			values: map[Property]interface{}{
+				SuccessIcon:     tc.SuccessIcon,
+				ErrorIcon:       tc.ErrorIcon,
+				DisplayExitCode: tc.DisplayExitCode,
+				AlwaysNumeric:   tc.AlwaysNumeric,
+			},
+		}
+		e := &exit{
+			env:   env,
+			props: props,
+		}
+		assert.Equal(t, tc.Expected, e.string())
+	}
+}
diff --git a/src/segment_executiontime_test.go b/src/segment_executiontime_test.go
index ab069390..b2cee41d 100644
--- a/src/segment_executiontime_test.go
+++ b/src/segment_executiontime_test.go
@@ -64,7 +64,7 @@ func TestExecutionTimeWriterDuration(t *testing.T) {
 		env: env,
 	}
 	executionTime.enabled()
-	assert.Equal(t, expected, executionTime.output)
+	assert.Equal(t, expected, executionTime.FormattedMs)
 }
 
 func TestExecutionTimeWriterDuration2(t *testing.T) {
@@ -76,7 +76,7 @@ func TestExecutionTimeWriterDuration2(t *testing.T) {
 		env: env,
 	}
 	executionTime.enabled()
-	assert.Equal(t, expected, executionTime.output)
+	assert.Equal(t, expected, executionTime.FormattedMs)
 }
 
 func TestExecutionTimeFormatDurationAustin(t *testing.T) {
@@ -99,7 +99,8 @@ func TestExecutionTimeFormatDurationAustin(t *testing.T) {
 	for _, tc := range cases {
 		duration, _ := time.ParseDuration(tc.Input)
 		executionTime := &executiontime{}
-		output := executionTime.formatDurationAustin(duration.Milliseconds())
+		executionTime.Ms = duration.Milliseconds()
+		output := executionTime.formatDurationAustin()
 		assert.Equal(t, tc.Expected, output)
 	}
 }
@@ -124,7 +125,8 @@ func TestExecutionTimeFormatDurationRoundrock(t *testing.T) {
 	for _, tc := range cases {
 		duration, _ := time.ParseDuration(tc.Input)
 		executionTime := &executiontime{}
-		output := executionTime.formatDurationRoundrock(duration.Milliseconds())
+		executionTime.Ms = duration.Milliseconds()
+		output := executionTime.formatDurationRoundrock()
 		assert.Equal(t, tc.Expected, output)
 	}
 }
@@ -149,7 +151,8 @@ func TestExecutionTimeFormatDallas(t *testing.T) {
 	for _, tc := range cases {
 		duration, _ := time.ParseDuration(tc.Input)
 		executionTime := &executiontime{}
-		output := executionTime.formatDurationDallas(duration.Milliseconds())
+		executionTime.Ms = duration.Milliseconds()
+		output := executionTime.formatDurationDallas()
 		assert.Equal(t, tc.Expected, output)
 	}
 }
@@ -174,7 +177,8 @@ func TestExecutionTimeFormatGalveston(t *testing.T) {
 	for _, tc := range cases {
 		duration, _ := time.ParseDuration(tc.Input)
 		executionTime := &executiontime{}
-		output := executionTime.formatDurationGalveston(duration.Milliseconds())
+		executionTime.Ms = duration.Milliseconds()
+		output := executionTime.formatDurationGalveston()
 		assert.Equal(t, tc.Expected, output)
 	}
 }
@@ -199,7 +203,8 @@ func TestExecutionTimeFormatHouston(t *testing.T) {
 	for _, tc := range cases {
 		duration, _ := time.ParseDuration(tc.Input)
 		executionTime := &executiontime{}
-		output := executionTime.formatDurationHouston(duration.Milliseconds())
+		executionTime.Ms = duration.Milliseconds()
+		output := executionTime.formatDurationHouston()
 		assert.Equal(t, tc.Expected, output)
 	}
 }
@@ -224,7 +229,8 @@ func TestExecutionTimeFormatAmarillo(t *testing.T) {
 	for _, tc := range cases {
 		duration, _ := time.ParseDuration(tc.Input)
 		executionTime := &executiontime{}
-		output := executionTime.formatDurationAmarillo(duration.Milliseconds())
+		executionTime.Ms = duration.Milliseconds()
+		output := executionTime.formatDurationAmarillo()
 		assert.Equal(t, tc.Expected, output)
 	}
 }
@@ -249,7 +255,8 @@ func TestExecutionTimeFormatDurationRound(t *testing.T) {
 	for _, tc := range cases {
 		duration, _ := time.ParseDuration(tc.Input)
 		executionTime := &executiontime{}
-		output := executionTime.formatDurationRound(duration.Milliseconds())
+		executionTime.Ms = duration.Milliseconds()
+		output := executionTime.formatDurationRound()
 		assert.Equal(t, tc.Expected, output)
 	}
 }
diff --git a/src/segment_exit_test.go b/src/segment_exit_test.go
index e78dfa1b..04f6d690 100644
--- a/src/segment_exit_test.go
+++ b/src/segment_exit_test.go
@@ -26,46 +26,6 @@ func TestExitWriterEnabled(t *testing.T) {
 	}
 }
 
-func TestExitWriterFormattedText(t *testing.T) {
-	cases := []struct {
-		ExitCode        int
-		Expected        string
-		SuccessIcon     string
-		ErrorIcon       string
-		DisplayExitCode bool
-		AlwaysNumeric   bool
-	}{
-		{ExitCode: 129, Expected: "SIGHUP", DisplayExitCode: true},
-		{ExitCode: 5001, Expected: "5001", DisplayExitCode: true},
-		{ExitCode: 147, Expected: "SIGSTOP", DisplayExitCode: true},
-		{ExitCode: 147, Expected: "", DisplayExitCode: false},
-		{ExitCode: 147, Expected: "147", DisplayExitCode: true, AlwaysNumeric: true},
-		{ExitCode: 0, Expected: "wooopie", SuccessIcon: "wooopie"},
-		{ExitCode: 129, Expected: "err SIGHUP", ErrorIcon: "err ", DisplayExitCode: true},
-		{ExitCode: 129, Expected: "err", ErrorIcon: "err", DisplayExitCode: false},
-	}
-
-	for _, tc := range cases {
-		env := new(MockedEnvironment)
-		env.On("lastErrorCode", nil).Return(tc.ExitCode)
-		props := &properties{
-			foreground: "#111111",
-			background: "#ffffff",
-			values: map[Property]interface{}{
-				SuccessIcon:     tc.SuccessIcon,
-				ErrorIcon:       tc.ErrorIcon,
-				DisplayExitCode: tc.DisplayExitCode,
-				AlwaysNumeric:   tc.AlwaysNumeric,
-			},
-		}
-		e := &exit{
-			env:   env,
-			props: props,
-		}
-		assert.Equal(t, tc.Expected, e.getFormattedText())
-	}
-}
-
 func TestGetMeaningFromExitCode(t *testing.T) {
 	errorMap := make(map[int]string)
 	errorMap[1] = "ERROR"
@@ -97,26 +57,34 @@ func TestGetMeaningFromExitCode(t *testing.T) {
 	errorMap[151] = "151"
 	errorMap[7000] = "7000"
 	for exitcode, want := range errorMap {
-		env := new(MockedEnvironment)
-		env.On("lastErrorCode", nil).Return(exitcode)
-		e := &exit{
-			env: env,
-		}
+		e := &exit{}
+		e.Code = exitcode
 		assert.Equal(t, want, e.getMeaningFromExitCode())
 	}
 }
 
-func TestAlwaysNumericExitCode(t *testing.T) {
-	env := new(MockedEnvironment)
-	env.On("lastErrorCode", nil).Return(1)
-	props := &properties{
-		values: map[Property]interface{}{
-			AlwaysNumeric: true,
-		},
+func TestExitWriterTemplateString(t *testing.T) {
+	cases := []struct {
+		Case     string
+		ExitCode int
+		Expected string
+		Template string
+	}{
+		{Case: "Only code", ExitCode: 129, Expected: "129", Template: "{{ .Code }}"},
 	}
-	e := &exit{
-		env:   env,
-		props: props,
+
+	for _, tc := range cases {
+		env := new(MockedEnvironment)
+		env.On("lastErrorCode", nil).Return(tc.ExitCode)
+		props := &properties{
+			values: map[Property]interface{}{
+				SegmentTemplate: tc.Template,
+			},
+		}
+		e := &exit{
+			env:   env,
+			props: props,
+		}
+		assert.Equal(t, tc.Expected, e.string(), tc.Case)
 	}
-	assert.Equal(t, "1", e.getMeaningFromExitCode())
 }