Repository: JanDeDobbeleer/oh-my-posh
Pull request #2195 (2022-04-29 21:15:13)

feat: iTerm2 integration for MacOS & Theme
### 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

iTerm2 offers a shell integration which puts a mark in the user's prompt. You may remember this from JanDeDobbeleer/oh-my-posh2#261.

I've tried to create a segment that will inject this mark only if the user 
A) is using iTerm
B) has properly set env ITERM2_SQUELCH_MARK=1
C) is using zsh, bash, or fish

My issue is that I don't know Go and I need just a little leg-up on completing my tests. It fails properly, but returns empty strings when I'm expecting responses. Can somebody take a really quick look at my segment/test and tell me which is to blame? I suspect that my test is malformed...

<!--TemplateBody-->

<!---

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


ehawman-rosenberg: I have tested this in a shell on Windows and MacOS and it works as expected. I'm further convinced that there's a problem with my test code.
JanDeDobbeleer: @ehawman-rosenberg I'll have a look at it and will fix. Hopefully this evening!

Patch:
diff --git a/docs/docs/contributing/segment.md b/docs/docs/contributing/segment.md
index 4fae3afa..394105c8 100644
--- a/docs/docs/contributing/segment.md
+++ b/docs/docs/contributing/segment.md
@@ -69,7 +69,7 @@ NEW SegmentType = "new"
 
 ## Add the SegmentType mapping
 
