Repository: JanDeDobbeleer/oh-my-posh
Pull request #1459 (2021-12-17 19:55:22)

fix(kubectl): parse yaml instead of csv
### 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

Multiple issue closing time

<!---

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/faq.mdx b/docs/docs/faq.mdx
index d241b6db..50da4fbc 100644
--- a/docs/docs/faq.mdx
+++ b/docs/docs/faq.mdx
@@ -138,6 +138,47 @@ To solely rely on Oh My Posh to set the prompt, you can configure the follwing s
 conda config --set changeps1 False
 ```
 
+### Python venv: Prompt is changed to display the environment name
+Upon activation, virtual environments created with `venv` change the prompt to add the activated environment's name.
+To disable this behaviour, set `VIRTUAL_ENV_DISABLE_PROMPT` environment variable to `1` on your system. Example commands to run, with probable file locations you'll have to put them in for auto-loading:
+
+Note: Tilde (~) in paths here refers to your user's home directory.
+
+<Tabs
+  defaultValue="powershell"
+  groupId="shell"
+  values={[
+    { label: 'powershell', value: 'powershell', },
+    { label: 'fish', value: 'fish', },
+    { label: 'others', value: 'others', },
+  ]
+}>
+<TabItem value="powershell">
+
+```powershell
+# powershell - ~/Documents/WindowsPowerShell/profile.ps1
+$env:VIRTUAL_ENV_DISABLE_PROMPT=1
+```
+
+</TabItem>
+<TabItem value="fish">
+
+```fish
+#fish - ~/.config/fish/config.fish
+set -x VIRTUAL_ENV_DISABLE_PROMPT 1
+```
+
+</TabItem>
+<TabItem value="others">
+
+```bash
+# bash, zsh - ~/bashrc or ~/.zprofile ~/.zshrc
+export VIRTUAL_ENV_DISABLE_PROMPT=1
+```
+
+</TabItem>
+</Tabs>
+
 [new-issue]: https://github.com/JanDeDobbeleer/oh-my-posh/issues/new/choose
 [latest]: https://github.com/JanDeDobbeleer/oh-my-posh/releases/latest
 [wt-glyph]: https://github.com/microsoft/terminal/issues/3546
diff --git a/docs/docs/install-linux.mdx b/docs/docs/install-linux.mdx
index c058272d..77139967 100644
--- a/docs/docs/install-linux.mdx
+++ b/docs/docs/install-linux.mdx
@@ -58,6 +58,7 @@ rm ~/.poshthemes/themes.zip
 
 The guides below assume you copied the theme called `jandedobbeleer.omp.json` to your user's `$HOME` folder.
 When you've downloaded the themes, you can find this one at `~/.poshthemes/jandedobbeleer.omp.json`.
+
 </TabItem>
 </Tabs>
 
diff --git a/docs/docs/install-shells.mdx b/docs/docs/install-shells.mdx
index 29f55727..f794d06b 100644
--- a/docs/docs/install-shells.mdx
+++ b/docs/docs/install-shells.mdx
@@ -70,7 +70,7 @@ Once added, restart cmd for the changes to take effect.
 Add the following to `~/.zshrc`:
 
 ```bash
-eval "$(oh-my-posh --init --shell zsh --config ~/.poshthemes/jandedobbeleer.omp.json)"
+eval "$(oh-my-posh --init --shell zsh --config ~/jandedobbeleer.omp.json)"
 ```
 
 Once added, reload your profile for the changes to take effect.
@@ -85,7 +85,7 @@ source ~/.zshrc
 Add the following to `~/.bashrc` (could be `~/.profile` or `~/.bash_profile` depending on your environment):
 
 ```bash
-eval "$(oh-my-posh --init --shell bash --config ~/.poshthemes/jandedobbeleer.omp.json)"
+eval "$(oh-my-posh --init --shell bash --config ~/jandedobbeleer.omp.json)"
 ```
 
 Once added, reload your profile for the changes to take effect.
@@ -110,7 +110,7 @@ It's advised to be on the latest version of fish. Versions below 3.1.2 have issu
 Initialize Oh My Posh in `~/.config/fish/config.fish`:
 
 ```bash
-oh-my-posh --init --shell fish --config ~/.poshthemes/jandedobbeleer.omp.json | source
+oh-my-posh --init --shell fish --config ~/jandedobbeleer.omp.json | source
 ```
 
 Once added, reload your config for the changes to take effect.
@@ -127,13 +127,13 @@ Set the prompt and restart nu shell:
 ### Nu < 0.32.0
 
 ```bash