-Map your `SegmentType` to your Segment in the `mapSegmentWithWriter` function.
+Map your `SegmentType` to your Segment in the `mapSegmentWithWriter` function (respect the alphabetical order).
 
 ```go
 NEW: &New{},
diff --git a/docs/docs/segments/iterm.md b/docs/docs/segments/iterm.md
new file mode 100644
index 00000000..8a3c6ebd
--- /dev/null
+++ b/docs/docs/segments/iterm.md
@@ -0,0 +1,39 @@
+---
+id: iterm
+title: iTerm
+sidebar_label: iTerm
+---
+
+## What
+
+Inserts the iTerm2 shell integration prompt mark for zsh, bash, and fish.
+For more information, read the [shell integration page][int-page] on
+the developer's website.
+
+:::info
+You will need to set env var `ITERM2_SQUELCH_MARK = 1` prior to initiating Oh My Posh.
+:::
+
+## Sample Configuration
+
+```json
+{
+  "type": "iterm",
+  "style": "plain",
+  "foreground": "#80ffea",
+  "template": "{{ .PromptMark }}"
+}
+```
+
+## Template ([info][templates])
+
+:::note default template
+
+```template
+{{ .PromptMark }}
+```
+
+:::
+
+[templates]: /docs/configuration/templates
+[int-page]: https://iterm2.com/documentation-shell-integration.html
diff --git a/docs/sidebars.js b/docs/sidebars.js
index 147440e3..911e3240 100644
--- a/docs/sidebars.js
+++ b/docs/sidebars.js
@@ -71,6 +71,7 @@ module.exports = {
         "segments/golang",
         "segments/haskell",
         "segments/ipify",
+        "segments/iterm",
         "segments/java",
         "segments/julia",
         "segments/kotlin",
diff --git a/src/engine/segment.go b/src/engine/segment.go
index 0f3c18b2..9b0bdd5b 100644
--- a/src/engine/segment.go
+++ b/src/engine/segment.go
@@ -60,121 +60,123 @@ type SegmentStyle string
 type SegmentType string
 
 const (
+	// Plain writes it without ornaments
+	Plain SegmentStyle = "plain"
 	// Powerline writes it Powerline style
 	Powerline SegmentStyle = "powerline"
 	// Accordion writes it Powerline style but collapses the segment when disabled instead of hiding
 	Accordion SegmentStyle = "accordion"
-	// Plain writes it without ornaments
-	Plain SegmentStyle = "plain"
 	// Diamond writes the prompt shaped with a leading and trailing symbol
 	Diamond SegmentStyle = "diamond"
 
-	// SESSION represents the user info segment
-	SESSION SegmentType = "session"
-	// PATH represents the current path segment
-	PATH SegmentType = "path"
-	// GIT represents the git status and information
-	GIT SegmentType = "git"
-	// PLASTIC represents the plastic scm status and information
-	PLASTIC SegmentType = "plastic"
-	// EXIT writes the last exit code
-	EXIT SegmentType = "exit"
-	// PYTHON writes the virtual env name
-	PYTHON SegmentType = "python"
-	// ROOT writes root symbol
-	ROOT SegmentType = "root"
-	// TIME writes the current timestamp
-	TIME SegmentType = "time"
-	// TEXT writes a text
-	TEXT SegmentType = "text"
-	// CMD writes the output of a shell command
-	CMD SegmentType = "command"
-	// BATTERY writes the battery percentage
-	BATTERY SegmentType = "battery"
-	// SPOTIFY writes the SPOTIFY status for Mac
-	SPOTIFY SegmentType = "spotify"
-	// SHELL writes which shell we're currently in
-	SHELL SegmentType = "shell"
-	// NODE writes which node version is currently active
-	NODE SegmentType = "node"
-	// OS write os specific icon
-	OS SegmentType = "os"
-	// AZ writes the Azure subscription info we're currently in
-	AZ SegmentType = "az"
-	// KUBECTL writes the Kubernetes context we're currently in
-	KUBECTL SegmentType = "kubectl"
-	// DOTNET writes which dotnet version is currently active
-	DOTNET SegmentType = "dotnet"
-	// TERRAFORM writes the terraform workspace we're currently in
-	TERRAFORM SegmentType = "terraform"
-	// GOLANG writes which go version is currently active
-	GOLANG SegmentType = "go"
-	// JULIA writes which julia version is currently active
-	JULIA SegmentType = "julia"
-	// YTM writes YouTube Music information and status
-	YTM SegmentType = "ytm"
-	// EXECUTIONTIME writes the execution time of the last run command
-	EXECUTIONTIME SegmentType = "executiontime"
-	// RUBY writes which ruby version is currently active
-	RUBY SegmentType = "ruby"
+	// ANGULAR writes which angular cli version us currently active
+	ANGULAR SegmentType = "angular"
 	// AWS writes the active aws context
 	AWS SegmentType = "aws"
-	// JAVA writes the active java version
-	JAVA SegmentType = "java"
-	// POSHGIT writes the posh git prompt
-	POSHGIT SegmentType = "poshgit"
+	// AZ writes the Azure subscription info we're currently in
+	AZ SegmentType = "az"
 	// AZFUNC writes current AZ func version
 	AZFUNC SegmentType = "azfunc"
+	// BATTERY writes the battery percentage
+	BATTERY SegmentType = "battery"
+	// Brewfather segment
+	BREWFATHER SegmentType = "brewfather"
+	// cds (SAP CAP) version
+	CDS SegmentType = "cds"
+	// Cloud Foundry segment
+	CF SegmentType = "cf"
+	// Cloud Foundry logged in target
+	CFTARGET SegmentType = "cftarget"
+	// CMD writes the output of a shell command
+	CMD SegmentType = "command"
 	// CRYSTAL writes the active crystal version
 	CRYSTAL SegmentType = "crystal"
 	// DART writes the active dart version
 	DART SegmentType = "dart"
+	// DOTNET writes which dotnet version is currently active
+	DOTNET SegmentType = "dotnet"
+	// EXECUTIONTIME writes the execution time of the last run command
+	EXECUTIONTIME SegmentType = "executiontime"
+	// EXIT writes the last exit code
+	EXIT SegmentType = "exit"
+	// GIT represents the git status and information
+	GIT SegmentType = "git"
+	// GOLANG writes which go version is currently active
+	GOLANG SegmentType = "go"
+	// HASKELL segment
+	HASKELL SegmentType = "haskell"
+	// IPIFY segment
+	IPIFY SegmentType = "ipify"
+	// ITERM inserts the Shell Integration prompt mark on iTerm zsh/bash/fish
+	ITERM SegmentType = "iterm"
+	// JAVA writes the active java version
+	JAVA SegmentType = "java"
+	// JULIA writes which julia version is currently active
+	JULIA SegmentType = "julia"
+	// KOTLIN writes the active kotlin version
+	KOTLIN SegmentType = "kotlin"
+	// KUBECTL writes the Kubernetes context we're currently in
+	KUBECTL SegmentType = "kubectl"
 	// NBGV writes the nbgv version information
 	NBGV SegmentType = "nbgv"
-	// RUST writes the cargo version information if cargo.toml is present
-	RUST SegmentType = "rust"
+	// NIGHTSCOUT is an open source diabetes system
+	NIGHTSCOUT SegmentType = "nightscout"
+	// NODE writes which node version is currently active
+	NODE SegmentType = "node"
+	// npm version
+	NPM SegmentType = "npm"
+	// OS write os specific icon
+	OS SegmentType = "os"
 	// OWM writes the weather coming from openweatherdata
 	OWM SegmentType = "owm"
-	// SYSTEMINFO writes system information (memory, cpu, load)
-	SYSTEMINFO SegmentType = "sysinfo"
-	// ANGULAR writes which angular cli version us currently active
-	ANGULAR SegmentType = "angular"
+	// PATH represents the current path segment
+	PATH SegmentType = "path"
 	// PHP writes which php version is currently active
 	PHP SegmentType = "php"
-	// NIGHTSCOUT is an open source diabetes system
-	NIGHTSCOUT SegmentType = "nightscout"
+	// PLASTIC represents the plastic scm status and information
+	PLASTIC SegmentType = "plastic"
+	// POSHGIT writes the posh git prompt
+	POSHGIT SegmentType = "poshgit"
+	// Project version
+	PROJECT SegmentType = "project"
+	// PYTHON writes the virtual env name
+	PYTHON SegmentType = "python"
+	// R version
+	R SegmentType = "r"
+	// ROOT writes root symbol
+	ROOT SegmentType = "root"
+	// RUBY writes which ruby version is currently active
+	RUBY SegmentType = "ruby"
+	// RUST writes the cargo version information if cargo.toml is present
+	RUST SegmentType = "rust"
+	// SESSION represents the user info segment
+	SESSION SegmentType = "session"
+	// SHELL writes which shell we're currently in
+	SHELL SegmentType = "shell"
+	// SPOTIFY writes the SPOTIFY status for Mac
+	SPOTIFY SegmentType = "spotify"
 	// STRAVA is a sports activity tracker
 	STRAVA SegmentType = "strava"
+	// SWIFT writes the active swift version
+	SWIFT SegmentType = "swift"
+	// SYSTEMINFO writes system information (memory, cpu, load)
+	SYSTEMINFO SegmentType = "sysinfo"
+	// TERRAFORM writes the terraform workspace we're currently in
+	TERRAFORM SegmentType = "terraform"
+	// TEXT writes a text
+	TEXT SegmentType = "text"
+	// TIME writes the current timestamp
+	TIME SegmentType = "time"
+	// UI5 Tooling segment
+	UI5TOOLING SegmentType = "ui5tooling"
 	// WAKATIME writes tracked time spend in dev editors
 	WAKATIME SegmentType = "wakatime"
 	// WIFI writes details about the current WIFI connection
 	WIFI SegmentType = "wifi"
 	// WINREG queries the Windows registry.
 	WINREG SegmentType = "winreg"
-	// Brewfather segment
-	BREWFATHER SegmentType = "brewfather"
-	// IPIFY segment
-	IPIFY SegmentType = "ipify"
-	// HASKELL segment
-	HASKELL SegmentType = "haskell"
-	// UI5 Tooling segment
-	UI5TOOLING SegmentType = "ui5tooling"
-	// Cloud Foundry segment
-	CF SegmentType = "cf"
-	// Cloud Foundry logged in target
-	CFTARGET SegmentType = "cftarget"
-	// KOTLIN writes the active kotlin version
-	KOTLIN SegmentType = "kotlin"
-	// SWIFT writes the active swift version
-	SWIFT SegmentType = "swift"
-	// cds (SAP CAP) version
-	CDS SegmentType = "cds"
-	// npm version
-	NPM SegmentType = "npm"
-	// Project version
-	PROJECT SegmentType = "project"
-	// R version
-	R SegmentType = "r"
+	// YTM writes YouTube Music information and status
+	YTM SegmentType = "ytm"
 )
 
 func (segment *Segment) shouldIncludeFolder() bool {
@@ -242,59 +244,60 @@ func (segment *Segment) background() string {
 func (segment *Segment) mapSegmentWithWriter(env environment.Environment) error {
 	segment.env = env
 	functions := map[SegmentType]SegmentWriter{
-		PROJECT:       &segments.Project{},
+		ANGULAR:       &segments.Angular{},
+		AWS:           &segments.Aws{},
+		AZ:            &segments.Az{},
+		AZFUNC:        &segments.AzFunc{},
+		BATTERY:       &segments.Battery{},
+		BREWFATHER:    &segments.Brewfather{},
+		CDS:           &segments.Cds{},
+		CF:            &segments.Cf{},
+		CFTARGET:      &segments.CfTarget{},
+		CMD:           &segments.Cmd{},
+		CRYSTAL:       &segments.Crystal{},
+		DART:          &segments.Dart{},
+		DOTNET:        &segments.Dotnet{},
+		EXECUTIONTIME: &segments.Executiontime{},
+		EXIT:          &segments.Exit{},
+		GIT:           &segments.Git{},
+		GOLANG:        &segments.Golang{},
+		HASKELL:       &segments.Haskell{},
+		IPIFY:         &segments.IPify{},
+		ITERM:         &segments.ITerm{},
+		JAVA:          &segments.Java{},
+		JULIA:         &segments.Julia{},
+		KOTLIN:        &segments.Kotlin{},
+		KUBECTL:       &segments.Kubectl{},
+		NBGV:          &segments.Nbgv{},
+		NIGHTSCOUT:    &segments.Nightscout{},
+		NODE:          &segments.Node{},
 		NPM:           &segments.Npm{},
+		OS:            &segments.Os{},
 		OWM:           &segments.Owm{},
-		SESSION:       &segments.Session{},
 		PATH:          &segments.Path{},
-		GIT:           &segments.Git{},
+		PHP:           &segments.Php{},
 		PLASTIC:       &segments.Plastic{},
-		EXIT:          &segments.Exit{},
+		POSHGIT:       &segments.PoshGit{},
+		PROJECT:       &segments.Project{},
 		PYTHON:        &segments.Python{},
+		R:             &segments.R{},
 		ROOT:          &segments.Root{},
-		TEXT:          &segments.Text{},
-		TIME:          &segments.Time{},
-		CMD:           &segments.Cmd{},
-		BATTERY:       &segments.Battery{},
-		SPOTIFY:       &segments.Spotify{},
-		SHELL:         &segments.Shell{},
-		NODE:          &segments.Node{},
-		OS:            &segments.Os{},
-		AZ:            &segments.Az{},
-		KUBECTL:       &segments.Kubectl{},
-		DOTNET:        &segments.Dotnet{},
-		TERRAFORM:     &segments.Terraform{},
-		GOLANG:        &segments.Golang{},
-		JULIA:         &segments.Julia{},
-		YTM:           &segments.Ytm{},
-		EXECUTIONTIME: &segments.Executiontime{},
 		RUBY:          &segments.Ruby{},
-		AWS:           &segments.Aws{},
-		JAVA:          &segments.Java{},
-		POSHGIT:       &segments.PoshGit{},
-		AZFUNC:        &segments.AzFunc{},
-		CRYSTAL:       &segments.Crystal{},
-		DART:          &segments.Dart{},
-		NBGV:          &segments.Nbgv{},
 		RUST:          &segments.Rust{},
-		SYSTEMINFO:    &segments.SystemInfo{},
-		ANGULAR:       &segments.Angular{},
-		PHP:           &segments.Php{},
-		NIGHTSCOUT:    &segments.Nightscout{},
+		SESSION:       &segments.Session{},
+		SHELL:         &segments.Shell{},
+		SPOTIFY:       &segments.Spotify{},
 		STRAVA:        &segments.Strava{},
+		SWIFT:         &segments.Swift{},
+		SYSTEMINFO:    &segments.SystemInfo{},
+		TERRAFORM:     &segments.Terraform{},
+		TEXT:          &segments.Text{},
+		TIME:          &segments.Time{},
+		UI5TOOLING:    &segments.UI5Tooling{},
 		WAKATIME:      &segments.Wakatime{},
 		WIFI:          &segments.Wifi{},
 		WINREG:        &segments.WindowsRegistry{},
-		BREWFATHER:    &segments.Brewfather{},
-		IPIFY:         &segments.IPify{},
-		HASKELL:       &segments.Haskell{},
-		UI5TOOLING:    &segments.UI5Tooling{},
-		CF:            &segments.Cf{},
-		CFTARGET:      &segments.CfTarget{},
-		KOTLIN:        &segments.Kotlin{},
-		SWIFT:         &segments.Swift{},
-		CDS:           &segments.Cds{},
-		R:             &segments.R{},
+		YTM:           &segments.Ytm{},
 	}
 	if segment.Properties == nil {
 		segment.Properties = make(properties.Map)
diff --git a/src/segments/iterm.go b/src/segments/iterm.go
new file mode 100644
index 00000000..8f24695a
--- /dev/null
+++ b/src/segments/iterm.go
@@ -0,0 +1,59 @@
+package segments
+
+import (
+	"errors"
+	"oh-my-posh/environment"
+	"oh-my-posh/properties"
+)
+
+type ITerm struct {
+	props      properties.Properties
+	env        environment.Environment
+	PromptMark string
+}
+
+func (i *ITerm) Template() string {
+	return "{{ .PromptMark }}"
+}
+
+func (i *ITerm) Enabled() bool {
+	promptMark, err := i.getResult()
+	if err != nil {
+		return false
+	}
+	i.PromptMark = promptMark
+
+	return true
+}
+
+func (i *ITerm) getResult() (string, error) {
+	var response string
+	// First, check if we're using iTerm
+	if i.env.Getenv("TERM_PROGRAM") != "iTerm.app" {
+		return "", errors.New("Only works with iTerm")
+	}
+
+	// Check to ensure the user has squelched the default mark
+	if i.env.Getenv("ITERM2_SQUELCH_MARK") != "1" {
+		return "", errors.New("iTerm default mark enabled (set ITERM2_SQUELCH_MARK=1)")
+	}
+
+	// Now, set the mark string based on shell (or error out)
+	switch i.env.Shell() {
+	case "zsh":
+		response = `%{$(iterm2_prompt_mark)%}`
+	case "bash":
+		response = `\[$(iterm2_prompt_mark)\]`
+	case "fish":
+		response = `iterm2_prompt_mark`
+	default:
+		return "", errors.New("Shell isn't compatible with iTerm Shell Integration")
+	}
+
+	return response, nil
+}
+
+func (i *ITerm) Init(props properties.Properties, env environment.Environment) {
+	i.props = props
+	i.env = env
+}
diff --git a/themes/devious-diamonds.omp.json b/themes/devious-diamonds.omp.json
new file mode 100644
index 00000000..ba4d04b9
--- /dev/null
+++ b/themes/devious-diamonds.omp.json
@@ -0,0 +1,316 @@
+{
+  "$schema": "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json",
+  "blocks": [
+    {
+      "alignment": "left",
+      "newline": true,
+      "segments": [
+        {
+          "type": "iterm",
+          "style": "plain",
+          "foreground": "p:cyan",
+          "template": "{{ .PromptMark }}"
+        },
+        {
+          "foreground": "p:cyan",
+          "properties": {
+            "alpine": "\uf300",
+            "arch": "\uf303",
+            "centos": "\uf304",
+            "debian": "\uf306",
+            "elementary": "\uf309",
+            "fedora": "\uf30a",
+            "gentoo": "\uf30d",
+            "linux": "\ue712",
+            "macos": "\uf179",
+            "manjaro": "\uf312",
+            "mint": "\uf30f",
+            "opensuse": "\uf314",
+            "raspbian": "\uf315",
+            "ubuntu": "\uf31b",
+            "windows": "\uf871",
+            "wsl": "\ue712",
+            "wsl_separator": " on "
+          },
+          "style": "diamond",
+          "template": " {{ if .WSL }}WSL at {{ end }}{{.Icon}}\u2550",
+          "trailing_diamond": "<transparent,>\ue0b2</>",
+          "type": "os"
+        },
+        {
+          "background": "p:green",
+          "foreground": "p:dracula-black",
+          "leading_diamond": "\ue0b2",
+          "style": "diamond",
+          "template": " \uf489 {{ .Name }} ",
+          "type": "shell"
+        },
+        {
+          "background": "p:pink",
+          "foreground": "p:dracula-black",
+          "powerline_symbol": "\ue0bc",
+          "style": "powerline",
+          "template": "{{ if .SSHSession }}\uf817{{ end }}{{ .UserName }}@{{ .HostName }}",
+          "type": "session"
+        },
+        {
+          "background": "p:bright-cyan",
+          "foreground": "p:dracula-black",
+          "powerline_symbol": "\ue0bc",
+          "properties": {
+            "fetch_version": true
+          },
+          "style": "powerline",
+          "template": " \ue624 {{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }} ",
+          "type": "julia"
+        },
+        {
+          "background": "p:bright-cyan",
+          "foreground": "p:dracula-black",
+          "powerline_symbol": "\ue0bc",
+          "properties": {
+            "fetch_version": true
+          },
+          "style": "powerline",
+          "template": " \ue626 {{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }} ",
+          "type": "go"
+        },
+        {
+          "background": "p:bright-cyan",
+          "foreground": "p:dracula-white",
+          "powerline_symbol": "\ue0bc",
+          "style": "powerline",
+          "template": " \ue738 {{ .Full }}",
+          "type": "java"
+        },
+        {
+          "background": "p:bright-cyan",
+          "foreground": "p:dracula-white",
+          "powerline_symbol": "\ue0bc",
+          "style": "powerline",
+          "template": " \ue73d {{ .Full }} ",
+          "type": "php"
+        },
+        {
+          "background": "p:bright-green",
+          "foreground": "p:dracula-white",
+          "powerline_symbol": "\ue0bc",
+          "properties": {
+            "fetch_version": true
+          },
+          "style": "powerline",
+          "template": " \uf898 {{ if .PackageManagerIcon }}{{ .PackageManagerIcon }} {{ end }}{{ .Full }} ",
+          "type": "node"
+        },
+        {
+          "background": "p:bright-orange",
+          "foreground": "p:dracula-white",
+          "powerline_symbol": "\ue0bc",
+          "properties": {
+            "display_mode": "files",
+            "fetch_version": false
+          },
+          "style": "powerline",
+          "template": " \ufd03 {{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }} ",
+          "type": "azfunc"
+        },
+        {
+          "background": "p:bright-red",
+          "foreground": "p:dracula-white",
+          "powerline_symbol": "\ue0bc",
+          "properties": {
+            "display_mode": "files",
+            "fetch_version": true
+          },
+          "style": "powerline",
+          "template": " \ue791 {{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }} ",
+          "type": "ruby"
+        },
+        {
+          "background": "p:bright-yellow",
+          "foreground": "p:dracula-black",
+          "powerline_symbol": "\ue0bc",
+          "style": "powerline",
+          "template": " \ufd31 {{.Context}}{{if .Namespace}} :: {{.Namespace}}{{end}} ",
+          "type": "kubectl"
+        },
+        {
+          "background": "p:yellow",
+          "foreground": "p:dracula-black",
+          "powerline_symbol": "\ue0bc",
+          "properties": {
+            "display_mode": "files",
+            "fetch_virtual_env": false
+          },
+          "style": "powerline",
+          "template": " \ue235 {{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }} ",
+          "type": "python"
+        },
+        {
+          "background_templates": [
+            "{{if contains \"default\" .Profile}}#FFA400{{end}}",
+            "{{if contains \"jan\" .Profile}}#f1184c{{end}}"
+          ],
+          "foreground": "p:dracula-white",
+          "powerline_symbol": "\ue0bc",
+          "properties": {
+            "display_default": false
+          },
+          "style": "powerline",
+          "template": " \ue7ad {{ .Profile }}{{ if .Region }}@{{ .Region }}{{ end }} ",
+          "type": "aws"
+        },
+        {
+          "background": "p:orange",
+          "foreground": "p:dracula-black",
+          "powerline_symbol": "\ue0bc",
+          "properties": {
+            "time_format": "Mon | 15:04:05"
+          },
+          "style": "powerline",
+          "template": " {{ .CurrentDate | date .Format }} ",
+          "type": "time"
+        },
+        {
+          "background": "p:cyan",
+          "foreground": "p:dracula-black",
+          "properties": {
+            "style": "austin",
+            "threshold": 0
+          },
+          "style": "diamond",
+          "template": " {{ .FormattedMs }} ",
+          "trailing_diamond": "\ue0b0",
+          "type": "executiontime"
+        }
+      ],
+      "type": "prompt"
+    },
+    {
+      "alignment": "right",
+      "segments": [
+        {
+          "background": "p:pink",
+          "foreground": "p:dracula-black",
+          "leading_diamond": "\ue0b2",
+          "properties": {
+            "branch_icon": "\ue725 ",
+            "fetch_stash_count": true,
+            "fetch_status": true,
+            "fetch_upstream_icon": true,
+            "fetch_worktree_count": true
+          },
+          "style": "diamond",
+          "template": " {{ .UpstreamIcon }}{{ .HEAD }}{{ .BranchStatus }}{{ if .Working.Changed }} \uf044 {{ .Working.String }}{{ end }}{{ if and (.Working.Changed) (.Staging.Changed) }} |{{ end }}{{ if .Staging.Changed }} \uf046 {{ .Staging.String }}{{ end }}{{ if gt .StashCount 0 }} \uf692 {{ .StashCount }}{{ end }} ",
+          "trailing_diamond": "\ue0b0",
+          "type": "git"
+        }
+      ],
+      "type": "prompt"
+    },
+    {
+      "alignment": "left",
+      "newline": true,
+      "segments": [
+        {
+          "foreground": "p:cyan",
+          "style": "plain",
+          "template": " \u255a",
+          "type": "text"
+        },
+        {
+          "background": "p:purple",
+          "background_templates": ["{{ if gt .Code 0 }}#FF5555{{ end }}"],
+          "foreground": "p:dracula-black",
+          "leading_diamond": "\ue0b2",
+          "properties": {
+            "always_enabled": true
+          },
+          "style": "diamond",
+          "template": "{{ if gt .Code 0 }} \uf7d3 {{ else }} \uf004{{ end }}",
+          "type": "exit"
+        },
+        {
+          "background": "p:purple",
+          "foreground": "p:dracula-black",
+          "powerline_symbol": "\ue0bc",
+          "properties": {
+            "folder_icon": "\uf07b",
+            "folder_separator_icon": " \uf554 ",
+            "home_icon": "\uf7db",
+            "max_depth": 3,
+            "style": "agnoster_short"
+          },
+          "style": "powerline",
+          "template": " \ue5ff {{ .Path }}{{ if .Root }} {{ else }}\u200b{{ end }}",
+          "type": "path"
+        },
+        {
+          "background": "p:purple",
+          "background_templates": ["{{ if .Root }}p:red{{ end }}"],
+          "foreground": "p:dracula-white",
+          "properties": {
+            "root_icon": "\uf292"
+          },
+          "style": "diamond",
+          "template": "{{ if .Root }} \uf0e7 {{ else }}\u200b{{ end }}",
+          "trailing_diamond": "\ue0b0",
+          "type": "text"
+        }
+      ],
+      "type": "prompt"
+    },
+    {
+      "alignment": "left",
+      "newline": true,
+      "segments": [
+        {
+          "foreground": "p:cyan",
+          "foreground_templates": ["{{ if gt .Code 0 }}#ef5350{{ end }}"],
+          "properties": {
+            "always_enabled": true
+          },
+          "style": "plain",
+          "template": " ",
+          "type": "exit"
+        }
+      ],
+      "type": "prompt"
+    }
+  ],
+  "console_title_template": "{{ .Folder }}",
+  "osc99": true,
+  "palette": {
+    "black": "#1b1a23",
+    "comment": "#7970a9",
+    "cyan": "#80ffea",
+    "bright-cyan": "#99ffee",
+    "bright-green": "#a2ff99",
+    "bright-orange": "#ffaa99",
+    "bright-pink": "#ff99cc",
+    "bright-purple": "#ff99cc",
+    "bright-red": "#ffaa99",
+    "bright-yellow": "#ffff99",
+    "dracula-black": "#22212c",
+    "dracula-white": "#f8f8f2",
+    "green": "#8aff80",
+    "orange": "#ffca80",
+    "pink": "#ff80bf",
+    "purple": "#9580ff",
+    "red": "#ff9580",
+    "selection": "#454158",
+    "white": "#ffffff",
+    "yellow": "#ffff80"
+  },
+  "secondary_prompt": {
+    "background": "transparent",
+    "foreground": "p:dracula-white",
+    "template": "\ue285 "
+  },
+  "transient_prompt": {
+    "background": "transparent",
+    "foreground": "p:dracula-white",
+    "template": "\ue285{{ .Shell }}"
+  },
+  "version": 2
+}


Test patch:
diff --git a/src/segments/iterm_test.go b/src/segments/iterm_test.go
new file mode 100644
index 00000000..2142abea
--- /dev/null
+++ b/src/segments/iterm_test.go
@@ -0,0 +1,43 @@
+package segments
+
+import (
+	"oh-my-posh/mock"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestITermSegment(t *testing.T) {
+	cases := []struct {
+		Case             string
+		TermProgram      string
+		SquelchMark      string
+		Shell            string
+		Template         string
+		ExpectedString   string
+		ExpectedDisabled bool
+	}{
+		{Case: "not iterm", TermProgram: "", SquelchMark: "1", Shell: "zsh", ExpectedDisabled: true},
+		{Case: "default mark", TermProgram: "iTerm.app", Shell: "zsh", Template: "{{ .PromptMark }}", ExpectedDisabled: true},
+		{Case: "zsh", TermProgram: "iTerm.app", SquelchMark: "1", Shell: "zsh", Template: "{{ .PromptMark }}", ExpectedString: `%{$(iterm2_prompt_mark)%}`},
+		{Case: "bash", TermProgram: "iTerm.app", SquelchMark: "1", Shell: "bash", Template: "{{ .PromptMark }}", ExpectedString: `\[$(iterm2_prompt_mark)\]`},
+		{Case: "fish", TermProgram: "iTerm.app", SquelchMark: "1", Shell: "fish", Template: "{{ .PromptMark }}", ExpectedString: `iterm2_prompt_mark`},
+		{Case: "pwsh", TermProgram: "iTerm.app", SquelchMark: "1", Shell: "pwsh", Template: "{{ .PromptMark }}", ExpectedDisabled: true},
+		{Case: "gibberishshell", TermProgram: "iTerm.app", SquelchMark: "1", Shell: "jaserhuashf", Template: "{{ .PromptMark }}", ExpectedDisabled: true},
+	}
+
+	for _, tc := range cases {
+		env := new(mock.MockedEnvironment)
+		env.On("PathSeparator").Return("/")
+		env.On("Getenv", "TERM_PROGRAM").Return(tc.TermProgram)
+		env.On("Getenv", "ITERM2_SQUELCH_MARK").Return(tc.SquelchMark)
+		env.On("Shell").Return(tc.Shell)
+		iterm := &ITerm{
+			env: env,
+		}
+		assert.Equal(t, !tc.ExpectedDisabled, iterm.Enabled(), tc.Case)
+		if !tc.ExpectedDisabled {
+			assert.Equal(t, tc.ExpectedString, renderTemplate(env, tc.Template, iterm), tc.Case)
+		}
+	}
+}