-config set prompt  "= `{{$(oh-my-posh --config ~/.poshthemes/jandedobbeleer.omp.json | str collect)}}`"
+config set prompt  "= `{{$(oh-my-posh --config ~/jandedobbeleer.omp.json | str collect)}}`"
 ```
 
 ### Nu >= 0.32.0
 
 ```bash
-config set prompt  "(oh-my-posh --config ~/.poshthemes/jandedobbeleer.omp.json | str collect)"
+config set prompt  "(oh-my-posh --config ~/jandedobbeleer.omp.json | str collect)"
 ```
 
 Restart nu shell for the changes to take effect.
diff --git a/docs/docs/segment-path.md b/docs/docs/segment-path.md
index bd172016..fed6d349 100644
--- a/docs/docs/segment-path.md
+++ b/docs/docs/segment-path.md
@@ -37,8 +37,9 @@ Display the current path.
 - enable_hyperlink: `boolean` - displays an hyperlink for the path - defaults to `false`
 - mixed_threshold: `number` - the maximum length of a path segment that will be displayed when using `Mixed` -
   defaults to `4`
-- stack_count_enabled: `boolean` - displays the stack count when using pushd/popd - defaults to `false`
 - max_depth: `number` - maximum path depth to display before shortening when using `Agnoster Short` - defaults to `1`
+- template: `string` - A go [text/template][go-text-template] template extended with [sprig][sprig] utilizing the
+properties below. Defaults to `{{ .Path }}`
 
 ## Mapped Locations
 
@@ -123,3 +124,12 @@ starts with a symbol or icon.
 - `.config` will be shortened to `.c`
 - `__pycache__` will be shortened to `__p`
 - `➼ folder` will be shortened to `➼ f`
+
+## Template Properties
+
+- `.PWD`: `string` - the current directory (non styled)
+- `.Path`: `string` - the current directory (styled)
+- `.StackCount`: `int` - the stack count
+
+[go-text-template]: https://golang.org/pkg/text/template/
+[sprig]: https://masterminds.github.io/sprig/
diff --git a/src/segment_kubectl.go b/src/segment_kubectl.go
index d9f86653..71d29eaf 100644
--- a/src/segment_kubectl.go
+++ b/src/segment_kubectl.go
@@ -2,7 +2,6 @@ package main
 
 import (
 	"path/filepath"
-	"strings"
 
 	"gopkg.in/yaml.v3"
 )
@@ -14,23 +13,23 @@ type kubectl struct {
 	props   properties
 	env     environmentInfo
 	Context string
-	KubeConfigContext
-}
-
-type KubeConfigContext struct {
-	Cluster   string `yaml:"cluster"`
-	User      string `yaml:"user"`
-	Namespace string `yaml:"namespace"`
+	KubeContext
 }
 
 type KubeConfig struct {
 	CurrentContext string `yaml:"current-context"`
 	Contexts       []struct {
-		Context KubeConfigContext `yaml:"context"`
-		Name    string            `yaml:"name"`
+		Context *KubeContext `yaml:"context"`
+		Name    string       `yaml:"name"`
 	} `yaml:"contexts"`
 }
 
+type KubeContext struct {
+	Cluster   string `yaml:"cluster"`
+	User      string `yaml:"user"`
+	Namespace string `yaml:"namespace"`
+}
+
 func (k *kubectl) string() string {
 	segmentTemplate := k.props.getString(SegmentTemplate, "{{.Context}}{{if .Namespace}} :: {{.Namespace}}{{end}}")
 	template := &textTemplate{
@@ -65,7 +64,7 @@ func (k *kubectl) doParseKubeConfig() bool {
 	if len(kubeconfigs) == 0 {
 		kubeconfigs = []string{filepath.Join(k.env.homeDir(), ".kube/config")}
 	}
-	contexts := make(map[string]KubeConfigContext)
+	contexts := make(map[string]*KubeContext)
 	k.Context = ""
 	for _, kubeconfig := range kubeconfigs {
 		if len(kubeconfig) == 0 {
@@ -91,10 +90,13 @@ func (k *kubectl) doParseKubeConfig() bool {
 		}
 
 		context, exists := contexts[k.Context]
-		if exists {
-			k.KubeConfigContext = context
-			return true
+		if !exists {
+			continue
+		}
+		if context != nil {
+			k.KubeContext = *context
 		}
+		return true
 	}
 
 	displayError := k.props.getBool(DisplayError, false)
@@ -110,7 +112,7 @@ func (k *kubectl) doCallKubectl() bool {
 	if !k.env.hasCommand(cmd) {
 		return false
 	}
-	result, err := k.env.runCommand(cmd, "config", "view", "--minify", "--output", "jsonpath={..current-context},{..namespace},{..context.user},{..context.cluster}")
+	result, err := k.env.runCommand(cmd, "config", "view", "--output", "yaml", "--minify")
 	displayError := k.props.getBool(DisplayError, false)
 	if err != nil && displayError {
 		k.setError("KUBECTL ERR")
@@ -120,15 +122,16 @@ func (k *kubectl) doCallKubectl() bool {
 		return false
 	}
 
-	values := strings.Split(result, ",")
-	if len(values) < 4 {
+	var config KubeConfig
+	err = yaml.Unmarshal([]byte(result), &config)
+	if err != nil {
 		return false
 	}
-	k.Context = values[0]
-	k.Namespace = values[1]
-	k.User = values[2]
-	k.Cluster = values[3]
-	return len(k.Context) > 0
+	k.Context = config.CurrentContext
+	if len(config.Contexts) > 0 {
+		k.KubeContext = *config.Contexts[0].Context
+	}
+	return true
 }
 
 func (k *kubectl) setError(message string) {
diff --git a/src/segment_path.go b/src/segment_path.go
index 7e68c81b..19a2e30c 100644
--- a/src/segment_path.go
+++ b/src/segment_path.go
@@ -10,6 +10,10 @@ import (
 type path struct {
 	props properties
 	env   environmentInfo
+
+	PWD        string
+	Path       string
+	StackCount int
 }
 
 const (
@@ -45,8 +49,6 @@ const (
 	MappedLocations Property = "mapped_locations"
 	// MappedLocationsEnabled enables overriding certain locations with an icon
 	MappedLocationsEnabled Property = "mapped_locations_enabled"
-	// StackCountEnabled enables the stack count display
-	StackCountEnabled Property = "stack_count_enabled"
 	// MaxDepth Maximum path depth to display whithout shortening
 	MaxDepth Property = "max_depth"
 )
@@ -56,45 +58,51 @@ func (pt *path) enabled() bool {
 }
 
 func (pt *path) string() string {
-	cwd := pt.env.getcwd()
-	var formattedPath string
+	pt.PWD = pt.env.getcwd()
 	switch style := pt.props.getString(Style, Agnoster); style {
 	case Agnoster:
-		formattedPath = pt.getAgnosterPath()
+		pt.Path = pt.getAgnosterPath()
 	case AgnosterFull:
-		formattedPath = pt.getAgnosterFullPath()
+		pt.Path = pt.getAgnosterFullPath()
 	case AgnosterShort:
-		formattedPath = pt.getAgnosterShortPath()
+		pt.Path = pt.getAgnosterShortPath()
 	case Mixed:
-		formattedPath = pt.getMixedPath()
+		pt.Path = pt.getMixedPath()
 	case Letter:
-		formattedPath = pt.getLetterPath()
+		pt.Path = pt.getLetterPath()
 	case AgnosterLeft:
-		formattedPath = pt.getAgnosterLeftPath()
+		pt.Path = pt.getAgnosterLeftPath()
 	case Short:
 		// "short" is a duplicate of "full", just here for backwards compatibility
 		fallthrough
 	case Full:
-		formattedPath = pt.getFullPath()
+		pt.Path = pt.getFullPath()
 	case Folder:
-		formattedPath = pt.getFolderPath()
+		pt.Path = pt.getFolderPath()
 	default:
 		return fmt.Sprintf("Path style: %s is not available", style)
 	}
-	formattedPath = pt.formatWindowsDrive(formattedPath)
+	pt.Path = pt.formatWindowsDrive(pt.Path)
 	if pt.props.getBool(EnableHyperlink, false) {
 		// wsl check
 		if pt.env.isWsl() {
-			cwd, _ = pt.env.runCommand("wslpath", "-m", cwd)
+			pt.PWD, _ = pt.env.runCommand("wslpath", "-m", pt.PWD)
 		}
-		return fmt.Sprintf("[%s](file://%s)", formattedPath, cwd)
+		pt.Path = fmt.Sprintf("[%s](file://%s)", pt.Path, pt.PWD)
 	}
 
-	if pt.props.getBool(StackCountEnabled, false) && pt.env.stackCount() > 0 {
-		return fmt.Sprintf("%d %s", pt.env.stackCount(), formattedPath)
+	pt.StackCount = pt.env.stackCount()
+	segmentTemplate := pt.props.getString(SegmentTemplate, "{{ .Path }}")
+	template := &textTemplate{
+		Template: segmentTemplate,
+		Context:  pt,
+		Env:      pt.env,
 	}
-
-	return formattedPath
+	text, err := template.render()
+	if err != nil {
+		return err.Error()
+	}
+	return text
 }
 
 func (pt *path) formatWindowsDrive(pwd string) string {
diff --git a/themes/cloud-native-azure.omp.json b/themes/cloud-native-azure.omp.json
new file mode 100644
index 00000000..51984514
--- /dev/null
+++ b/themes/cloud-native-azure.omp.json
@@ -0,0 +1,164 @@
+{
+  "$schema": "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json",
+  "blocks": [
+    {
+      "alignment": "left",
+      "horizontal_offset": 0,
+      "segments": [
+        {
+          "type": "session",
+          "style": "diamond",
+          "background": "#c386f1",
+          "foreground": "#ffffff",
+          "leading_diamond": "\ue0b6",
+          "trailing_diamond": "\ue0b0"
+        },
+        {
+          "type": "path",
+          "style": "powerline",
+          "background": "#ff479c",
+          "foreground": "#ffffff",
+          "invert_powerline": false,
+          "powerline_symbol": "\ue0b0",
+          "properties": {
+            "prefix": " \uf07b  ",
+            "style": "folder"
+          }
+        },
+        {
+          "type": "git",
+          "style": "powerline",
+          "background": "#fffb38",
+          "foreground": "#193549",
+          "powerline_symbol": "\ue0b0",
+          "background_templates": [
+            "{{ if or (.Working.Changed) (.Staging.Changed) }}#FF9248{{ end }}",
+            "{{ if and (gt .Ahead 0) (gt .Behind 0) }}#ff4500{{ end }}",
+            "{{ if gt .Ahead 0 }}#B388FF{{ end }}",
+            "{{ if gt .Behind 0 }}#B388FF{{ end }}"
+          ],
+          "properties": {
+            "fetch_status": true,
+            "fetch_stash_count": true,
+            "fetch_upstream_icon": true,
+            "branch_max_length": 25,
+            "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 }}"
+          }
+        },
+        {
+          "type": "exit",
+          "style": "diamond",
+          "background": "#2e9599",
+          "foreground": "#ffffff",
+          "leading_diamond": "<transparent,background>\ue0b0</>",
+          "trailing_diamond": "\ue0b4",
+          "background_templates": ["{{ if gt .Code 0 }}#f1184c{{ end }}"],
+          "properties": {
+            "always_enabled": true,
+            "prefix": " \ue23a "
+          }
+        }
+      ],
+      "type": "prompt",
+      "vertical_offset": 0
+    },
+    {
+      "alignment": "right",
+      "horizontal_offset": 0,
+      "segments": [
+        {
+          "type": "shell",
+          "style": "plain",
+          "background": "#0077c2",
+          "foreground": "#ffffff",
+          "properties": {
+            "postfix": " <transparent,#0077c2>\ue0b2</>",
+            "prefix": "<#0077c2,transparent>\ue0b6</> \uf489 "
+          }
+        },
+        {
+          "type": "battery",
+          "style": "powerline",
+          "background": "#f36943",
+          "foreground": "#ffffff",
+          "invert_powerline": true,
+          "powerline_symbol": "",
+          "background_templates": [
+            "{{if eq \"Charging\" .State.String}}#40c4ff{{end}}",
+            "{{if eq \"Discharging\" .State.String}}#ff5722{{end}}",
+            "{{if eq \"Full\" .State.String}}#4caf50{{end}}"
+          ],
+          "properties": {
+            "charged_icon": "\ue22f ",
+            "charging_icon": "\uf583 ",
+            "color_background": true,
+            "discharging_icon": "\uf582 ",
+            "postfix": "\uf295 "
+          }
+        },
+        {
+          "type": "time",
+          "style": "diamond",
+          "background": "#2e9599",
+          "foreground": "#111111",
+          "invert_powerline": true,
+          "leading_diamond": "",
+          "trailing_diamond": "\ue0b4"
+        }
+      ],
+      "type": "prompt",
+      "vertical_offset": 0
+    },
+    {
+      "alignment": "left",
+      "horizontal_offset": 0,
+      "newline": true,
+      "segments": [
+        {
+          "type": "kubectl",
+          "style": "diamond",
+          "background": "#ebcc34",
+          "foreground": "#000000",
+          "leading_diamond": "\ue0b6",
+          "trailing_diamond": "",
+          "properties": {
+            "prefix": " \uefd31 ",
+            "template": "Kubernetes {{.Context}} cluster {{if .Namespace}}- {{.Namespace}} namespace{{end}}"
+          }
+        },
+        {
+          "type": "az",
+          "style": "powerline",
+          "background": "#9ec3f0",
+          "foreground": "#000000",
+          "powerline_symbol": "",
+          "properties": {
+            "prefix": " \ufd03 ",
+            "template": "Subscription {{ .Name }} ({{ if .EnvironmentName | contains \"AzureCloud\" }}{{ \"Global\" }}{{ else }}{{ .EnvironmentName }}{{ end }})"
+          }
+        }
+      ],
+      "type": "prompt",
+      "vertical_offset": 0
+    },
+    {
+      "alignment": "left",
+      "newline": true,
+      "segments": [
+        {
+          "type": "text",
+          "style": "plain",
+          "foreground": "#E06C75",
+          "properties": {
+            "text": "~"
+          }
+        }
+      ],
+      "type": "prompt"
+    }
+  ],
+  "console_title": true,
+  "console_title_style": "template",
+  "console_title_template": "{{ .Shell }} in {{ .Folder }}",
+  "final_space": true
+}
diff --git a/themes/schema.json b/themes/schema.json
index ec6c0f2d..b105dd60 100644
--- a/themes/schema.json
+++ b/themes/schema.json
@@ -1219,22 +1219,19 @@
                     "title": "Maximum Depth",
                     "description": "Maximum path depth to display whithout shortening",
                     "default": 1
-                  }
-                },
-                "mapped_locations_enabled": {
-                  "type": "boolean",
-                  "title": "Enable the Mapped Locations feature",
-                  "description": "Replace known locations in the path with the replacements before applying the style.",
-                  "default": true
-                },
-                "stack_count_enabled": {
-                  "type": "boolean",
-                  "title": "Show/hide stack count",
-                  "description": "Displays the stack count when using pushd/popd",
-                  "default": false
-                },
-                "enable_hyperlink": {
-                  "$ref": "#/definitions/enable_hyperlink"
+                  },
+                  "mapped_locations_enabled": {
+                    "type": "boolean",
+                    "title": "Enable the Mapped Locations feature",
+                    "description": "Replace known locations in the path with the replacements before applying the style.",
+                    "default": true
+                  },
+                  "enable_hyperlink": {
+                    "$ref": "#/definitions/enable_hyperlink"
+                  },
+                  "template": {
+                      "$ref": "#/definitions/template"
+                    }
                 }
               }
             }


Test patch:
diff --git a/src/segment_kubectl_test.go b/src/segment_kubectl_test.go
index 76a59458..34d69f4a 100644
--- a/src/segment_kubectl_test.go
+++ b/src/segment_kubectl_test.go
@@ -1,6 +1,8 @@
 package main
 
 import (
+	"fmt"
+	"io/ioutil"
 	"path/filepath"
 	"testing"
 
@@ -29,16 +31,16 @@ func TestKubectlSegment(t *testing.T) {
 		ExpectedString  string
 		Files           map[string]string
 	}{
-		{Case: "disabled", Template: standardTemplate, KubectlExists: false, Context: "aaa", Namespace: "bbb", ExpectedString: "", ExpectedEnabled: false},
 		{
-			Case:            "not enough arguments",
-			Template:        standardTemplate,
-			KubectlExists:   true,
-			Context:         "aaa",
-			Namespace:       "bbb",
-			ExpectedString:  "",
-			ExpectedEnabled: false,
+			Case:            "kubeconfig incomplete",
+			Template:        testKubectlAllInfoTemplate,
+			ParseKubeConfig: true,
+			Kubeconfig:      "currentcontextmarker" + lsep + "contextdefinitionincomplete",
+			Files:           testKubeConfigFiles,
+			ExpectedString:  "ctx ::  ::  :: ",
+			ExpectedEnabled: true,
 		},
+		{Case: "disabled", Template: standardTemplate, KubectlExists: false, Context: "aaa", Namespace: "bbb", ExpectedEnabled: false},
 		{
 			Case:            "all information",
 			Template:        testKubectlAllInfoTemplate,
@@ -50,7 +52,7 @@ func TestKubectlSegment(t *testing.T) {
 			ExpectedString:  "aaa :: bbb :: ccc :: ddd",
 			ExpectedEnabled: true,
 		},
-		{Case: "no namespace", Template: standardTemplate, KubectlExists: true, Context: "aaa", Namespace: "", ExpectedString: "", ExpectedEnabled: false},
+		{Case: "no namespace", Template: standardTemplate, KubectlExists: true, Context: "aaa", ExpectedString: "aaa", ExpectedEnabled: true},
 		{
 			Case:            "kubectl error",
 			Template:        standardTemplate,
@@ -100,30 +102,16 @@ func TestKubectlSegment(t *testing.T) {
 			ExpectedString:  "KUBECONFIG ERR :: KUBECONFIG ERR :: KUBECONFIG ERR :: KUBECONFIG ERR",
 			ExpectedEnabled: true,
 		},
-		{
-			Case:            "kubeconfig incomplete",
-			Template:        testKubectlAllInfoTemplate,
-			ParseKubeConfig: true,
-			Kubeconfig:      "currentcontextmarker" + lsep + "contextdefinitionincomplete",
-			Files:           testKubeConfigFiles,
-			ExpectedString:  "ctx ::  ::  :: ",
-			ExpectedEnabled: true,
-		},
 	}
 
 	for _, tc := range cases {
 		env := new(MockedEnvironment)
 		env.On("hasCommand", "kubectl").Return(tc.KubectlExists)
-		addCommaAndvalue := func(s string) string {
-			if s == "" {
-				return ""
-			}
-			return "," + s
+		var kubeconfig string
+		content, err := ioutil.ReadFile("./test/kubectl.yml")
+		if err == nil {
+			kubeconfig = fmt.Sprintf(string(content), tc.Cluster, tc.User, tc.Namespace, tc.Context)
 		}
-		kubectlOut := tc.Context
-		kubectlOut += addCommaAndvalue(tc.Namespace)
-		kubectlOut += addCommaAndvalue(tc.User)
-		kubectlOut += addCommaAndvalue(tc.Cluster)
 		var kubectlErr error
 		if tc.KubectlErr {
 			kubectlErr = &commandError{
@@ -131,9 +119,7 @@ func TestKubectlSegment(t *testing.T) {
 				exitCode: 1,
 			}
 		}
-		env.On("runCommand", "kubectl",
-			[]string{"config", "view", "--minify", "--output", "jsonpath={..current-context},{..namespace},{..context.user},{..context.cluster}"}).Return(kubectlOut, kubectlErr)
-
+		env.On("runCommand", "kubectl", []string{"config", "view", "--output", "yaml", "--minify"}).Return(kubeconfig, kubectlErr)
 		env.On("getenv", "KUBECONFIG").Return(tc.Kubeconfig)
 		for path, content := range tc.Files {
 			env.On("getFileContent", path).Return(content)
diff --git a/src/segment_path_test.go b/src/segment_path_test.go
index 92a50ccb..7b7051ba 100644
--- a/src/segment_path_test.go
+++ b/src/segment_path_test.go
@@ -387,6 +387,7 @@ func TestAgnosterPathStyles(t *testing.T) {
 		env.On("homeDir", nil).Return(tc.HomePath)
 		env.On("getcwd", nil).Return(tc.Pwd)
 		env.On("getRuntimeGOOS", nil).Return(tc.GOOS)
+		env.On("stackCount", nil).Return(0)
 		args := &args{
 			PSWD: &tc.Pswd,
 		}
@@ -397,6 +398,7 @@ func TestAgnosterPathStyles(t *testing.T) {
 				FolderSeparatorIcon: tc.FolderSeparatorIcon,
 				Style:               tc.Style,
 				MaxDepth:            tc.MaxDepth,
+				SegmentTemplate:     "{{ .Path }}",
 			},
 		}
 		got := path.string()
@@ -415,8 +417,10 @@ func TestGetFullPath(t *testing.T) {
 		GOOS                   string
 		PathSeparator          string
 		StackCount             int
-		StackCountEnabled      bool
+		Template               string
 	}{
+		{Style: Full, Pwd: "/usr/home/abc", Template: "{{ .Path }}", StackCount: 2, Expected: "~/abc"},
+
 		{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", Expected: "/"},
 		{Style: Full, Pwd: "", Expected: ""},
 		{Style: Full, Pwd: "/", Expected: "/"},
@@ -449,49 +453,49 @@ func TestGetFullPath(t *testing.T) {
 		{Style: Full, FolderSeparatorIcon: "\\", Pwd: "C:\\Users\\Jan", Expected: "C:\\Users\\Jan", PathSeparator: "\\", GOOS: windowsPlatform},
 
 		// StackCountEnabled=true and StackCount=2
-		{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", StackCountEnabled: true, StackCount: 2, Expected: "2 /"},
-		{Style: Full, Pwd: "", StackCountEnabled: true, StackCount: 2, Expected: "2 "},
-		{Style: Full, Pwd: "/", StackCountEnabled: true, StackCount: 2, Expected: "2 /"},
-		{Style: Full, Pwd: "/usr/home", StackCountEnabled: true, StackCount: 2, Expected: "2 ~"},
-		{Style: Full, Pwd: "/usr/home/abc", StackCountEnabled: true, StackCount: 2, Expected: "2 ~/abc"},
-		{Style: Full, Pwd: "/usr/home/abc", StackCountEnabled: true, StackCount: 2, Expected: "2 /usr/home/abc", DisableMappedLocations: true},
-		{Style: Full, Pwd: "/a/b/c/d", StackCountEnabled: true, StackCount: 2, Expected: "2 /a/b/c/d"},
+		{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", StackCount: 2, Expected: "2 /"},
+		{Style: Full, Pwd: "", StackCount: 2, Expected: "2 "},
+		{Style: Full, Pwd: "/", StackCount: 2, Expected: "2 /"},
+		{Style: Full, Pwd: "/usr/home", StackCount: 2, Expected: "2 ~"},
+		{Style: Full, Pwd: "/usr/home/abc", StackCount: 2, Expected: "2 ~/abc"},
+		{Style: Full, Pwd: "/usr/home/abc", StackCount: 2, Expected: "2 /usr/home/abc", DisableMappedLocations: true},
+		{Style: Full, Pwd: "/a/b/c/d", StackCount: 2, Expected: "2 /a/b/c/d"},
 
 		// StackCountEnabled=false and StackCount=2
-		{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", StackCountEnabled: false, StackCount: 2, Expected: "/"},
-		{Style: Full, Pwd: "", StackCountEnabled: false, StackCount: 2, Expected: ""},
-		{Style: Full, Pwd: "/", StackCountEnabled: false, StackCount: 2, Expected: "/"},
-		{Style: Full, Pwd: "/usr/home", StackCountEnabled: false, StackCount: 2, Expected: "~"},
-		{Style: Full, Pwd: "/usr/home/abc", StackCountEnabled: false, StackCount: 2, Expected: "~/abc"},
-		{Style: Full, Pwd: "/usr/home/abc", StackCountEnabled: false, StackCount: 2, Expected: "/usr/home/abc", DisableMappedLocations: true},
-		{Style: Full, Pwd: "/a/b/c/d", StackCountEnabled: false, StackCount: 2, Expected: "/a/b/c/d"},
+		{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", Template: "{{ .Path }}", StackCount: 2, Expected: "/"},
+		{Style: Full, Pwd: "", Template: "{{ .Path }}", StackCount: 2, Expected: ""},
+		{Style: Full, Pwd: "/", Template: "{{ .Path }}", StackCount: 2, Expected: "/"},
+		{Style: Full, Pwd: "/usr/home", Template: "{{ .Path }}", StackCount: 2, Expected: "~"},
+
+		{Style: Full, Pwd: "/usr/home/abc", Template: "{{ .Path }}", StackCount: 2, Expected: "/usr/home/abc", DisableMappedLocations: true},
+		{Style: Full, Pwd: "/a/b/c/d", Template: "{{ .Path }}", StackCount: 2, Expected: "/a/b/c/d"},
 
 		// StackCountEnabled=true and StackCount=0
-		{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", StackCountEnabled: true, StackCount: 0, Expected: "/"},
-		{Style: Full, Pwd: "", StackCountEnabled: true, StackCount: 0, Expected: ""},
-		{Style: Full, Pwd: "/", StackCountEnabled: true, StackCount: 0, Expected: "/"},
-		{Style: Full, Pwd: "/usr/home", StackCountEnabled: true, StackCount: 0, Expected: "~"},
-		{Style: Full, Pwd: "/usr/home/abc", StackCountEnabled: true, StackCount: 0, Expected: "~/abc"},
-		{Style: Full, Pwd: "/usr/home/abc", StackCountEnabled: true, StackCount: 0, Expected: "/usr/home/abc", DisableMappedLocations: true},
-		{Style: Full, Pwd: "/a/b/c/d", StackCountEnabled: true, StackCount: 0, Expected: "/a/b/c/d"},
+		{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", StackCount: 0, Expected: "/"},
+		{Style: Full, Pwd: "", StackCount: 0, Expected: ""},
+		{Style: Full, Pwd: "/", StackCount: 0, Expected: "/"},
+		{Style: Full, Pwd: "/usr/home", StackCount: 0, Expected: "~"},
+		{Style: Full, Pwd: "/usr/home/abc", StackCount: 0, Expected: "~/abc"},
+		{Style: Full, Pwd: "/usr/home/abc", StackCount: 0, Expected: "/usr/home/abc", DisableMappedLocations: true},
+		{Style: Full, Pwd: "/a/b/c/d", StackCount: 0, Expected: "/a/b/c/d"},
 
 		// StackCountEnabled=true and StackCount<0
-		{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", StackCountEnabled: true, StackCount: -1, Expected: "/"},
-		{Style: Full, Pwd: "", StackCountEnabled: true, StackCount: -1, Expected: ""},
-		{Style: Full, Pwd: "/", StackCountEnabled: true, StackCount: -1, Expected: "/"},
-		{Style: Full, Pwd: "/usr/home", StackCountEnabled: true, StackCount: -1, Expected: "~"},
-		{Style: Full, Pwd: "/usr/home/abc", StackCountEnabled: true, StackCount: -1, Expected: "~/abc"},
-		{Style: Full, Pwd: "/usr/home/abc", StackCountEnabled: true, StackCount: -1, Expected: "/usr/home/abc", DisableMappedLocations: true},
-		{Style: Full, Pwd: "/a/b/c/d", StackCountEnabled: true, StackCount: -1, Expected: "/a/b/c/d"},
+		{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", StackCount: -1, Expected: "/"},
+		{Style: Full, Pwd: "", StackCount: -1, Expected: ""},
+		{Style: Full, Pwd: "/", StackCount: -1, Expected: "/"},
+		{Style: Full, Pwd: "/usr/home", StackCount: -1, Expected: "~"},
+		{Style: Full, Pwd: "/usr/home/abc", StackCount: -1, Expected: "~/abc"},
+		{Style: Full, Pwd: "/usr/home/abc", StackCount: -1, Expected: "/usr/home/abc", DisableMappedLocations: true},
+		{Style: Full, Pwd: "/a/b/c/d", StackCount: -1, Expected: "/a/b/c/d"},
 
 		// StackCountEnabled=true and StackCount not set
-		{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", StackCountEnabled: true, Expected: "/"},
-		{Style: Full, Pwd: "", StackCountEnabled: true, Expected: ""},
-		{Style: Full, Pwd: "/", StackCountEnabled: true, Expected: "/"},
-		{Style: Full, Pwd: "/usr/home", StackCountEnabled: true, Expected: "~"},
-		{Style: Full, Pwd: "/usr/home/abc", StackCountEnabled: true, Expected: "~/abc"},
-		{Style: Full, Pwd: "/usr/home/abc", StackCountEnabled: true, Expected: "/usr/home/abc", DisableMappedLocations: true},
-		{Style: Full, Pwd: "/a/b/c/d", StackCountEnabled: true, Expected: "/a/b/c/d"},
+		{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", Expected: "/"},
+		{Style: Full, Pwd: "", Expected: ""},
+		{Style: Full, Pwd: "/", Expected: "/"},
+		{Style: Full, Pwd: "/usr/home", Expected: "~"},
+		{Style: Full, Pwd: "/usr/home/abc", Expected: "~/abc"},
+		{Style: Full, Pwd: "/usr/home/abc", Expected: "/usr/home/abc", DisableMappedLocations: true},
+		{Style: Full, Pwd: "/a/b/c/d", Expected: "/a/b/c/d"},
 	}
 
 	for _, tc := range cases {
@@ -508,9 +512,12 @@ func TestGetFullPath(t *testing.T) {
 			PSWD: &tc.Pswd,
 		}
 		env.On("getArgs", nil).Return(args)
+		if len(tc.Template) == 0 {
+			tc.Template = "{{ if gt .StackCount 0 }}{{ .StackCount }} {{ end }}{{ .Path }}"
+		}
 		var props properties = map[Property]interface{}{
-			Style:             tc.Style,
-			StackCountEnabled: tc.StackCountEnabled,
+			Style:           tc.Style,
+			SegmentTemplate: tc.Template,
 		}
 		if tc.FolderSeparatorIcon != "" {
 			props[FolderSeparatorIcon] = tc.FolderSeparatorIcon
diff --git a/src/test/kubectl.yml b/src/test/kubectl.yml
new file mode 100644
index 00000000..a32f409c
--- /dev/null
+++ b/src/test/kubectl.yml
@@ -0,0 +1,12 @@
+apiVersion: v1
+clusters: null
+contexts:
+  - context:
+      cluster: '%s'
+      user: '%s'
+      namespace: '%s'
+    name: jan
+current-context: '%s'
+kind: Config
+preferences: {}
+users: null