Repository: JanDeDobbeleer/oh-my-posh
Pull request #5865 (2024-11-10 16:39:19)

feat(cache): make template cache available to all prompts
### Prerequisites

- [x] I have read and understood the [Contributing Guide][contributing-guide].
- [x] The commit message follows the [Conventional Commits][conventional-commits].
- [x] Tests for the changes have been added (for bug fixes or features).
- [x] The documentation has been added or updated (for bug fixes or features).

### Description

The template cache is frequently used during prompt rendering, so we don't need a lazy population. BTW, this will also thoroughly resolve the issue mentioned in #2885, which is not truly fixed in the PR #5863, since the [culprit][comment] is still the one that I found about two years ago. This time, I've left comments in code to prevent negligence in future maintenance.

[contributing-guide]: https://github.com/JanDeDobbeleer/oh-my-posh/blob/main/CONTRIBUTING.md
[conventional-commits]: https://www.conventionalcommits.org/en/v1.0.0/#summary
[comment]: https://github.com/JanDeDobbeleer/oh-my-posh/discussions/2885#discussioncomment-4497439

JanDeDobbeleer: @lewis-yeung you can install `fieldalignment` and fix the error using `fieldalignment --fix "./..."` on Windows.

I missed the comment from 2 years ago, otherwise I would've caught that as well indeed. The map changes don't necessarily need to be reverted, not sure if sync.Map is more performant, especially with it's weird way to convert to a simple map. But that could be gut feeling.

Patch:
diff --git a/src/cache/path.go b/src/cache/path.go
new file mode 100644
index 00000000..448cc0d5
--- /dev/null
+++ b/src/cache/path.go
@@ -0,0 +1,61 @@
+package cache
+
+import (
+	"os"
+	"path/filepath"
+	"time"
+
+	"github.com/jandedobbeleer/oh-my-posh/src/log"
+	"github.com/jandedobbeleer/oh-my-posh/src/runtime/path"
+)
+
+func Path() string {
+	defer log.Trace(time.Now())
+
+	returnOrBuildCachePath := func(input string) (string, bool) {
+		// validate root path
+		if _, err := os.Stat(input); err != nil {
+			return "", false
+		}
+
+		// validate oh-my-posh folder, if non existent, create it
+		cachePath := filepath.Join(input, "oh-my-posh")
+		if _, err := os.Stat(cachePath); err == nil {
+			return cachePath, true
+		}
+
+		if err := os.Mkdir(cachePath, 0o755); err != nil {
+			return "", false
+		}
+
+		return cachePath, true
+	}
+
+	// allow the user to set the cache path using OMP_CACHE_DIR
+	if cachePath, OK := returnOrBuildCachePath(os.Getenv("OMP_CACHE_DIR")); OK {
+		return cachePath
+	}
+
+	// WINDOWS cache folder, should not exist elsewhere
+	if cachePath, OK := returnOrBuildCachePath(os.Getenv("LOCALAPPDATA")); OK {
+		return cachePath
+	}
+
+	// get XDG_CACHE_HOME if present
+	if cachePath, OK := returnOrBuildCachePath(os.Getenv("XDG_CACHE_HOME")); OK {
+		return cachePath
+	}
+
+	// try to create the cache folder in the user's home directory if non-existent
+	dotCache := filepath.Join(path.Home(), ".cache")
+	if _, err := os.Stat(dotCache); err != nil {
+		_ = os.Mkdir(dotCache, 0o755)
+	}
+
+	// HOME cache folder
+	if cachePath, OK := returnOrBuildCachePath(dotCache); OK {
+		return cachePath
+	}
+
+	return path.Home()
+}
diff --git a/src/cache/template.go b/src/cache/template.go
index 27631f79..7906eff2 100644
--- a/src/cache/template.go
+++ b/src/cache/template.go
@@ -23,7 +23,6 @@ type Template struct {
 	Jobs          int
 	WSL           bool
 	Root          bool
-	Initialized   bool
 }
 
 func (t *Template) AddSegmentData(key string, value any) {
diff --git a/src/cli/cache.go b/src/cli/cache.go
index 91bc206c..40de0e1d 100644
--- a/src/cli/cache.go
+++ b/src/cli/cache.go
@@ -6,7 +6,6 @@ import (
 	"path/filepath"
 
 	"github.com/jandedobbeleer/oh-my-posh/src/cache"
-	"github.com/jandedobbeleer/oh-my-posh/src/runtime"
 
 	"github.com/spf13/cobra"
 )
@@ -34,18 +33,11 @@ You can do the following:
 			return
 		}
 
-		env := &runtime.Terminal{
-			CmdFlags: &runtime.Flags{},
-		}
-
-		env.Init()
-		defer env.Close()
-
 		switch args[0] {
 		case "path":
-			fmt.Println(env.CachePath())
+			fmt.Println(cache.Path())
 		case "clear":
-			deletedFiles, err := cache.Clear(env.CachePath(), true)
+			deletedFiles, err := cache.Clear(cache.Path(), true)
 			if err != nil {
 				fmt.Println(err)
 				return
@@ -55,7 +47,7 @@ You can do the following:
 				fmt.Println("removed cache file:", file)
 			}
 		case "edit":
-			cacheFilePath := filepath.Join(env.CachePath(), cache.FileName)
+			cacheFilePath := filepath.Join(cache.Path(), cache.FileName)
 			os.Exit(editFileWithEditor(cacheFilePath))
 		}
 	},
diff --git a/src/cli/config.go b/src/cli/config.go
index 2bca2323..27a2500d 100644
--- a/src/cli/config.go
+++ b/src/cli/config.go
@@ -5,7 +5,7 @@ import (
 	"os"
 	"time"
 
-	"github.com/jandedobbeleer/oh-my-posh/src/runtime"
+	"github.com/jandedobbeleer/oh-my-posh/src/config"
 
 	"github.com/spf13/cobra"
 )
@@ -31,13 +31,8 @@ You can export, migrate or edit the config (via the editor specified in the envi
 		}
 		switch args[0] {
 		case "edit":
-			env := &runtime.Terminal{
-				CmdFlags: &runtime.Flags{
-					Config: configFlag,
-				},
-			}
-			env.ResolveConfigPath()
-			os.Exit(editFileWithEditor(env.CmdFlags.Config))
+			path := config.Path((configFlag))
+			os.Exit(editFileWithEditor(path))
 		case "get":
 			// only here for backwards compatibility
 			fmt.Print(time.Now().UnixNano() / 1000000)
diff --git a/src/cli/config_export.go b/src/cli/config_export.go
index eaf534e9..6093402c 100644
--- a/src/cli/config_export.go
+++ b/src/cli/config_export.go
@@ -7,7 +7,8 @@ import (
 	"strings"
 
 	"github.com/jandedobbeleer/oh-my-posh/src/config"
-	"github.com/jandedobbeleer/oh-my-posh/src/runtime"
+	"github.com/jandedobbeleer/oh-my-posh/src/runtime/path"
+	"github.com/jandedobbeleer/oh-my-posh/src/shell"
 
 	"github.com/spf13/cobra"
 )
@@ -39,14 +40,7 @@ Exports the current config to "~/new_config.omp.json" (in JSON format).`,
 			os.Exit(2)
 		}
 
-		env := &runtime.Terminal{
-			CmdFlags: &runtime.Flags{
-				Config: configFlag,
-			},
-		}
-		env.Init()
-		defer env.Close()
-		cfg := config.Load(env)
+		cfg := config.Load(configFlag, shell.GENERIC, false)
 
 		validateExportFormat := func() {
 			format = strings.ToLower(format)
@@ -74,7 +68,7 @@ Exports the current config to "~/new_config.omp.json" (in JSON format).`,
 			return
 		}
 
-		cfg.Output = cleanOutputPath(output, env)
+		cfg.Output = cleanOutputPath(output)
 
 		if len(format) == 0 {
 			format = strings.TrimPrefix(filepath.Ext(output), ".")
@@ -85,16 +79,16 @@ Exports the current config to "~/new_config.omp.json" (in JSON format).`,
 	},
 }
 
-func cleanOutputPath(path string, env runtime.Environment) string {
-	path = runtime.ReplaceTildePrefixWithHomeDir(env, path)
+func cleanOutputPath(output string) string {
+	output = path.ReplaceTildePrefixWithHomeDir(output)
 
-	if !filepath.IsAbs(path) {
-		if absPath, err := filepath.Abs(path); err == nil {
-			path = absPath
+	if !filepath.IsAbs(output) {
+		if absPath, err := filepath.Abs(output); err == nil {
+			output = absPath
 		}
 	}
 
-	return filepath.Clean(path)
+	return filepath.Clean(output)
 }
 
 func init() {
diff --git a/src/cli/config_export_image.go b/src/cli/config_export_image.go
index 285e74fe..ceead33c 100644
--- a/src/cli/config_export_image.go
+++ b/src/cli/config_export_image.go
@@ -50,31 +50,31 @@ Exports the config to an image file ~/mytheme.png.
 Exports the config to an image file using customized output options.`,
 	Args: cobra.NoArgs,
 	Run: func(_ *cobra.Command, _ []string) {
-		env := &runtime.Terminal{
-			CmdFlags: &runtime.Flags{
-				Config:        configFlag,
-				Shell:         shell.GENERIC,
-				TerminalWidth: 150,
-			},
+		cfg := config.Load(configFlag, shell.GENERIC, false)
+
+		flags := &runtime.Flags{
+			Config:        configFlag,
+			Shell:         shell.GENERIC,
+			TerminalWidth: 150,
 		}
 
-		env.Init()
-		defer env.Close()
+		env := &runtime.Terminal{}
+		env.Init(flags)
 
-		template.Init(env)
+		template.Init(env, cfg.Var)
 
-		cfg := config.Load(env)
+		defer func() {
+			template.SaveCache()
+			env.Close()
+		}()
 
 		// set sane defaults for things we don't print
 		cfg.ConsoleTitleTemplate = ""
 		cfg.PWD = ""
 
-		// add variables to the environment
-		env.Var = cfg.Var
-
 		terminal.Init(shell.GENERIC)
 		terminal.BackgroundColor = cfg.TerminalBackground.ResolveTemplate()
-		terminal.Colors = cfg.MakeColors()
+		terminal.Colors = cfg.MakeColors(env)
 
 		eng := &prompt.Engine{
 			Config: cfg,
@@ -90,7 +90,7 @@ Exports the config to an image file using customized output options.`,
 		}
 
 		if outputImage != "" {
-			imageCreator.Path = cleanOutputPath(outputImage, env)
+			imageCreator.Path = cleanOutputPath(outputImage)
 		}
 
 		err := imageCreator.Init(env)
diff --git a/src/cli/config_migrate.go b/src/cli/config_migrate.go
index 83fec6e6..dbe2a612 100644
--- a/src/cli/config_migrate.go
+++ b/src/cli/config_migrate.go
@@ -5,6 +5,7 @@ import (
 
 	"github.com/jandedobbeleer/oh-my-posh/src/config"
 	"github.com/jandedobbeleer/oh-my-posh/src/runtime"
+	"github.com/jandedobbeleer/oh-my-posh/src/shell"
 
 	"github.com/spf13/cobra"
 )
@@ -39,15 +40,17 @@ Migrates the ~/myconfig.omp.json config file to TOML and writes the result to yo
 A backup of the current config can be found at ~/myconfig.omp.json.bak.`,
 	Args: cobra.NoArgs,
 	Run: func(_ *cobra.Command, _ []string) {
-		env := &runtime.Terminal{
-			CmdFlags: &runtime.Flags{
-				Config:  configFlag,
-				Migrate: true,
-			},
+		cfg := config.Load(configFlag, shell.GENERIC, true)
+
+		flags := &runtime.Flags{
+			Config:  configFlag,
+			Migrate: true,
 		}
-		env.Init()
+
+		env := &runtime.Terminal{}
+		env.Init(flags)
 		defer env.Close()
-		cfg := config.Load(env)
+
 		if write {
 			cfg.BackupAndMigrate()
 			return
diff --git a/src/cli/config_migrate_glyphs.go b/src/cli/config_migrate_glyphs.go
index e9340ecd..e93dae20 100644
--- a/src/cli/config_migrate_glyphs.go
+++ b/src/cli/config_migrate_glyphs.go
@@ -5,6 +5,7 @@ import (
 
 	"github.com/jandedobbeleer/oh-my-posh/src/config"
 	"github.com/jandedobbeleer/oh-my-posh/src/runtime"
+	"github.com/jandedobbeleer/oh-my-posh/src/shell"
 
 	"github.com/spf13/cobra"
 )
@@ -34,15 +35,15 @@ Migrates the ~/myconfig.omp.json config file's glyphs and writes the result to y
 A backup of the current config can be found at ~/myconfig.omp.json.bak.`,
 	Args: cobra.NoArgs,
 	Run: func(_ *cobra.Command, _ []string) {
-		env := &runtime.Terminal{
-			CmdFlags: &runtime.Flags{
-				Config: configFlag,
-			},
+		cfg := config.Load(configFlag, shell.GENERIC, false)
+
+		flags := &runtime.Flags{
+			Config: configFlag,
 		}
 
-		env.Init()
+		env := &runtime.Terminal{}
+		env.Init(flags)
 		defer env.Close()
-		cfg := config.Load(env)
 
 		cfg.MigrateGlyphs = true
 		if len(format) == 0 {
diff --git a/src/cli/debug.go b/src/cli/debug.go
index 7ef76f12..1001fdf2 100644
--- a/src/cli/debug.go
+++ b/src/cli/debug.go
@@ -36,29 +36,29 @@ func createDebugCmd() *cobra.Command {
 				return
 			}
 
-			env := &runtime.Terminal{
-				CmdFlags: &runtime.Flags{
-					Config: configFlag,
-					Debug:  true,
-					PWD:    pwd,
-					Shell:  args[0],
-					Plain:  plain,
-				},
-			}
+			cfg := config.Load(configFlag, args[0], false)
 
-			env.Init()
-			defer env.Close()
+			flags := &runtime.Flags{
+				Config: configFlag,
+				Debug:  true,
+				PWD:    pwd,
+				Shell:  args[0],
+				Plain:  plain,
+			}
 
-			template.Init(env)
+			env := &runtime.Terminal{}
+			env.Init(flags)
 
-			cfg := config.Load(env)
+			template.Init(env, cfg.Var)
 
-			// add variables to the environment
-			env.Var = cfg.Var
+			defer func() {
+				template.SaveCache()
+				env.Close()
+			}()
 
 			terminal.Init(args[0])
 			terminal.BackgroundColor = cfg.TerminalBackground.ResolveTemplate()
-			terminal.Colors = cfg.MakeColors()
+			terminal.Colors = cfg.MakeColors(env)
 			terminal.Plain = plain
 
 			eng := &prompt.Engine{
diff --git a/src/cli/enable.go b/src/cli/enable.go
index 3c481577..e56093a7 100644
--- a/src/cli/enable.go
+++ b/src/cli/enable.go
@@ -43,14 +43,13 @@ func init() {
 }
 
 func toggleFeature(cmd *cobra.Command, feature string, enable bool) {
-	env := &runtime.Terminal{
-		CmdFlags: &runtime.Flags{
-			Shell:     shellName,
-			SaveCache: true,
-		},
+	flags := &runtime.Flags{
+		Shell:     shellName,
+		SaveCache: true,
 	}
 
-	env.Init()
+	env := &runtime.Terminal{}
+	env.Init(flags)
 	defer env.Close()
 
 	if len(feature) == 0 {
diff --git a/src/cli/font.go b/src/cli/font.go
index ec21ecf1..cf1070ed 100644
--- a/src/cli/font.go
+++ b/src/cli/font.go
@@ -36,13 +36,12 @@ This command is used to install fonts and configure the font in your terminal.
 					fontName = args[1]
 				}
 
-				env := &runtime.Terminal{
-					CmdFlags: &runtime.Flags{
-						SaveCache: true,
-					},
+				flags := &runtime.Flags{
+					SaveCache: true,
 				}
 
-				env.Init()
+				env := &runtime.Terminal{}
+				env.Init(flags)
 				defer env.Close()
 
 				terminal.Init(env.Shell())
diff --git a/src/cli/get.go b/src/cli/get.go
index 5666f1af..cd97eaa4 100644
--- a/src/cli/get.go
+++ b/src/cli/get.go
@@ -45,12 +45,12 @@ This command is used to get the value of the following variables:
 			return
 		}
 
-		env := &runtime.Terminal{
-			CmdFlags: &runtime.Flags{
-				Shell: shellName,
-			},
+		flags := &runtime.Flags{
+			Shell: shellName,
 		}
-		env.Init()
+
+		env := &runtime.Terminal{}
+		env.Init(flags)
 		defer env.Close()
 
 		switch args[0] {
diff --git a/src/cli/init.go b/src/cli/init.go
index ef8763b9..66c6788a 100644
--- a/src/cli/init.go
+++ b/src/cli/init.go
@@ -70,23 +70,26 @@ func runInit(sh string) {
 		startTime = time.Now()
 	}
 
-	env := &runtime.Terminal{
-		CmdFlags: &runtime.Flags{
-			Shell:  sh,
-			Config: configFlag,
-			Strict: strict,
-			Debug:  debug,
-		},
+	cfg := config.Load(configFlag, sh, false)
+
+	flags := &runtime.Flags{
+		Shell:  sh,
+		Config: configFlag,
+		Strict: strict,
+		Debug:  debug,
 	}
 
-	env.Init()
-	defer env.Close()
+	env := &runtime.Terminal{}
+	env.Init(flags)
 
-	template.Init(env)
+	template.Init(env, cfg.Var)
 
-	cfg := config.Load(env)
+	defer func() {
+		template.SaveCache()
+		env.Close()
+	}()
 
-	feats := cfg.Features()
+	feats := cfg.Features(env)
 
 	var output string
 
diff --git a/src/cli/notice.go b/src/cli/notice.go
index c2be683b..58640b44 100644
--- a/src/cli/notice.go
+++ b/src/cli/notice.go
@@ -15,13 +15,12 @@ var noticeCmd = &cobra.Command{
 	Long:  "Print the upgrade notice when a new version is available.",
 	Args:  cobra.NoArgs,
 	Run: func(_ *cobra.Command, _ []string) {
-		env := &runtime.Terminal{
-			CmdFlags: &runtime.Flags{
-				SaveCache: true,
-			},
+		flags := &runtime.Flags{
+			SaveCache: true,
 		}
 
-		env.Init()
+		env := &runtime.Terminal{}
+		env.Init(flags)
 		defer env.Close()
 
 		if notice, hasNotice := upgrade.Notice(env, false); hasNotice {
diff --git a/src/cli/print.go b/src/cli/print.go
index ecafbde8..12deec26 100644
--- a/src/cli/print.go
+++ b/src/cli/print.go
@@ -5,6 +5,7 @@ import (
 
 	"github.com/jandedobbeleer/oh-my-posh/src/prompt"
 	"github.com/jandedobbeleer/oh-my-posh/src/runtime"
+	"github.com/jandedobbeleer/oh-my-posh/src/template"
 
 	"github.com/spf13/cobra"
 )
@@ -76,11 +77,16 @@ func createPrintCmd() *cobra.Command {
 				NoExitCode:    noStatus,
 				Column:        column,
 				JobCount:      jobCount,
+				IsPrimary:     args[0] == prompt.PRIMARY,
 				SaveCache:     saveCache,
 			}
 
 			eng := prompt.New(flags)
-			defer eng.Env.Close()
+
+			defer func() {
+				template.SaveCache()
+				eng.Env.Close()
+			}()
 
 			switch args[0] {
 			case prompt.DEBUG:
diff --git a/src/cli/toggle.go b/src/cli/toggle.go
index bc7c963a..425666f7 100644
--- a/src/cli/toggle.go
+++ b/src/cli/toggle.go
@@ -20,13 +20,12 @@ var toggleCmd = &cobra.Command{
 			return
 		}
 
-		env := &runtime.Terminal{
-			CmdFlags: &runtime.Flags{
-				SaveCache: true,
-			},
+		flags := &runtime.Flags{
+			SaveCache: true,
 		}
 
-		env.Init()
+		env := &runtime.Terminal{}
+		env.Init(flags)
 		defer env.Close()
 
 		togglesCache, _ := env.Session().Get(cache.TOGGLECACHE)
diff --git a/src/cli/upgrade.go b/src/cli/upgrade.go
index f646ba90..abeb6343 100644
--- a/src/cli/upgrade.go
+++ b/src/cli/upgrade.go
@@ -33,7 +33,7 @@ var upgradeCmd = &cobra.Command{
 		}
 
 		env := &runtime.Terminal{}
-		env.Init()
+		env.Init(nil)
 		defer env.Close()
 
 		terminal.Init(env.Shell())
diff --git a/src/config/config.go b/src/config/config.go
index 05af4b64..e01baaaa 100644
--- a/src/config/config.go
+++ b/src/config/config.go
@@ -22,7 +22,6 @@ const (
 
 // Config holds all the theme for rendering the prompt
 type Config struct {
-	env                     runtime.Environment
 	Palette                 color.Palette   `json:"palette,omitempty" toml:"palette,omitempty"`
 	DebugPrompt             *Segment        `json:"debug_prompt,omitempty" toml:"debug_prompt,omitempty"`
 	Var                     map[string]any  `json:"var,omitempty" toml:"var,omitempty"`
@@ -53,9 +52,9 @@ type Config struct {
 	FinalSpace              bool `json:"final_space,omitempty" toml:"final_space,omitempty"`
 }
 
-func (cfg *Config) MakeColors() color.String {
-	cacheDisabled := cfg.env.Getenv("OMP_CACHE_DISABLED") == "1"
-	return color.MakeColors(cfg.getPalette(), !cacheDisabled, cfg.AccentColor, cfg.env)
+func (cfg *Config) MakeColors(env runtime.Environment) color.String {
+	cacheDisabled := env.Getenv("OMP_CACHE_DISABLED") == "1"
+	return color.MakeColors(cfg.getPalette(), !cacheDisabled, cfg.AccentColor, env)
 }
 
 func (cfg *Config) getPalette() color.Palette {
@@ -88,7 +87,7 @@ func (cfg *Config) getPalette() color.Palette {
 	return palette
 }
 
-func (cfg *Config) Features() shell.Features {
+func (cfg *Config) Features(env runtime.Environment) shell.Features {
 	var feats shell.Features
 
 	if cfg.TransientPrompt != nil {
@@ -100,12 +99,12 @@ func (cfg *Config) Features() shell.Features {
 	}
 
 	autoUpgrade := cfg.AutoUpgrade
-	if _, OK := cfg.env.Cache().Get(AUTOUPGRADE); OK {
+	if _, OK := env.Cache().Get(AUTOUPGRADE); OK {
 		autoUpgrade = true
 	}
 
 	upgradeNotice := cfg.UpgradeNotice
-	if _, OK := cfg.env.Cache().Get(UPGRADENOTICE); OK {
+	if _, OK := env.Cache().Get(UPGRADENOTICE); OK {
 		upgradeNotice = true
 	}
 
@@ -125,7 +124,7 @@ func (cfg *Config) Features() shell.Features {
 		feats = append(feats, shell.Tooltips)
 	}
 
-	if cfg.env.Shell() == shell.FISH && cfg.ITermFeatures != nil && cfg.ITermFeatures.Contains(terminal.PromptMark) {
+	if env.Shell() == shell.FISH && cfg.ITermFeatures != nil && cfg.ITermFeatures.Contains(terminal.PromptMark) {
 		feats = append(feats, shell.PromptMark)
 	}
 
diff --git a/src/config/default.go b/src/config/default.go
index 3abee94a..83547260 100644
--- a/src/config/default.go
+++ b/src/config/default.go
@@ -3,11 +3,10 @@ package config
 import (
 	"github.com/jandedobbeleer/oh-my-posh/src/color"
 	"github.com/jandedobbeleer/oh-my-posh/src/properties"
-	"github.com/jandedobbeleer/oh-my-posh/src/runtime"
 	"github.com/jandedobbeleer/oh-my-posh/src/segments"
 )
 
-func Default(env runtime.Environment, warning bool) *Config {
+func Default(warning bool) *Config {
 	exitBackgroundTemplate := "{{ if gt .Code 0 }}p:red{{ end }}"
 	exitTemplate := " {{ if gt .Code 0 }}\uf00d{{ else }}\uf00c{{ end }} "
 
@@ -197,6 +196,5 @@ func Default(env runtime.Environment, warning bool) *Config {
 		},
 	}
 
-	cfg.env = env
 	return cfg
 }
diff --git a/src/runtime/config/download.go b/src/config/download.go
similarity index 100%
rename from src/runtime/config/download.go
rename to src/config/download.go
diff --git a/src/config/load.go b/src/config/load.go
index fd752486..f6c8dde6 100644
--- a/src/config/load.go
+++ b/src/config/load.go
@@ -3,13 +3,17 @@ package config
 import (
 	"bytes"
 	"fmt"
+	"os"
 	stdOS "os"
 	"path/filepath"
+	"runtime"
 	"strings"
 	"time"
 
 	"github.com/gookit/goutil/jsonutil"
-	"github.com/jandedobbeleer/oh-my-posh/src/runtime"
+	"github.com/jandedobbeleer/oh-my-posh/src/cache"
+	"github.com/jandedobbeleer/oh-my-posh/src/log"
+	"github.com/jandedobbeleer/oh-my-posh/src/runtime/path"
 	"github.com/jandedobbeleer/oh-my-posh/src/shell"
 
 	json "github.com/goccy/go-json"
@@ -18,11 +22,15 @@ import (
 )
 
 // LoadConfig returns the default configuration including possible user overrides
-func Load(env runtime.Environment) *Config {
-	cfg := loadConfig(env)
+func Load(configFile, sh string, migrate bool) *Config {
+	defer log.Trace(time.Now())
+
+	configFile = Path(configFile)
+
+	cfg := loadConfig(configFile)
 
 	// only migrate automatically when the switch isn't set
-	if !env.Flags().Migrate && cfg.Version < Version {
+	if !migrate && cfg.Version < Version {
 		cfg.BackupAndMigrate()
 	}
 
@@ -39,7 +47,7 @@ func Load(env runtime.Environment) *Config {
 	// elv   - broken OSC sequences
 	// xonsh - broken OSC sequences
 	// tcsh  - overall broken, FTCS_COMMAND_EXECUTED could be added to POSH_POSTCMD in the future
-	switch env.Shell() {
+	switch sh {
 	case shell.ELVISH, shell.XONSH, shell.TCSH, shell.NU:
 		cfg.ShellIntegration = false
 	}
@@ -47,24 +55,71 @@ func Load(env runtime.Environment) *Config {
 	return cfg
 }
 
-func loadConfig(env runtime.Environment) *Config {
-	defer env.Trace(time.Now())
-	configFile := env.Flags().Config
+func Path(config string) string {
+	defer log.Trace(time.Now())
+
+	// if the config flag is set, we'll use that over POSH_THEME
+	// in our internal shell logic, we'll always use the POSH_THEME
+	// due to not using --config to set the configuration
+	hasConfig := len(config) > 0
+
+	if poshTheme := os.Getenv("POSH_THEME"); len(poshTheme) > 0 && !hasConfig {
+		log.Debug("config set using POSH_THEME: %s", poshTheme)
+		return poshTheme
+	}
+
+	if len(config) == 0 {
+		return ""
+	}
+
+	if strings.HasPrefix(config, "https://") {
+		filePath, err := Download(cache.Path(), config)
+		if err != nil {
+			log.Error(err)
+			return ""
+		}
+
+		return filePath
+	}
+
+	isCygwin := func() bool {
+		return runtime.GOOS == "windows" && len(os.Getenv("OSTYPE")) > 0
+	}
+
+	// Cygwin path always needs the full path as we're on Windows but not really.
+	// Doing filepath actions will convert it to a Windows path and break the init script.
+	if isCygwin() {
+		log.Debug("cygwin detected, using full path for config")
+		return config
+	}
+
+	configFile := path.ReplaceTildePrefixWithHomeDir(config)
+
+	abs, err := filepath.Abs(configFile)
+	if err != nil {
+		log.Error(err)
+		return filepath.Clean(configFile)
+	}
+
+	return abs
+}
+
+func loadConfig(configFile string) *Config {
+	defer log.Trace(time.Now())
 
 	if len(configFile) == 0 {
-		env.Debug("no config file specified, using default")
-		return Default(env, false)
+		log.Debug("no config file specified, using default")
+		return Default(false)
 	}
 
 	var cfg Config
 	cfg.origin = configFile
 	cfg.Format = strings.TrimPrefix(filepath.Ext(configFile), ".")
-	cfg.env = env
 
 	data, err := stdOS.ReadFile(configFile)
 	if err != nil {
-		env.Error(err)
-		return Default(env, true)
+		log.Error(err)
+		return Default(true)
 	}
 
 	switch cfg.Format {
@@ -87,8 +142,8 @@ func loadConfig(env runtime.Environment) *Config {
 	}
 
 	if err != nil {
-		env.Error(err)
-		return Default(env, true)
+		log.Error(err)
+		return Default(true)
 	}
 
 	return &cfg
diff --git a/src/config/segment.go b/src/config/segment.go
index a21b4a38..bbc2b34a 100644
--- a/src/config/segment.go
+++ b/src/config/segment.go
@@ -121,7 +121,7 @@ func (segment *Segment) Execute(env runtime.Environment) {
 
 	if segment.writer.Enabled() {
 		segment.Enabled = true
-		env.TemplateCache().AddSegmentData(segment.Name(), segment.writer)
+		template.Cache.AddSegmentData(segment.Name(), segment.writer)
 	}
 }
 
@@ -134,13 +134,15 @@ func (segment *Segment) Render() {
 	segment.Enabled = len(strings.ReplaceAll(text, " ", "")) > 0
 
 	if !segment.Enabled {
-		segment.env.TemplateCache().RemoveSegmentData(segment.Name())
+		template.Cache.RemoveSegmentData(segment.Name())
 		return
 	}
 
 	segment.SetText(text)
 	segment.setCache()
-	segment.env.TemplateCache().AddSegmentData(segment.Name(), segment.writer)
+
+	// We do this to make `.Text` available for a cross-segment reference in an extra prompt.
+	template.Cache.AddSegmentData(segment.Name(), segment.writer)
 }
 
 func (segment *Segment) Text() string {
@@ -229,7 +231,7 @@ func (segment *Segment) restoreCache() bool {
 	}
 
 	segment.Enabled = true
-	segment.env.TemplateCache().AddSegmentData(segment.Name(), segment.writer)
+	template.Cache.AddSegmentData(segment.Name(), segment.writer)
 
 	return true
 }
diff --git a/src/image/image.go b/src/image/image.go
index 5dac876e..b97c4cb8 100644
--- a/src/image/image.go
+++ b/src/image/image.go
@@ -35,6 +35,7 @@ import (
 	"strings"
 	"unicode/utf8"
 
+	"github.com/jandedobbeleer/oh-my-posh/src/cache"
 	fontCLI "github.com/jandedobbeleer/oh-my-posh/src/font"
 	"github.com/jandedobbeleer/oh-my-posh/src/regex"
 	"github.com/jandedobbeleer/oh-my-posh/src/runtime"
@@ -218,7 +219,7 @@ func (ir *Renderer) setOutputPath(config string) {
 func (ir *Renderer) loadFonts() error {
 	var data []byte
 
-	fontCachePath := filepath.Join(ir.env.CachePath(), "Hack.zip")
+	fontCachePath := filepath.Join(cache.Path(), "Hack.zip")
 	if _, err := stdOS.Stat(fontCachePath); err == nil {
 		data, _ = stdOS.ReadFile(fontCachePath)
 	}
diff --git a/src/maps/concurrent.go b/src/maps/concurrent.go
index 7db17305..c5bb1537 100644
--- a/src/maps/concurrent.go
+++ b/src/maps/concurrent.go
@@ -1,58 +1,36 @@
 package maps
 
-import (
-	"sync"
-)
+import "sync"
 
 func NewConcurrent() *Concurrent {
-	return &Concurrent{
-		data: make(map[string]any),
-	}
+	var cm Concurrent
+	return &cm
 }
 
-type Concurrent struct {
-	data map[string]any
-	sync.RWMutex
-}
+type Concurrent sync.Map
 
 func (cm *Concurrent) Set(key string, value any) {
-	cm.Lock()
-	defer cm.Unlock()
-
-	if cm.data == nil {
-		cm.data = make(map[string]any)
-	}
-
-	cm.data[key] = value
+	(*sync.Map)(cm).Store(key, value)
 }
 
 func (cm *Concurrent) Get(key string) (any, bool) {
-	cm.RLock()
-	defer cm.RUnlock()
-
-	if cm.data == nil {
-		return nil, false
-	}
-
-	value, ok := cm.data[key]
-	return value, ok
+	return (*sync.Map)(cm).Load(key)
 }
 
 func (cm *Concurrent) Delete(key string) {
-	cm.Lock()
-	defer cm.Unlock()
-
-	delete(cm.data, key)
+	(*sync.Map)(cm).Delete(key)
 }
 
 func (cm *Concurrent) Contains(key string) bool {
-	_, ok := cm.Get(key)
+	_, ok := (*sync.Map)(cm).Load(key)
 	return ok
 }
 
 func (cm *Concurrent) ToSimple() Simple {
-	cm.RLock()
-	defer cm.RUnlock()
-
-	return cm.data
+	list := make(map[string]any)
+	(*sync.Map)(cm).Range(func(key, value any) bool {
+		list[key.(string)] = value
+		return true
+	})
+	return list
 }
diff --git a/src/maps/simple.go b/src/maps/simple.go
index a1f39c1a..696a4550 100644
--- a/src/maps/simple.go
+++ b/src/maps/simple.go
@@ -3,7 +3,9 @@ package maps
 type Simple map[string]any
 
 func (m Simple) ToConcurrent() *Concurrent {
-	return &Concurrent{
-		data: m,
+	var cm Concurrent
+	for k, v := range m {
+		cm.Set(k, v)
 	}
+	return &cm
 }
diff --git a/src/prompt/debug.go b/src/prompt/debug.go
index 94e2f55c..71e574d3 100644
--- a/src/prompt/debug.go
+++ b/src/prompt/debug.go
@@ -4,6 +4,7 @@ import (
 	"fmt"
 	"time"
 
+	"github.com/jandedobbeleer/oh-my-posh/src/cache"
 	"github.com/jandedobbeleer/oh-my-posh/src/config"
 	"github.com/jandedobbeleer/oh-my-posh/src/log"
 )
@@ -66,7 +67,7 @@ func (e *Engine) PrintDebug(startTime time.Time, version string) string {
 	}
 
 	e.write(fmt.Sprintf("\n%s %s\n", log.Text("Run duration:").Green().Bold().Plain(), time.Since(startTime)))
-	e.write(fmt.Sprintf("\n%s %s\n", log.Text("Cache path:").Green().Bold().Plain(), e.Env.CachePath()))
+	e.write(fmt.Sprintf("\n%s %s\n", log.Text("Cache path:").Green().Bold().Plain(), cache.Path()))
 
 	cfg := e.Env.Flags().Config
 	if len(cfg) == 0 {
diff --git a/src/prompt/engine.go b/src/prompt/engine.go
index 20d8c2e8..0647cebe 100644
--- a/src/prompt/engine.go
+++ b/src/prompt/engine.go
@@ -462,31 +462,22 @@ func (e *Engine) rectifyTerminalWidth(diff int) {
 // given configuration options, and is ready to print any
 // of the prompt components.
 func New(flags *runtime.Flags) *Engine {
-	env := &runtime.Terminal{
-		CmdFlags: flags,
-	}
-
-	env.Init()
-	cfg := config.Load(env)
+	cfg := config.Load(flags.Config, flags.Shell, flags.Migrate)
 
-	// load the template cache for extra prompts prior to
-	// rendering any template
-	if flags.Type == DEBUG ||
-		flags.Type == SECONDARY ||
-		flags.Type == TRANSIENT ||
-		flags.Type == VALID ||
-		flags.Type == ERROR {
-		env.LoadTemplateCache()
-	}
+	env := &runtime.Terminal{}
+	env.Init(flags)
 
-	template.Init(env)
+	template.Init(env, cfg.Var)
 
-	env.Var = cfg.Var
-	flags.HasTransient = cfg.TransientPrompt != nil
+	flags.HasExtra = cfg.DebugPrompt != nil ||
+		cfg.SecondaryPrompt != nil ||
+		cfg.TransientPrompt != nil ||
+		cfg.ValidLine != nil ||
+		cfg.ErrorLine != nil
 
 	terminal.Init(env.Shell())
 	terminal.BackgroundColor = cfg.TerminalBackground.ResolveTemplate()
-	terminal.Colors = cfg.MakeColors()
+	terminal.Colors = cfg.MakeColors(env)
 	terminal.Plain = flags.Plain
 
 	eng := &Engine{
diff --git a/src/runtime/environment.go b/src/runtime/environment.go
index bde949f5..50fdd5cd 100644
--- a/src/runtime/environment.go
+++ b/src/runtime/environment.go
@@ -33,43 +33,39 @@ type Environment interface {
 	Shell() string
 	Platform() string
 	StatusCodes() (int, string)
-	PathSeparator() string
 	HasFiles(pattern string) bool
 	HasFilesInDir(dir, pattern string) bool
 	HasFolder(folder string) bool
-	HasParentFilePath(path string, followSymlinks bool) (fileInfo *FileInfo, err error)
+	HasParentFilePath(input string, followSymlinks bool) (fileInfo *FileInfo, err error)
 	HasFileInParentDirs(pattern string, depth uint) bool
-	ResolveSymlink(path string) (string, error)
+	ResolveSymlink(input string) (string, error)
 	DirMatchesOneOf(dir string, regexes []string) bool
-	DirIsWritable(path string) bool
+	DirIsWritable(input string) bool
 	CommandPath(command string) string
 	HasCommand(command string) bool
 	FileContent(file string) string
-	LsDir(path string) []fs.DirEntry
+	LsDir(input string) []fs.DirEntry
 	RunCommand(command string, args ...string) (string, error)
 	RunShellCommand(shell, command string) string
 	ExecutionTime() float64
 	Flags() *Flags
 	BatteryState() (*battery.Info, error)
 	QueryWindowTitles(processName, windowTitleRegex string) (string, error)
-	WindowsRegistryKeyValue(path string) (*WindowsRegistryValue, error)
+	WindowsRegistryKeyValue(key string) (*WindowsRegistryValue, error)
 	HTTPRequest(url string, body io.Reader, timeout int, requestModifiers ...http.RequestModifier) ([]byte, error)
 	IsWsl() bool
 	IsWsl2() bool
 	IsCygwin() bool
 	StackCount() int
 	TerminalWidth() (int, error)
-	CachePath() string
 	Cache() cache.Cache
 	Session() cache.Cache
 	Close()
 	Logs() string
 	InWSLSharedDrive() bool
-	ConvertToLinuxPath(path string) string
-	ConvertToWindowsPath(path string) string
+	ConvertToLinuxPath(input string) string
+	ConvertToWindowsPath(input string) string
 	Connection(connectionType ConnectionType) (*Connection, error)
-	TemplateCache() *cache.Template
-	LoadTemplateCache()
 	CursorPosition() (row, col int)
 	SystemInfo() (*SystemInfo, error)
 	Debug(message string)
@@ -85,6 +81,7 @@ type Flags struct {
 	Shell         string
 	ShellVersion  string
 	PWD           string
+	AbsolutePWD   string
 	Type          string
 	ErrorCode     int
 	PromptCount   int
@@ -93,7 +90,8 @@ type Flags struct {
 	TerminalWidth int
 	ExecutionTime float64
 	JobCount      int
-	HasTransient  bool
+	IsPrimary     bool
+	HasExtra      bool
 	Debug         bool
 	Plain         bool
 	Strict        bool
diff --git a/src/runtime/mock/environment.go b/src/runtime/mock/environment.go
index 50f7d63e..acca25c9 100644
--- a/src/runtime/mock/environment.go
+++ b/src/runtime/mock/environment.go
@@ -47,8 +47,8 @@ func (env *Environment) HasFolder(folder string) bool {
 	return args.Bool(0)
 }
 
-func (env *Environment) ResolveSymlink(path string) (string, error) {
-	args := env.Called(path)
+func (env *Environment) ResolveSymlink(input string) (string, error) {
+	args := env.Called(input)
 	return args.String(0), args.Error(1)
 }
 
@@ -57,16 +57,11 @@ func (env *Environment) FileContent(file string) string {
 	return args.String(0)
 }
 
-func (env *Environment) LsDir(path string) []fs.DirEntry {
-	args := env.Called(path)
+func (env *Environment) LsDir(input string) []fs.DirEntry {
+	args := env.Called(input)
 	return args.Get(0).([]fs.DirEntry)
 }
 
-func (env *Environment) PathSeparator() string {
-	args := env.Called()
-	return args.String(0)
-}
-
 func (env *Environment) User() string {
 	args := env.Called()
 	return args.String(0)
@@ -226,15 +221,6 @@ func (env *Environment) Connection(connectionType runtime.ConnectionType) (*runt
 	return args.Get(0).(*runtime.Connection), args.Error(1)
 }
 
-func (env *Environment) TemplateCache() *cache.Template {
-	args := env.Called()
-	return args.Get(0).(*cache.Template)
-}
-
-func (env *Environment) LoadTemplateCache() {
-	_ = env.Called()
-}
-
 func (env *Environment) MockGitCommand(dir, returnValue string, args ...string) {
 	args = append([]string{"-C", dir, "--no-optional-locks", "-c", "core.quotepath=false", "-c", "color.status=false"}, args...)
 	env.On("RunCommand", "git", args).Return(returnValue, nil)
diff --git a/src/runtime/path/clean.go b/src/runtime/path/clean.go
new file mode 100644
index 00000000..c8f905eb
--- /dev/null
+++ b/src/runtime/path/clean.go
@@ -0,0 +1,123 @@
+package path
+
+import (
+	"fmt"
+	"path/filepath"
+	"runtime"
+	"strings"
+
+	"github.com/jandedobbeleer/oh-my-posh/src/regex"
+)
+
+// Base returns the last element of path.
+// Trailing path separators are removed before extracting the last element.
+// If the path consists entirely of separators, Base returns a single separator.
+func Base(input string) string {
+	volumeName := filepath.VolumeName(input)
+	// Strip trailing slashes.
+	for len(input) > 0 && IsSeparator(input[len(input)-1]) {
+		input = input[0 : len(input)-1]
+	}
+
+	if len(input) == 0 {
+		return Separator()
+	}
+
+	if volumeName == input {
+		return input
+	}
+
+	// Throw away volume name
+	input = input[len(filepath.VolumeName(input)):]
+	// Find the last element
+	i := len(input) - 1
+	for i >= 0 && !IsSeparator(input[i]) {
+		i--
+	}
+
+	if i >= 0 {
+		input = input[i+1:]
+	}
+
+	// If empty now, it had only slashes.
+	if len(input) == 0 {
+		return Separator()
+	}
+
+	return input
+}
+
+func Clean(input string) string {
+	if len(input) == 0 {
+		return input
+	}
+
+	cleaned := input
+	separator := Separator()
+
+	// The prefix can be empty for a relative path.
+	var prefix string
+	if IsSeparator(cleaned[0]) {
+		prefix = separator
+	}
+
+	if runtime.GOOS == windows {
+		// Normalize (forward) slashes to backslashes on Windows.
+		cleaned = strings.ReplaceAll(cleaned, "/", `\`)
+
+		// Clean the prefix for a UNC path, if any.
+		if regex.MatchString(`^\\{2}[^\\]+`, cleaned) {
+			cleaned = strings.TrimPrefix(cleaned, `\\.\UNC\`)
+			if len(cleaned) == 0 {
+				return cleaned
+			}
+			prefix = `\\`
+		}
+
+		// Always use an uppercase drive letter on Windows.
+		driveLetter := regex.GetCompiledRegex(`^[a-z]:`)
+		cleaned = driveLetter.ReplaceAllStringFunc(cleaned, strings.ToUpper)
+	}
+
+	sb := new(strings.Builder)
+	sb.WriteString(prefix)
+
+	// Clean slashes.
+	matches := regex.FindAllNamedRegexMatch(fmt.Sprintf(`(?P<element>[^\%s]+)`, separator), cleaned)
+	n := len(matches) - 1
+	for i, m := range matches {
+		sb.WriteString(m["element"])
+		if i != n {
+			sb.WriteString(separator)
+		}
+	}
+
+	return sb.String()
+}
+
+func ReplaceHomeDirPrefixWithTilde(path string) string {
+	home := Home()
+	if !strings.HasPrefix(path, home) {
+		return path
+	}
+
+	rem := path[len(home):]
+	if len(rem) == 0 || IsSeparator(rem[0]) {
+		return "~" + rem
+	}
+
+	return path
+}
+
+func ReplaceTildePrefixWithHomeDir(path string) string {
+	if !strings.HasPrefix(path, "~") {
+		return path
+	}
+
+	rem := path[1:]
+	if len(rem) == 0 || IsSeparator(rem[0]) {
+		return Home() + rem
+	}
+
+	return path
+}
diff --git a/src/runtime/path/home.go b/src/runtime/path/home.go
new file mode 100644
index 00000000..d2ffd4c4
--- /dev/null
+++ b/src/runtime/path/home.go
@@ -0,0 +1,27 @@
+package path
+
+import (
+	"os"
+
+	"github.com/jandedobbeleer/oh-my-posh/src/log"
+)
+
+func Home() string {
+	home := os.Getenv("HOME")
+	defer func() {
+		log.Debug(home)
+	}()
+
+	if len(home) > 0 {
+		return home
+	}
+
+	// fallback to older implemenations on Windows
+	home = os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
+
+	if len(home) == 0 {
+		home = os.Getenv("USERPROFILE")
+	}
+
+	return home
+}
diff --git a/src/runtime/path/separator.go b/src/runtime/path/separator.go
new file mode 100644
index 00000000..fe5f0c85
--- /dev/null
+++ b/src/runtime/path/separator.go
@@ -0,0 +1,34 @@
+package path
+
+import (
+	"runtime"
+	"time"
+
+	"github.com/jandedobbeleer/oh-my-posh/src/log"
+)
+
+const (
+	windows = "windows"
+)
+
+func Separator() string {
+	defer log.Trace(time.Now())
+
+	if runtime.GOOS == windows {
+		return `\`
+	}
+
+	return "/"
+}
+
+func IsSeparator(c uint8) bool {
+	if c == '/' {
+		return true
+	}
+
+	if runtime.GOOS == windows && c == '\\' {
+		return true
+	}
+
+	return false
+}
diff --git a/src/runtime/terminal.go b/src/runtime/terminal.go
index 63727b95..5fee41cb 100644
--- a/src/runtime/terminal.go
+++ b/src/runtime/terminal.go
@@ -2,7 +2,6 @@ package runtime
 
 import (
 	"context"
-	"encoding/json"
 	"errors"
 	"fmt"
 	"io"
@@ -22,8 +21,8 @@ import (
 	"github.com/jandedobbeleer/oh-my-posh/src/maps"
 	"github.com/jandedobbeleer/oh-my-posh/src/regex"
 	"github.com/jandedobbeleer/oh-my-posh/src/runtime/cmd"
-	"github.com/jandedobbeleer/oh-my-posh/src/runtime/config"
 	"github.com/jandedobbeleer/oh-my-posh/src/runtime/http"
+	"github.com/jandedobbeleer/oh-my-posh/src/runtime/path"
 
 	disk "github.com/shirou/gopsutil/v3/disk"
 	load "github.com/shirou/gopsutil/v3/load"
@@ -32,20 +31,20 @@ import (
 
 type Terminal struct {
 	CmdFlags     *Flags
-	Var          maps.Simple
 	cmdCache     *cache.Command
 	deviceCache  *cache.File
 	sessionCache *cache.File
-	tmplCache    *cache.Template
+	lsDirMap     maps.Concurrent
 	cwd          string
 	host         string
 	networks     []*Connection
-	lsDirMap     maps.Concurrent
 }
 
-func (term *Terminal) Init() {
+func (term *Terminal) Init(flags *Flags) {
 	defer term.Trace(time.Now())
 
+	term.CmdFlags = flags
+
 	if term.CmdFlags == nil {
 		term.CmdFlags = &Flags{}
 	}
@@ -61,9 +60,9 @@ func (term *Terminal) Init() {
 	}
 
 	initCache := func(fileName string) *cache.File {
-		cache := &cache.File{}
-		cache.Init(filepath.Join(term.CachePath(), fileName), term.CmdFlags.SaveCache)
-		return cache
+		fileCache := &cache.File{}
+		fileCache.Init(filepath.Join(cache.Path(), fileName), term.CmdFlags.SaveCache)
+		return fileCache
 	}
 
 	term.deviceCache = initCache(cache.FileName)
@@ -72,67 +71,9 @@ func (term *Terminal) Init() {
 
 	term.setPwd()
 
-	term.ResolveConfigPath()
-
 	term.cmdCache = &cache.Command{
 		Commands: maps.NewConcurrent(),
 	}
-
-	term.tmplCache = &cache.Template{}
-}
-
-func (term *Terminal) ResolveConfigPath() {
-	defer term.Trace(time.Now())
-
-	// if the config flag is set, we'll use that over POSH_THEME
-	// in our internal shell logic, we'll always use the POSH_THEME
-	// due to not using --config to set the configuration
-	hasConfigFlag := len(term.CmdFlags.Config) > 0
-
-	if poshTheme := term.Getenv("POSH_THEME"); len(poshTheme) > 0 && !hasConfigFlag {
-		term.DebugF("config set using POSH_THEME: %s", poshTheme)
-		term.CmdFlags.Config = poshTheme
-		return
-	}
-
-	if len(term.CmdFlags.Config) == 0 {
-		term.Debug("no config set, fallback to default config")
-		return
-	}
-
-	if strings.HasPrefix(term.CmdFlags.Config, "https://") {
-		filePath, err := config.Download(term.CachePath(), term.CmdFlags.Config)
-		if err != nil {
-			term.Error(err)
-			term.CmdFlags.Config = ""
-			return
-		}
-
-		term.CmdFlags.Config = filePath
-		return
-	}
-
-	isCygwin := func() bool {
-		return term.Platform() == WINDOWS && len(term.Getenv("OSTYPE")) > 0
-	}
-
-	// Cygwin path always needs the full path as we're on Windows but not really.
-	// Doing filepath actions will convert it to a Windows path and break the init script.
-	if isCygwin() {
-		term.Debug("cygwin detected, using full path for config")
-		return
-	}
-
-	configFile := ReplaceTildePrefixWithHomeDir(term, term.CmdFlags.Config)
-
-	abs, err := filepath.Abs(configFile)
-	if err != nil {
-		term.Error(err)
-		term.CmdFlags.Config = filepath.Clean(configFile)
-		return
-	}
-
-	term.CmdFlags.Config = abs
 }
 
 func (term *Terminal) Trace(start time.Time, args ...string) {
@@ -179,7 +120,7 @@ func (term *Terminal) setPwd() {
 	}
 
 	if term.CmdFlags != nil && term.CmdFlags.PWD != "" {
-		term.cwd = CleanPath(term, term.CmdFlags.PWD)
+		term.cwd = path.Clean(term.CmdFlags.PWD)
 		term.Debug(term.cwd)
 		return
 	}
@@ -277,9 +218,9 @@ func (term *Terminal) HasFolder(folder string) bool {
 	return isDir
 }
 
-func (term *Terminal) ResolveSymlink(path string) (string, error) {
-	defer term.Trace(time.Now(), path)
-	link, err := filepath.EvalSymlinks(path)
+func (term *Terminal) ResolveSymlink(input string) (string, error) {
+	defer term.Trace(time.Now(), input)
+	link, err := filepath.EvalSymlinks(input)
 	if err != nil {
 		term.Error(err)
 		return "", err
@@ -293,35 +234,32 @@ func (term *Terminal) FileContent(file string) string {
 	if !filepath.IsAbs(file) {
 		file = filepath.Join(term.Pwd(), file)
 	}
+
 	content, err := os.ReadFile(file)
 	if err != nil {
 		term.Error(err)
 		return ""
 	}
+
 	fileContent := string(content)
 	term.Debug(fileContent)
+
 	return fileContent
 }
 
-func (term *Terminal) LsDir(path string) []fs.DirEntry {
-	defer term.Trace(time.Now(), path)
-	entries, err := os.ReadDir(path)
+func (term *Terminal) LsDir(input string) []fs.DirEntry {
+	defer term.Trace(time.Now(), input)
+
+	entries, err := os.ReadDir(input)
 	if err != nil {
 		term.Error(err)
 		return nil
 	}
+
 	term.DebugF("%v", entries)
 	return entries
 }
 
-func (term *Terminal) PathSeparator() string {
-	defer term.Trace(time.Now())
-	if term.GOOS() == WINDOWS {
-		return `\`
-	}
-	return "/"
-}
-
 func (term *Terminal) User() string {
 	defer term.Trace(time.Now())
 	user := os.Getenv("USER")
@@ -356,6 +294,10 @@ func (term *Terminal) GOOS() string {
 	return runtime.GOOS
 }
 
+func (term *Terminal) Home() string {
+	return path.Home()
+}
+
 func (term *Terminal) RunCommand(command string, args ...string) (string, error) {
 	defer term.Trace(time.Now(), append([]string{command}, args...)...)
 
@@ -384,16 +326,16 @@ func (term *Terminal) RunShellCommand(shell, command string) string {
 
 func (term *Terminal) CommandPath(command string) string {
 	defer term.Trace(time.Now(), command)
-	if path, ok := term.cmdCache.Get(command); ok {
-		term.Debug(path)
-		return path
+	if cmdPath, ok := term.cmdCache.Get(command); ok {
+		term.Debug(cmdPath)
+		return cmdPath
 	}
 
-	path, err := exec.LookPath(command)
+	cmdPath, err := exec.LookPath(command)
 	if err == nil {
-		term.cmdCache.Set(command, path)
-		term.Debug(path)
-		return path
+		term.cmdCache.Set(command, cmdPath)
+		term.Debug(cmdPath)
+		return cmdPath
 	}
 
 	term.Error(err)
@@ -402,9 +344,11 @@ func (term *Terminal) CommandPath(command string) string {
 
 func (term *Terminal) HasCommand(command string) bool {
 	defer term.Trace(time.Now(), command)
-	if path := term.CommandPath(command); path != "" {
+
+	if cmdPath := term.CommandPath(command); cmdPath != "" {
 		return true
 	}
+
 	return false
 }
 
@@ -529,20 +473,20 @@ func (term *Terminal) HTTPRequest(targetURL string, body io.Reader, timeout int,
 func (term *Terminal) HasParentFilePath(parent string, followSymlinks bool) (*FileInfo, error) {
 	defer term.Trace(time.Now(), parent)
 
-	path := term.Pwd()
+	pwd := term.Pwd()
 	if followSymlinks {
-		if actual, err := term.ResolveSymlink(path); err == nil {
-			path = actual
+		if actual, err := term.ResolveSymlink(pwd); err == nil {
+			pwd = actual
 		}
 	}
 
 	for {
-		fileSystem := os.DirFS(path)
+		fileSystem := os.DirFS(pwd)
 		info, err := fs.Stat(fileSystem, parent)
 		if err == nil {
 			return &FileInfo{
-				ParentFolder: path,
-				Path:         filepath.Join(path, parent),
+				ParentFolder: pwd,
+				Path:         filepath.Join(pwd, parent),
 				IsDir:        info.IsDir(),
 			}, nil
 		}
@@ -551,8 +495,8 @@ func (term *Terminal) HasParentFilePath(parent string, followSymlinks bool) (*Fi
 			return nil, err
 		}
 
-		if dir := filepath.Dir(path); dir != path {
-			path = dir
+		if dir := filepath.Dir(pwd); dir != pwd {
+			pwd = dir
 			continue
 		}
 
@@ -563,6 +507,7 @@ func (term *Terminal) HasParentFilePath(parent string, followSymlinks bool) (*Fi
 
 func (term *Terminal) StackCount() int {
 	defer term.Trace(time.Now())
+
 	if term.CmdFlags.StackCount < 0 {
 		return 0
 	}
@@ -578,26 +523,8 @@ func (term *Terminal) Session() cache.Cache {
 	return term.sessionCache
 }
 
-func (term *Terminal) saveTemplateCache() {
-	// only store this when in a primary prompt
-	// and when we have a transient prompt in the config
-	canSave := term.CmdFlags.Type == PRIMARY && term.CmdFlags.HasTransient
-	if !canSave {
-		return
-	}
-
-	tmplCache := term.TemplateCache()
-	tmplCache.SegmentsCache = tmplCache.Segments.ToSimple()
-
-	templateCache, err := json.Marshal(tmplCache)
-	if err == nil {
-		term.sessionCache.Set(cache.TEMPLATECACHE, string(templateCache), cache.ONEDAY)
-	}
-}
-
 func (term *Terminal) Close() {
 	defer term.Trace(time.Now())
-	term.saveTemplateCache()
 	term.clearCacheFiles()
 	term.deviceCache.Close()
 	term.sessionCache.Close()
@@ -608,7 +535,7 @@ func (term *Terminal) clearCacheFiles() {
 		return
 	}
 
-	deletedFiles, err := cache.Clear(term.CachePath(), false)
+	deletedFiles, err := cache.Clear(cache.Path(), false)
 	if err != nil {
 		term.Error(err)
 		return
@@ -619,89 +546,10 @@ func (term *Terminal) clearCacheFiles() {
 	}
 }
 
-func (term *Terminal) LoadTemplateCache() {
-	defer term.Trace(time.Now())
-
-	val, OK := term.sessionCache.Get(cache.TEMPLATECACHE)
-	if !OK {
-		return
-	}
-
-	var tmplCache cache.Template
-
-	err := json.Unmarshal([]byte(val), &tmplCache)
-	if err != nil {
-		term.Error(err)
-		return
-	}
-
-	tmplCache.Segments = tmplCache.SegmentsCache.ToConcurrent()
-	tmplCache.Initialized = true
-
-	term.tmplCache = &tmplCache
-}
-
 func (term *Terminal) Logs() string {
 	return log.String()
 }
 
-func (term *Terminal) TemplateCache() *cache.Template {
-	defer term.Trace(time.Now())
-	tmplCache := term.tmplCache
-
-	if tmplCache.Initialized {
-		return tmplCache
-	}
-
-	tmplCache.Root = term.Root()
-	tmplCache.Shell = term.Shell()
-	tmplCache.ShellVersion = term.CmdFlags.ShellVersion
-	tmplCache.Code, _ = term.StatusCodes()
-	tmplCache.WSL = term.IsWsl()
-	tmplCache.Segments = maps.NewConcurrent()
-	tmplCache.PromptCount = term.CmdFlags.PromptCount
-	tmplCache.Var = make(map[string]any)
-	tmplCache.Jobs = term.CmdFlags.JobCount
-
-	if term.Var != nil {
-		tmplCache.Var = term.Var
-	}
-
-	pwd := term.Pwd()
-	tmplCache.PWD = ReplaceHomeDirPrefixWithTilde(term, pwd)
-
-	tmplCache.AbsolutePWD = pwd
-	if term.IsWsl() {
-		tmplCache.AbsolutePWD, _ = term.RunCommand("wslpath", "-m", pwd)
-	}
-
-	tmplCache.PSWD = term.CmdFlags.PSWD
-
-	tmplCache.Folder = Base(term, pwd)
-	if term.GOOS() == WINDOWS && strings.HasSuffix(tmplCache.Folder, ":") {
-		tmplCache.Folder += `\`
-	}
-
-	tmplCache.UserName = term.User()
-	if host, err := term.Host(); err == nil {
-		tmplCache.HostName = host
-	}
-
-	goos := term.GOOS()
-	tmplCache.OS = goos
-	if goos == LINUX {
-		tmplCache.OS = term.Platform()
-	}
-
-	val := term.Getenv("SHLVL")
-	if shlvl, err := strconv.Atoi(val); err == nil {
-		tmplCache.SHLVL = shlvl
-	}
-
-	tmplCache.Initialized = true
-	return tmplCache
-}
-
 func (term *Terminal) DirMatchesOneOf(dir string, regexes []string) (match bool) {
 	// sometimes the function panics inside golang, we want to silence that error
 	// and assume that there's no match. Not perfect, but better than crashing
@@ -798,170 +646,6 @@ func (term *Terminal) SystemInfo() (*SystemInfo, error) {
 	return s, nil
 }
 
-func (term *Terminal) CachePath() string {
-	defer term.Trace(time.Now())
-
-	returnOrBuildCachePath := func(path string) (string, bool) {
-		// validate root path
-		if _, err := os.Stat(path); err != nil {
-			return "", false
-		}
-
-		// validate oh-my-posh folder, if non existent, create it
-		cachePath := filepath.Join(path, "oh-my-posh")
-		if _, err := os.Stat(cachePath); err == nil {
-			return cachePath, true
-		}
-
-		if err := os.Mkdir(cachePath, 0o755); err != nil {
-			return "", false
-		}
-
-		return cachePath, true
-	}
-
-	// WINDOWS cache folder, should not exist elsewhere
-	if cachePath, OK := returnOrBuildCachePath(term.Getenv("LOCALAPPDATA")); OK {
-		return cachePath
-	}
-
-	// allow the user to set the cache path using OMP_CACHE_DIR
-	if cachePath, OK := returnOrBuildCachePath(term.Getenv("OMP_CACHE_DIR")); OK {
-		return cachePath
-	}
-
-	// get XDG_CACHE_HOME if present
-	if cachePath, OK := returnOrBuildCachePath(term.Getenv("XDG_CACHE_HOME")); OK {
-		return cachePath
-	}
-
-	// try to create the cache folder in the user's home directory if non-existent
-	dotCache := filepath.Join(term.Home(), ".cache")
-	if _, err := os.Stat(dotCache); err != nil {
-		_ = os.Mkdir(dotCache, 0o755)
-	}
-
-	// HOME cache folder
-	if cachePath, OK := returnOrBuildCachePath(dotCache); OK {
-		return cachePath
-	}
-
-	return term.Home()
-}
-
-func IsPathSeparator(env Environment, c uint8) bool {
-	if c == '/' {
-		return true
-	}
-	if env.GOOS() == WINDOWS && c == '\\' {
-		return true
-	}
-	return false
-}
-
-// Base returns the last element of path.
-// Trailing path separators are removed before extracting the last element.
-// If the path consists entirely of separators, Base returns a single separator.
-func Base(env Environment, path string) string {
-	volumeName := filepath.VolumeName(path)
-	// Strip trailing slashes.
-	for len(path) > 0 && IsPathSeparator(env, path[len(path)-1]) {
-		path = path[0 : len(path)-1]
-	}
-	if len(path) == 0 {
-		return env.PathSeparator()
-	}
-	if volumeName == path {
-		return path
-	}
-	// Throw away volume name
-	path = path[len(filepath.VolumeName(path)):]
-	// Find the last element
-	i := len(path) - 1
-	for i >= 0 && !IsPathSeparator(env, path[i]) {
-		i--
-	}
-	if i >= 0 {
-		path = path[i+1:]
-	}
-	// If empty now, it had only slashes.
-	if len(path) == 0 {
-		return env.PathSeparator()
-	}
-	return path
-}
-
-func CleanPath(env Environment, path string) string {
-	if len(path) == 0 {
-		return path
-	}
-
-	cleaned := path
-	separator := env.PathSeparator()
-
-	// The prefix can be empty for a relative path.
-	var prefix string
-	if IsPathSeparator(env, cleaned[0]) {
-		prefix = separator
-	}
-
-	if env.GOOS() == WINDOWS {
-		// Normalize (forward) slashes to backslashes on Windows.
-		cleaned = strings.ReplaceAll(cleaned, "/", `\`)
-
-		// Clean the prefix for a UNC path, if any.
-		if regex.MatchString(`^\\{2}[^\\]+`, cleaned) {
-			cleaned = strings.TrimPrefix(cleaned, `\\.\UNC\`)
-			if len(cleaned) == 0 {
-				return cleaned
-			}
-			prefix = `\\`
-		}
-
-		// Always use an uppercase drive letter on Windows.
-		driveLetter := regex.GetCompiledRegex(`^[a-z]:`)
-		cleaned = driveLetter.ReplaceAllStringFunc(cleaned, strings.ToUpper)
-	}
-
-	sb := new(strings.Builder)
-	sb.WriteString(prefix)
-
-	// Clean slashes.
-	matches := regex.FindAllNamedRegexMatch(fmt.Sprintf(`(?P<element>[^\%s]+)`, separator), cleaned)
-	n := len(matches) - 1
-	for i, m := range matches {
-		sb.WriteString(m["element"])
-		if i != n {
-			sb.WriteString(separator)
-		}
-	}
-
-	return sb.String()
-}
-
-func ReplaceTildePrefixWithHomeDir(env Environment, path string) string {
-	if !strings.HasPrefix(path, "~") {
-		return path
-	}
-	rem := path[1:]
-	if len(rem) == 0 || IsPathSeparator(env, rem[0]) {
-		return env.Home() + rem
-	}
-	return path
-}
-
-func ReplaceHomeDirPrefixWithTilde(env Environment, path string) string {
-	home := env.Home()
-	if !strings.HasPrefix(path, home) {
-		return path
-	}
-	rem := path[len(home):]
-	if len(rem) == 0 || IsPathSeparator(env, rem[0]) {
-		return "~" + rem
-	}
-	return path
-}
-
 func cleanHostName(hostName string) string {
 	garbage := []string{
 		".lan",
diff --git a/src/runtime/terminal_unix.go b/src/runtime/terminal_unix.go
index dc09204a..ce4cff39 100644
--- a/src/runtime/terminal_unix.go
+++ b/src/runtime/terminal_unix.go
@@ -20,10 +20,6 @@ func (term *Terminal) Root() bool {
 	return os.Geteuid() == 0
 }
 
-func (term *Terminal) Home() string {
-	return os.Getenv("HOME")
-}
-
 func (term *Terminal) QueryWindowTitles(_, _ string) (string, error) {
 	return "", &NotImplemented{}
 }
@@ -132,24 +128,24 @@ func (term *Terminal) InWSLSharedDrive() bool {
 	return !strings.HasPrefix(windowsPath, `//wsl.localhost/`) && !strings.HasPrefix(windowsPath, `//wsl$/`)
 }
 
-func (term *Terminal) ConvertToWindowsPath(path string) string {
-	windowsPath, err := term.RunCommand("wslpath", "-m", path)
+func (term *Terminal) ConvertToWindowsPath(input string) string {
+	windowsPath, err := term.RunCommand("wslpath", "-m", input)
 	if err == nil {
 		return windowsPath
 	}
-	return path
+	return input
 }
 
-func (term *Terminal) ConvertToLinuxPath(path string) string {
-	if linuxPath, err := term.RunCommand("wslpath", "-u", path); err == nil {
+func (term *Terminal) ConvertToLinuxPath(input string) string {
+	if linuxPath, err := term.RunCommand("wslpath", "-u", input); err == nil {
 		return linuxPath
 	}
-	return path
+	return input
 }
 
-func (term *Terminal) DirIsWritable(path string) bool {
-	defer term.Trace(time.Now(), path)
-	return unix.Access(path, unix.W_OK) == nil
+func (term *Terminal) DirIsWritable(input string) bool {
+	defer term.Trace(time.Now(), input)
+	return unix.Access(input, unix.W_OK) == nil
 }
 
 func (term *Terminal) Connection(_ ConnectionType) (*Connection, error) {
diff --git a/src/runtime/terminal_windows.go b/src/runtime/terminal_windows.go
index 95c3ecdf..75020e61 100644
--- a/src/runtime/terminal_windows.go
+++ b/src/runtime/terminal_windows.go
@@ -3,12 +3,12 @@ package runtime
 import (
 	"errors"
 	"fmt"
-	"os"
 	"strings"
 	"syscall"
 	"time"
 
 	"github.com/Azure/go-ansiterm/winterm"
+	"github.com/jandedobbeleer/oh-my-posh/src/runtime/path"
 	"golang.org/x/sys/windows"
 	"golang.org/x/sys/windows/registry"
 )
@@ -50,22 +50,6 @@ func (term *Terminal) Root() bool {
 	return member
 }
 
-func (term *Terminal) Home() string {
-	home := os.Getenv("HOME")
-	defer func() {
-		term.Debug(home)
-	}()
-	if len(home) > 0 {
-		return home
-	}
-	// fallback to older implemenations on Windows
-	home = os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
-	if home == "" {
-		home = os.Getenv("USERPROFILE")
-	}
-	return home
-}
-
 func (term *Terminal) QueryWindowTitles(processName, windowTitleRegex string) (string, error) {
 	defer term.Trace(time.Now(), windowTitleRegex)
 	title, err := queryWindowTitles(processName, windowTitleRegex)
@@ -128,8 +112,8 @@ func (term *Terminal) Platform() string {
 // If the path ends in "\", the "(Default)" key in that path is retrieved.
 //
 // Returns a variant type if successful; nil and an error if not.
-func (term *Terminal) WindowsRegistryKeyValue(path string) (*WindowsRegistryValue, error) {
-	term.Trace(time.Now(), path)
+func (term *Terminal) WindowsRegistryKeyValue(input string) (*WindowsRegistryValue, error) {
+	term.Trace(time.Now(), input)
 
 	// Format:
 	// "HKLM\Software\Microsoft\Windows NT\CurrentVersion\EditionID"
@@ -143,16 +127,16 @@ func (term *Terminal) WindowsRegistryKeyValue(path string) (*WindowsRegistryValu
 	//
 	// If 3 is "" (i.e. the path ends with "\"), then get (Default) key.
 	//
-	rootKey, regPath, found := strings.Cut(path, `\`)
+	rootKey, regPath, found := strings.Cut(input, `\`)
 	if !found {
-		err := fmt.Errorf("Error, malformed registry path: '%s'", path)
+		err := fmt.Errorf("Error, malformed registry path: '%s'", input)
 		term.Error(err)
 		return nil, err
 	}
 
 	var regKey string
 	if !strings.HasSuffix(regPath, `\`) {
-		regKey = Base(term, regPath)
+		regKey = path.Base(regPath)
 		if len(regKey) != 0 {
 			regPath = strings.TrimSuffix(regPath, `\`+regKey)
 		}
@@ -218,17 +202,17 @@ func (term *Terminal) InWSLSharedDrive() bool {
 	return false
 }
 
-func (term *Terminal) ConvertToWindowsPath(path string) string {
-	return strings.ReplaceAll(path, `\`, "/")
+func (term *Terminal) ConvertToWindowsPath(input string) string {
+	return strings.ReplaceAll(input, `\`, "/")
 }
 
-func (term *Terminal) ConvertToLinuxPath(path string) string {
-	return path
+func (term *Terminal) ConvertToLinuxPath(input string) string {
+	return input
 }
 
-func (term *Terminal) DirIsWritable(path string) bool {
+func (term *Terminal) DirIsWritable(input string) bool {
 	defer term.Trace(time.Now())
-	return term.isWriteable(path)
+	return term.isWriteable(input)
 }
 
 func (term *Terminal) Connection(connectionType ConnectionType) (*Connection, error) {
diff --git a/src/segments/git.go b/src/segments/git.go
index c70c9214..9ace75bc 100644
--- a/src/segments/git.go
+++ b/src/segments/git.go
@@ -11,6 +11,7 @@ import (
 	"github.com/jandedobbeleer/oh-my-posh/src/properties"
 	"github.com/jandedobbeleer/oh-my-posh/src/regex"
 	"github.com/jandedobbeleer/oh-my-posh/src/runtime"
+	"github.com/jandedobbeleer/oh-my-posh/src/runtime/path"
 
 	"gopkg.in/ini.v1"
 )
@@ -365,8 +366,8 @@ func (g *Git) getBareRepoInfo() {
 	// we can still have a pointer to a bare repo
 	if file, err := g.env.HasParentFilePath(".git", true); err == nil && !file.IsDir {
 		content := g.FileContents(file.ParentFolder, ".git")
-		path := strings.TrimPrefix(content, "gitdir: ")
-		g.workingDir = filepath.Join(file.ParentFolder, path)
+		dir := strings.TrimPrefix(content, "gitdir: ")
+		g.workingDir = filepath.Join(file.ParentFolder, dir)
 	}
 
 	head := g.FileContents(g.workingDir, "HEAD")
@@ -384,7 +385,7 @@ func (g *Git) getBareRepoInfo() {
 }
 
 func (g *Git) setDir(dir string) {
-	dir = runtime.ReplaceHomeDirPrefixWithTilde(g.env, dir) // align with template PWD
+	dir = path.ReplaceHomeDirPrefixWithTilde(dir) // align with template PWD
 	if g.env.GOOS() == runtime.WINDOWS {
 		g.Dir = strings.TrimSuffix(dir, `\.git`)
 		return
@@ -516,9 +517,9 @@ func (g *Git) cleanUpstreamURL(url string) string {
 	}
 
 	if len(match) != 0 {
-		path := strings.Trim(match["PATH"], "/")
-		path = strings.TrimSuffix(path, ".git")
-		return fmt.Sprintf("https://%s/%s", match["URL"], path)
+		repoPath := strings.Trim(match["PATH"], "/")
+		repoPath = strings.TrimSuffix(repoPath, ".git")
+		return fmt.Sprintf("https://%s/%s", match["URL"], repoPath)
 	}
 
 	// codecommit::region-identifier-id://repo-name
@@ -923,12 +924,12 @@ func (g *Git) getSwitchMode(property properties.Property, gitSwitch, mode string
 
 func (g *Git) repoName() string {
 	if !g.IsWorkTree {
-		return runtime.Base(g.env, g.convertToLinuxPath(g.realDir))
+		return path.Base(g.convertToLinuxPath(g.realDir))
 	}
 
 	ind := strings.LastIndex(g.workingDir, ".git/worktrees")
 	if ind > -1 {
-		return runtime.Base(g.env, g.workingDir[:ind])
+		return path.Base(g.workingDir[:ind])
 	}
 
 	return ""
diff --git a/src/segments/git_unix.go b/src/segments/git_unix.go
index 6c1ab7c2..24bb8484 100644
--- a/src/segments/git_unix.go
+++ b/src/segments/git_unix.go
@@ -9,5 +9,6 @@ func resolveGitPath(base, path string) string {
 	if filepath.IsAbs(path) {
 		return path
 	}
+
 	return filepath.Join(base, path)
 }
diff --git a/src/segments/git_windows.go b/src/segments/git_windows.go
index 424a5a51..0d22a8a4 100644
--- a/src/segments/git_windows.go
+++ b/src/segments/git_windows.go
@@ -7,9 +7,11 @@ func resolveGitPath(base, path string) string {
 	if len(path) == 0 {
 		return base
 	}
+
 	if filepath.IsAbs(path) {
 		return path
 	}
+
 	// Note that git on Windows uses slashes exclusively. And it's okay
 	// because Windows actually accepts both directory separators. More
 	// importantly, however, parts of the git segment depend on those
@@ -18,5 +20,6 @@ func resolveGitPath(base, path string) string {
 		// path is a disk-relative path.
 		return filepath.VolumeName(base) + path
 	}
+
 	return filepath.ToSlash(filepath.Join(base, path))
 }
diff --git a/src/segments/mercurial.go b/src/segments/mercurial.go
index 3deaf315..1d03134a 100644
--- a/src/segments/mercurial.go
+++ b/src/segments/mercurial.go
@@ -4,6 +4,7 @@ import (
 	"strings"
 
 	"github.com/jandedobbeleer/oh-my-posh/src/runtime"
+	"github.com/jandedobbeleer/oh-my-posh/src/runtime/path"
 )
 
 const (
@@ -90,7 +91,7 @@ func (hg *Mercurial) shouldDisplay() bool {
 }
 
 func (hg *Mercurial) setDir(dir string) {
-	dir = runtime.ReplaceHomeDirPrefixWithTilde(hg.env, dir) // align with template PWD
+	dir = path.ReplaceHomeDirPrefixWithTilde(dir) // align with template PWD
 	if hg.env.GOOS() == runtime.WINDOWS {
 		hg.Dir = strings.TrimSuffix(dir, `\.hg`)
 		return
diff --git a/src/segments/path.go b/src/segments/path.go
index 7af10cd9..99dcf8ab 100644
--- a/src/segments/path.go
+++ b/src/segments/path.go
@@ -9,6 +9,7 @@ import (
 	"github.com/jandedobbeleer/oh-my-posh/src/properties"
 	"github.com/jandedobbeleer/oh-my-posh/src/regex"
 	"github.com/jandedobbeleer/oh-my-posh/src/runtime"
+	"github.com/jandedobbeleer/oh-my-posh/src/runtime/path"
 	"github.com/jandedobbeleer/oh-my-posh/src/shell"
 	"github.com/jandedobbeleer/oh-my-posh/src/template"
 )
@@ -126,7 +127,7 @@ func (pt *Path) Enabled() bool {
 	pt.setStyle()
 	pwd := pt.env.Pwd()
 
-	pt.Location = pt.env.TemplateCache().AbsolutePWD
+	pt.Location = pt.env.Flags().AbsolutePWD
 	if pt.env.GOOS() == runtime.WINDOWS {
 		pt.Location = strings.ReplaceAll(pt.Location, `\`, `/`)
 	}
@@ -152,7 +153,7 @@ func (pt *Path) setPaths() {
 
 	pt.cygPath = displayCygpath()
 	pt.windowsPath = pt.env.GOOS() == runtime.WINDOWS && !pt.cygPath
-	pt.pathSeparator = pt.env.PathSeparator()
+	pt.pathSeparator = path.Separator()
 
 	pt.pwd = pt.env.Pwd()
 	if (pt.env.Shell() == shell.PWSH || pt.env.Shell() == shell.PWSH5) && len(pt.env.Flags().PSWD) != 0 {
@@ -186,10 +187,12 @@ func (pt *Path) Parent() string {
 	if !pt.endWithSeparator(pt.root) {
 		sb.WriteString(folderSeparator)
 	}
+
 	for _, folder := range folders[:len(folders)-1] {
 		sb.WriteString(folder)
 		sb.WriteString(folderSeparator)
 	}
+
 	return sb.String()
 }
 
@@ -267,6 +270,7 @@ func (pt *Path) getFolderSeparator() string {
 		if len(separator) == 0 {
 			return pt.pathSeparator
 		}
+
 		return separator
 	}
 
@@ -568,21 +572,21 @@ func (pt *Path) setMappedLocations() {
 			Context:  pt,
 		}
 
-		path, err := tmpl.Render()
+		location, err := tmpl.Render()
 		if err != nil {
 			pt.env.Error(err)
 		}
 
-		if len(path) == 0 {
+		if len(location) == 0 {
 			continue
 		}
 
 		// When two templates resolve to the same key, the values are compared in ascending order and the latter is taken.
-		if v, exist := mappedLocations[pt.normalize(path)]; exist && value <= v {
+		if v, exist := mappedLocations[pt.normalize(location)]; exist && value <= v {
 			continue
 		}
 
-		mappedLocations[pt.normalize(path)] = value
+		mappedLocations[pt.normalize(location)] = value
 	}
 
 	pt.mappedLocations = mappedLocations
@@ -660,9 +664,9 @@ func (pt *Path) parsePath(inputPath string) (string, string) {
 	}
 
 	if pt.cygPath {
-		path, err := pt.env.RunCommand("cygpath", "-u", inputPath)
-		if len(path) != 0 {
-			inputPath = path
+		cygPath, err := pt.env.RunCommand("cygpath", "-u", inputPath)
+		if len(cygPath) != 0 {
+			inputPath = cygPath
 			pt.pathSeparator = "/"
 		}
 
@@ -697,25 +701,26 @@ func (pt *Path) parsePath(inputPath string) (string, string) {
 	return root, relative
 }
 
-func (pt *Path) isRootFS(path string) bool {
-	return len(path) == 1 && runtime.IsPathSeparator(pt.env, path[0])
+func (pt *Path) isRootFS(inputPath string) bool {
+	return len(inputPath) == 1 && path.IsSeparator(inputPath[0])
 }
 
-func (pt *Path) endWithSeparator(path string) bool {
-	if len(path) == 0 {
+func (pt *Path) endWithSeparator(inputPath string) bool {
+	if len(inputPath) == 0 {
 		return false
 	}
-	return runtime.IsPathSeparator(pt.env, path[len(path)-1])
+
+	return path.IsSeparator(inputPath[len(inputPath)-1])
 }
 
 func (pt *Path) normalize(inputPath string) string {
 	normalized := inputPath
 
-	if strings.HasPrefix(normalized, "~") && (len(normalized) == 1 || runtime.IsPathSeparator(pt.env, normalized[1])) {
+	if strings.HasPrefix(normalized, "~") && (len(normalized) == 1 || path.IsSeparator(normalized[1])) {
 		normalized = pt.env.Home() + normalized[1:]
 	}
 
-	normalized = runtime.CleanPath(pt.env, normalized)
+	normalized = path.Clean(normalized)
 
 	if pt.env.GOOS() == runtime.WINDOWS || pt.env.GOOS() == runtime.DARWIN {
 		normalized = strings.ToLower(normalized)
@@ -827,9 +832,9 @@ func (pt *Path) makeFolderFormatMap() map[string]string {
 	if gitDirFormat := pt.props.GetString(GitDirFormat, ""); len(gitDirFormat) != 0 {
 		dir, err := pt.env.HasParentFilePath(".git", false)
 		if err == nil && dir.IsDir {
-			// Make it consistent with the modified path.
-			path := pt.join(pt.replaceMappedLocations(dir.ParentFolder))
-			folderFormatMap[path] = gitDirFormat
+			// Make it consistent with the modified parent.
+			parent := pt.join(pt.replaceMappedLocations(dir.ParentFolder))
+			folderFormatMap[parent] = gitDirFormat
 		}
 	}
 
diff --git a/src/segments/pulumi.go b/src/segments/pulumi.go
index b550705d..24d16dad 100644
--- a/src/segments/pulumi.go
+++ b/src/segments/pulumi.go
@@ -8,6 +8,7 @@ import (
 	"path/filepath"
 
 	"github.com/jandedobbeleer/oh-my-posh/src/properties"
+	"github.com/jandedobbeleer/oh-my-posh/src/runtime/path"
 	"gopkg.in/yaml.v3"
 )
 
@@ -135,21 +136,21 @@ func (p *Pulumi) getProjectName() error {
 
 	p.Name = pulumiFileSpec.Name
 
-	sha1HexString := func(value string) string {
-		h := sha1.New()
+	p.workspaceSHA1 = p.sha1HexString(p.env.Pwd() + path.Separator() + fileName)
 
-		_, err := h.Write([]byte(value))
-		if err != nil {
-			p.env.Error(err)
-			return ""
-		}
+	return nil
+}
 
-		return hex.EncodeToString(h.Sum(nil))
-	}
+func (p *Pulumi) sha1HexString(s string) string {
+	h := sha1.New()
 
-	p.workspaceSHA1 = sha1HexString(p.env.Pwd() + p.env.PathSeparator() + fileName)
+	_, err := h.Write([]byte(s))
+	if err != nil {
+		p.env.Error(err)
+		return ""
+	}
 
-	return nil
+	return hex.EncodeToString(h.Sum(nil))
 }
 
 func (p *Pulumi) getPulumiAbout() {
diff --git a/src/segments/python.go b/src/segments/python.go
index 3bc5dade..68015c05 100644
--- a/src/segments/python.go
+++ b/src/segments/python.go
@@ -8,7 +8,7 @@ import (
 	"strings"
 
 	"github.com/jandedobbeleer/oh-my-posh/src/properties"
-	"github.com/jandedobbeleer/oh-my-posh/src/runtime"
+	"github.com/jandedobbeleer/oh-my-posh/src/runtime/path"
 )
 
 type Python struct {
@@ -87,10 +87,10 @@ func (p *Python) loadContext() {
 			continue
 		}
 
-		name := runtime.Base(p.language.env, venv)
+		name := path.Base(venv)
 		if folderNameFallback && slices.Contains(defaultVenvNames, name) {
 			venv = strings.TrimSuffix(venv, name)
-			name = runtime.Base(p.language.env, venv)
+			name = path.Base(venv)
 		}
 
 		if p.canUseVenvName(name) {
@@ -121,23 +121,27 @@ func (p *Python) pyenvVersion() (string, error) {
 	// Use `pyenv root` instead of $PYENV_ROOT?
 	// Is our Python executable at $PYENV_ROOT/bin/python ?
 	// Should p.env expose command paths?
-	path := p.env.CommandPath("python")
-	if len(path) == 0 {
-		path = p.env.CommandPath("python3")
+	cmdPath := p.env.CommandPath("python")
+	if len(cmdPath) == 0 {
+		cmdPath = p.env.CommandPath("python3")
 	}
-	if len(path) == 0 {
+
+	if len(cmdPath) == 0 {
 		return "", errors.New("no python executable found")
 	}
+
 	pyEnvRoot := p.env.Getenv("PYENV_ROOT")
 	// TODO:  pyenv-win has this at $PYENV_ROOT/pyenv-win/shims
-	if path != filepath.Join(pyEnvRoot, "shims", "python") {
-		return "", fmt.Errorf("executable at %s is not a pyenv shim", path)
+	if cmdPath != filepath.Join(pyEnvRoot, "shims", "python") {
+		return "", fmt.Errorf("executable at %s is not a pyenv shim", cmdPath)
 	}
+
 	// pyenv version-name will return current version or virtualenv
 	cmdOutput, err := p.env.RunCommand("pyenv", "version-name")
 	if err != nil {
 		return "", err
 	}
+
 	versionString := strings.Split(cmdOutput, ":")[0]
 	if len(versionString) == 0 {
 		return "", errors.New("no pyenv version-name found")
@@ -148,34 +152,41 @@ func (p *Python) pyenvVersion() (string, error) {
 	if err != nil {
 		return "", err
 	}
+
 	// ../versions/(version)[/envs/(virtualenv)]
 	shortPath, err := filepath.Rel(filepath.Join(pyEnvRoot, "versions"), realPath)
 	if err != nil {
 		return "", err
 	}
+
 	// override virtualenv if pyenv set one
 	parts := strings.Split(shortPath, string(filepath.Separator))
 	if len(parts) > 2 && p.canUseVenvName(parts[2]) {
 		p.Venv = parts[2]
 	}
+
 	return parts[0], nil
 }
 
 func (p *Python) pyvenvCfgPrompt() string {
-	path := p.language.env.CommandPath("python")
-	if len(path) == 0 {
-		path = p.language.env.CommandPath("python3")
+	cmdPath := p.language.env.CommandPath("python")
+	if len(cmdPath) == 0 {
+		cmdPath = p.language.env.CommandPath("python3")
 	}
-	if len(path) == 0 {
+
+	if len(cmdPath) == 0 {
 		return ""
 	}
-	pyvenvDir := filepath.Dir(path)
+
+	pyvenvDir := filepath.Dir(cmdPath)
 	if !p.language.env.HasFilesInDir(pyvenvDir, "pyvenv.cfg") {
 		pyvenvDir = filepath.Dir(pyvenvDir)
 	}
+
 	if !p.language.env.HasFilesInDir(pyvenvDir, "pyvenv.cfg") {
 		return ""
 	}
+
 	pyvenvCfg := p.env.FileContent(filepath.Join(pyvenvDir, "pyvenv.cfg"))
 	for _, line := range strings.Split(pyvenvCfg, "\n") {
 		lineSplit := strings.SplitN(line, "=", 2)
@@ -188,5 +199,6 @@ func (p *Python) pyvenvCfgPrompt() string {
 			return value
 		}
 	}
+
 	return ""
 }
diff --git a/src/segments/sapling.go b/src/segments/sapling.go
index f9ee41f3..db6a0bec 100644
--- a/src/segments/sapling.go
+++ b/src/segments/sapling.go
@@ -4,6 +4,7 @@ import (
 	"strings"
 
 	"github.com/jandedobbeleer/oh-my-posh/src/runtime"
+	"github.com/jandedobbeleer/oh-my-posh/src/runtime/path"
 )
 
 // SaplingStatus represents part of the status of a Sapling repository
@@ -85,7 +86,7 @@ func (sl *Sapling) shouldDisplay() bool {
 	sl.rootDir = slDir.Path
 	// convert the worktree file path to a windows one when in a WSL shared folder
 	sl.realDir = strings.TrimSuffix(sl.convertToWindowsPath(slDir.Path), "/.sl")
-	sl.RepoName = runtime.Base(sl.env, sl.convertToLinuxPath(sl.realDir))
+	sl.RepoName = path.Base(sl.convertToLinuxPath(sl.realDir))
 	sl.setDir(slDir.Path)
 
 	return true
@@ -101,11 +102,13 @@ func (sl *Sapling) CacheKey() (string, bool) {
 }
 
 func (sl *Sapling) setDir(dir string) {
-	dir = runtime.ReplaceHomeDirPrefixWithTilde(sl.env, dir) // align with template PWD
+	dir = path.ReplaceHomeDirPrefixWithTilde(dir) // align with template PWD
+
 	if sl.env.GOOS() == runtime.WINDOWS {
 		sl.Dir = strings.TrimSuffix(dir, `\.sl`)
 		return
 	}
+
 	sl.Dir = strings.TrimSuffix(dir, "/.sl")
 }
 
diff --git a/src/shell/init.go b/src/shell/init.go
index 02f8c199..cb6eb072 100644
--- a/src/shell/init.go
+++ b/src/shell/init.go
@@ -9,6 +9,7 @@ import (
 	"github.com/google/uuid"
 	"github.com/jandedobbeleer/oh-my-posh/src/log"
 	"github.com/jandedobbeleer/oh-my-posh/src/runtime"
+	"github.com/jandedobbeleer/oh-my-posh/src/runtime/path"
 )
 
 const (
@@ -22,7 +23,7 @@ func getExecutablePath(env runtime.Environment) (string, error) {
 	}
 
 	if env.Flags().Strict {
-		return runtime.Base(env, executable), nil
+		return path.Base(executable), nil
 	}
 
 	// On Windows, it fails when the excutable is called in MSYS2 for example
diff --git a/src/template/cache.go b/src/template/cache.go
new file mode 100644
index 00000000..a3e50077
--- /dev/null
+++ b/src/template/cache.go
@@ -0,0 +1,112 @@
+package template
+
+import (
+	"encoding/json"
+	"strconv"
+	"strings"
+	"time"
+
+	"github.com/jandedobbeleer/oh-my-posh/src/cache"
+	"github.com/jandedobbeleer/oh-my-posh/src/log"
+	"github.com/jandedobbeleer/oh-my-posh/src/maps"
+	"github.com/jandedobbeleer/oh-my-posh/src/runtime"
+	"github.com/jandedobbeleer/oh-my-posh/src/runtime/path"
+)
+
+var (
+	Cache *cache.Template
+)
+
+func loadCache(vars maps.Simple) {
+	if !env.Flags().IsPrimary {
+		// Load the template cache for a non-primary prompt before rendering any templates.
+		if OK := restoreCache(env); OK {
+			return
+		}
+	}
+
+	Cache = new(cache.Template)
+
+	Cache.Root = env.Root()
+	Cache.Shell = env.Shell()
+	Cache.ShellVersion = env.Flags().ShellVersion
+	Cache.Code, _ = env.StatusCodes()
+	Cache.WSL = env.IsWsl()
+	Cache.Segments = maps.NewConcurrent()
+	Cache.PromptCount = env.Flags().PromptCount
+	Cache.Var = make(map[string]any)
+	Cache.Jobs = env.Flags().JobCount
+
+	if vars != nil {
+		Cache.Var = vars
+	}
+
+	pwd := env.Pwd()
+	Cache.PWD = path.ReplaceHomeDirPrefixWithTilde(pwd)
+
+	Cache.AbsolutePWD = pwd
+	if env.IsWsl() {
+		Cache.AbsolutePWD, _ = env.RunCommand("wslpath", "-m", pwd)
+	}
+
+	env.Flags().AbsolutePWD = Cache.AbsolutePWD
+	Cache.PSWD = env.Flags().PSWD
+
+	Cache.Folder = path.Base(pwd)
+	if env.GOOS() == runtime.WINDOWS && strings.HasSuffix(Cache.Folder, ":") {
+		Cache.Folder += `\`
+	}
+
+	Cache.UserName = env.User()
+	if host, err := env.Host(); err == nil {
+		Cache.HostName = host
+	}
+
+	goos := env.GOOS()
+	Cache.OS = goos
+	if goos == runtime.LINUX {
+		Cache.OS = env.Platform()
+	}
+
+	val := env.Getenv("SHLVL")
+	if shlvl, err := strconv.Atoi(val); err == nil {
+		Cache.SHLVL = shlvl
+	}
+}
+
+func restoreCache(env runtime.Environment) bool {
+	defer log.Trace(time.Now())
+
+	val, OK := env.Session().Get(cache.TEMPLATECACHE)
+	if !OK {
+		return false
+	}
+
+	var tmplCache cache.Template
+	err := json.Unmarshal([]byte(val), &tmplCache)
+	if err != nil {
+		log.Error(err)
+		return false
+	}
+
+	Cache = &tmplCache
+	Cache.Segments = Cache.SegmentsCache.ToConcurrent()
+
+	return true
+}
+
+func SaveCache() {
+	// only store this when in a primary prompt
+	// and when we have any extra prompt in the config
+	canSave := env.Flags().IsPrimary && env.Flags().HasExtra
+	if !canSave {
+		return
+	}
+
+	Cache.SegmentsCache = Cache.Segments.ToSimple()
+
+	templateCache, err := json.Marshal(Cache)
+	if err == nil {
+		env.Session().Set(cache.TEMPLATECACHE, string(templateCache), cache.ONEDAY)
+	}
+}
diff --git a/src/template/init.go b/src/template/init.go
index 6e439920..2b726549 100644
--- a/src/template/init.go
+++ b/src/template/init.go
@@ -3,6 +3,7 @@ package template
 import (
 	"sync"
 
+	"github.com/jandedobbeleer/oh-my-posh/src/maps"
 	"github.com/jandedobbeleer/oh-my-posh/src/runtime"
 )
 
@@ -23,7 +24,7 @@ var (
 	knownVariables []string
 )
 
-func Init(environment runtime.Environment) {
+func Init(environment runtime.Environment, vars maps.Simple) {
 	env = environment
 	shell = env.Shell()
 
@@ -55,4 +56,10 @@ func Init(environment runtime.Environment) {
 		"Data",
 		"Jobs",
 	}
+
+	if Cache != nil {
+		return
+	}
+
+	loadCache(vars)
 }
diff --git a/src/template/render_pool.go b/src/template/render_pool.go
index 1eb7f162..e4706410 100644
--- a/src/template/render_pool.go
+++ b/src/template/render_pool.go
@@ -8,6 +8,7 @@ import (
 	"text/template"
 
 	"github.com/jandedobbeleer/oh-my-posh/src/cache"
+	"github.com/jandedobbeleer/oh-my-posh/src/log"
 )
 
 type Data any
@@ -20,13 +21,8 @@ type context struct {
 
 func (c *context) init(t *Text) {
 	c.Data = t.Context
-
-	if c.Initialized {
-		return
-	}
-
 	c.Getenv = env.Getenv
-	c.Template = *env.TemplateCache()
+	c.Template = *Cache
 }
 
 var renderPool sync.Pool
@@ -54,7 +50,7 @@ func (t *renderer) release() {
 func (t *renderer) execute(text *Text) (string, error) {
 	tmpl, err := t.template.Parse(text.Template)
 	if err != nil {
-		env.Error(err)
+		log.Error(err)
 		return "", errors.New(InvalidTemplate)
 	}
 
@@ -62,7 +58,7 @@ func (t *renderer) execute(text *Text) (string, error) {
 
 	err = tmpl.Execute(&t.buffer, t.context)
 	if err != nil {
-		env.Error(err)
+		log.Error(err)
 		return "", errors.New(IncorrectTemplate)
 	}
 
diff --git a/src/template/text.go b/src/template/text.go
index 649f09d3..05b17add 100644
--- a/src/template/text.go
+++ b/src/template/text.go
@@ -6,6 +6,7 @@ import (
 	"strings"
 	"time"
 
+	"github.com/jandedobbeleer/oh-my-posh/src/log"
 	"github.com/jandedobbeleer/oh-my-posh/src/regex"
 )
 
@@ -15,7 +16,7 @@ type Text struct {
 }
 
 func (t *Text) Render() (string, error) {
-	defer env.Trace(time.Now(), t.Template)
+	defer log.Trace(time.Now(), t.Template)
 
 	if !strings.Contains(t.Template, "{{") || !strings.Contains(t.Template, "}}") {
 		return t.Template, nil


Test patch:
diff --git a/src/color/colors_test.go b/src/color/colors_test.go
index ad62ceea..6e399331 100644
--- a/src/color/colors_test.go
+++ b/src/color/colors_test.go
@@ -81,13 +81,11 @@ func TestAnsiRender(t *testing.T) {
 
 	for _, tc := range cases {
 		env := new(mock.Environment)
-		env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
-		env.On("TemplateCache").Return(&cache.Template{})
 		env.On("Getenv", "TERM_PROGRAM").Return(tc.Term)
 		env.On("Shell").Return("foo")
-		env.On("Trace", testify_.Anything, testify_.Anything).Return(nil)
 
-		template.Init(env)
+		template.Cache = new(cache.Template)
+		template.Init(env, nil)
 
 		ansi := Ansi("{{ if eq \"vscode\" .Env.TERM_PROGRAM }}#123456{{end}}")
 		got := ansi.ResolveTemplate()
diff --git a/src/config/config_test.go b/src/config/config_test.go
index 8bd18d5f..2c4a83bc 100644
--- a/src/config/config_test.go
+++ b/src/config/config_test.go
@@ -9,7 +9,6 @@ import (
 	"github.com/jandedobbeleer/oh-my-posh/src/template"
 
 	"github.com/stretchr/testify/assert"
-	testify_ "github.com/stretchr/testify/mock"
 )
 
 func TestGetPalette(t *testing.T) {
@@ -92,17 +91,14 @@ func TestGetPalette(t *testing.T) {
 
 	for _, tc := range cases {
 		env := &mock.Environment{}
-		env.On("TemplateCache").Return(&cache.Template{
-			Shell: "bash",
-		})
-		env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
 		env.On("Shell").Return("bash")
-		env.On("Trace", testify_.Anything, testify_.Anything).Return(nil)
 
-		template.Init(env)
+		template.Cache = &cache.Template{
+			Shell: "bash",
+		}
+		template.Init(env, nil)
 
 		cfg := &Config{
-			env:      env,
 			Palette:  tc.Palette,
 			Palettes: tc.Palettes,
 		}
diff --git a/src/prompt/engine_test.go b/src/prompt/engine_test.go
index 9ed88c89..4cf42b30 100644
--- a/src/prompt/engine_test.go
+++ b/src/prompt/engine_test.go
@@ -6,6 +6,7 @@ import (
 
 	"github.com/jandedobbeleer/oh-my-posh/src/cache"
 	"github.com/jandedobbeleer/oh-my-posh/src/config"
+	"github.com/jandedobbeleer/oh-my-posh/src/maps"
 	"github.com/jandedobbeleer/oh-my-posh/src/runtime"
 	"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
 	"github.com/jandedobbeleer/oh-my-posh/src/shell"
@@ -13,7 +14,6 @@ import (
 	"github.com/jandedobbeleer/oh-my-posh/src/terminal"
 
 	"github.com/stretchr/testify/assert"
-	testify_ "github.com/stretchr/testify/mock"
 )
 
 func TestCanWriteRPrompt(t *testing.T) {
@@ -64,7 +64,7 @@ func TestPrintPWD(t *testing.T) {
 		{Case: "OSC7", Config: terminal.OSC7, Expected: "\x1b]7;file://host/pwd\x1b\\"},
 		{Case: "OSC51", Config: terminal.OSC51, Expected: "\x1b]51;Auser@host:pwd\x1b\\"},
 		{Case: "Template (empty)", Config: "{{ if eq .Shell \"pwsh\" }}osc7{{ end }}"},
-		{Case: "Template (non empty)", Config: "{{ if eq .Shell \"shell\" }}osc7{{ end }}", Expected: "\x1b]7;file://host/pwd\x1b\\"},
+		{Case: "Template (non empty)", Shell: shell.GENERIC, Config: "{{ if eq .Shell \"shell\" }}osc7{{ end }}", Expected: "\x1b]7;file://host/pwd\x1b\\"},
 		{
 			Case:     "OSC99 Cygwin",
 			Pwd:      `C:\Users\user\Documents\GitHub\oh-my-posh`,
@@ -89,16 +89,16 @@ func TestPrintPWD(t *testing.T) {
 		env.On("Pwd").Return(tc.Pwd)
 		env.On("User").Return("user")
 		env.On("Shell").Return(tc.Shell)
-		env.On("Trace", testify_.Anything, testify_.Anything).Return(nil)
 		env.On("IsCygwin").Return(tc.Cygwin)
 		env.On("Host").Return("host", nil)
-		env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
-		env.On("TemplateCache").Return(&cache.Template{
-			Shell: "shell",
-		})
+
+		template.Cache = &cache.Template{
+			Shell:    tc.Shell,
+			Segments: maps.NewConcurrent(),
+		}
+		template.Init(env, nil)
 
 		terminal.Init(shell.GENERIC)
-		template.Init(env)
 
 		engine := &Engine{
 			Env: env,
@@ -121,15 +121,21 @@ func BenchmarkEngineRender(b *testing.B) {
 }
 
 func engineRender() {
+	cfg := config.Load("", shell.GENERIC, false)
+
 	env := &runtime.Terminal{}
-	env.Init()
+	env.Init(nil)
+
 	defer env.Close()
 
-	cfg := config.Load(env)
+	template.Cache = &cache.Template{
+		Segments: maps.NewConcurrent(),
+	}
+	template.Init(env, nil)
 
 	terminal.Init(shell.GENERIC)
 	terminal.BackgroundColor = cfg.TerminalBackground.ResolveTemplate()
-	terminal.Colors = cfg.MakeColors()
+	terminal.Colors = cfg.MakeColors(env)
 
 	engine := &Engine{
 		Config: cfg,
@@ -139,12 +145,6 @@ func engineRender() {
 	engine.Primary()
 }
 
-func BenchmarkEngineRenderPalette(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		engineRender()
-	}
-}
-
 func TestGetTitle(t *testing.T) {
 	cases := []struct {
 		Template      string
@@ -185,21 +185,21 @@ func TestGetTitle(t *testing.T) {
 		env.On("Pwd").Return(tc.Cwd)
 		env.On("Home").Return("/usr/home")
 		env.On("PathSeparator").Return(tc.PathSeparator)
-		env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
-		env.On("TemplateCache").Return(&cache.Template{
+		env.On("Getenv", "USERDOMAIN").Return("MyCompany")
+		env.On("Shell").Return(tc.ShellName)
+
+		terminal.Init(shell.GENERIC)
+
+		template.Cache = &cache.Template{
 			Shell:    tc.ShellName,
 			UserName: "MyUser",
 			Root:     tc.Root,
 			HostName: "MyHost",
 			PWD:      tc.Cwd,
 			Folder:   "vagrant",
-		})
-		env.On("Getenv", "USERDOMAIN").Return("MyCompany")
-		env.On("Shell").Return(tc.ShellName)
-		env.On("Trace", testify_.Anything, testify_.Anything).Return(nil)
-
-		terminal.Init(shell.GENERIC)
-		template.Init(env)
+			Segments: maps.NewConcurrent(),
+		}
+		template.Init(env, nil)
 
 		engine := &Engine{
 			Config: &config.Config{
@@ -249,19 +249,19 @@ func TestGetConsoleTitleIfGethostnameReturnsError(t *testing.T) {
 		env := new(mock.Environment)
 		env.On("Pwd").Return(tc.Cwd)
 		env.On("Home").Return("/usr/home")
-		env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
-		env.On("TemplateCache").Return(&cache.Template{
-			Shell:    tc.ShellName,
-			UserName: "MyUser",
-			Root:     tc.Root,
-			HostName: "",
-		})
 		env.On("Getenv", "USERDOMAIN").Return("MyCompany")
 		env.On("Shell").Return(tc.ShellName)
-		env.On("Trace", testify_.Anything, testify_.Anything).Return(nil)
 
 		terminal.Init(shell.GENERIC)
-		template.Init(env)
+
+		template.Cache = &cache.Template{
+			Shell:    tc.ShellName,
+			UserName: "MyUser",
+			Root:     tc.Root,
+			HostName: "",
+			Segments: maps.NewConcurrent(),
+		}
+		template.Init(env, nil)
 
 		engine := &Engine{
 			Config: &config.Config{
diff --git a/src/prompt/segments_test.go b/src/prompt/segments_test.go
index eae4e022..fc5231ee 100644
--- a/src/prompt/segments_test.go
+++ b/src/prompt/segments_test.go
@@ -10,7 +10,9 @@ import (
 )
 
 func TestRenderBlock(t *testing.T) {
-	engine := New(&runtime.Flags{})
+	engine := New(&runtime.Flags{
+		IsPrimary: true,
+	})
 	block := &config.Block{
 		Segments: []*config.Segment{
 			{
diff --git a/src/segments/os_test.go b/src/segments/os_test.go
index 30f91289..57124828 100644
--- a/src/segments/os_test.go
+++ b/src/segments/os_test.go
@@ -6,6 +6,7 @@ import (
 	"github.com/jandedobbeleer/oh-my-posh/src/cache"
 	"github.com/jandedobbeleer/oh-my-posh/src/properties"
 	"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
+	"github.com/jandedobbeleer/oh-my-posh/src/template"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -89,9 +90,6 @@ func TestOSInfo(t *testing.T) {
 		env := new(mock.Environment)
 		env.On("GOOS").Return(tc.GOOS)
 		env.On("Platform").Return(tc.Platform)
-		env.On("TemplateCache").Return(&cache.Template{
-			WSL: tc.IsWSL,
-		})
 
 		props := properties.Map{
 			DisplayDistroName: tc.DisplayDistroName,
@@ -106,6 +104,10 @@ func TestOSInfo(t *testing.T) {
 		osInfo := &Os{}
 		osInfo.Init(props, env)
 
+		template.Cache = &cache.Template{
+			WSL: tc.IsWSL,
+		}
+
 		_ = osInfo.Enabled()
 		assert.Equal(t, tc.ExpectedString, renderTemplate(env, osInfo.Template(), osInfo), tc.Case)
 	}
diff --git a/src/segments/path_test.go b/src/segments/path_test.go
index 511c37b1..53bae5c4 100644
--- a/src/segments/path_test.go
+++ b/src/segments/path_test.go
@@ -1,7 +1,6 @@
 package segments
 
 import (
-	"errors"
 	"strings"
 	"testing"
 
@@ -26,25 +25,12 @@ const (
 )
 
 func renderTemplateNoTrimSpace(env *mock.Environment, segmentTemplate string, context any) string {
-	found := false
-	for _, call := range env.Mock.ExpectedCalls {
-		if call.Method == "TemplateCache" {
-			found = true
-			break
-		}
-	}
-
-	if !found {
-		env.On("TemplateCache").Return(&cache.Template{})
-	}
-
-	env.On("Error", testify_.Anything)
-	env.On("Debug", testify_.Anything)
-	env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
-	env.On("Trace", testify_.Anything, testify_.Anything).Return(nil)
 	env.On("Shell").Return("foo")
 
-	template.Init(env)
+	if template.Cache == nil {
+		template.Cache = &cache.Template{}
+	}
+	template.Init(env, nil)
 
 	tmpl := &template.Text{
 		Template: segmentTemplate,
@@ -63,91 +49,18 @@ func renderTemplate(env *mock.Environment, segmentTemplate string, context any)
 	return strings.TrimSpace(renderTemplateNoTrimSpace(env, segmentTemplate, context))
 }
 
+type testParentCase struct {
+	Case                string
+	Expected            string
+	HomePath            string
+	Pwd                 string
+	GOOS                string
+	PathSeparator       string
+	FolderSeparatorIcon string
+}
+
 func TestParent(t *testing.T) {
-	cases := []struct {
-		Case                string
-		Expected            string
-		HomePath            string
-		Pwd                 string
-		GOOS                string
-		PathSeparator       string
-		FolderSeparatorIcon string
-	}{
-		{
-			Case:          "Inside Home folder",
-			Expected:      "~/",
-			HomePath:      homeDir,
-			Pwd:           homeDir + "/test",
-			GOOS:          runtime.DARWIN,
-			PathSeparator: "/",
-		},
-		{
-			Case:          "Home folder",
-			HomePath:      homeDir,
-			Pwd:           homeDir,
-			GOOS:          runtime.DARWIN,
-			PathSeparator: "/",
-		},
-		{
-			Case:          "Home folder with a trailing separator",
-			HomePath:      homeDir,
-			Pwd:           homeDir + "/",
-			GOOS:          runtime.DARWIN,
-			PathSeparator: "/",
-		},
-		{
-			Case:          "Root",
-			HomePath:      homeDir,
-			Pwd:           "/",
-			GOOS:          runtime.DARWIN,
-			PathSeparator: "/",
-		},
-		{
-			Case:          "Root + 1",
-			Expected:      "/",
-			HomePath:      homeDir,
-			Pwd:           "/usr",
-			GOOS:          runtime.DARWIN,
-			PathSeparator: "/",
-		},
-		{
-			Case:          "Windows Home folder",
-			HomePath:      homeDirWindows,
-			Pwd:           homeDirWindows,
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: "\\",
-		},
-		{
-			Case:          "Windows drive root",
-			HomePath:      homeDirWindows,
-			Pwd:           "C:",
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: "\\",
-		},
-		{
-			Case:          "Windows drive root with a trailing separator",
-			HomePath:      homeDirWindows,
-			Pwd:           "C:\\",
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: "\\",
-		},
-		{
-			Case:          "Windows drive root + 1",
-			Expected:      "C:\\",
-			HomePath:      homeDirWindows,
-			Pwd:           "C:\\test",
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: "\\",
-		},
-		{
-			Case:          "PSDrive root",
-			HomePath:      homeDirWindows,
-			Pwd:           "HKLM:",
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: "\\",
-		},
-	}
-	for _, tc := range cases {
+	for _, tc := range testParentCases {
 		env := new(mock.Environment)
 		env.On("Home").Return(tc.HomePath)
 		env.On("Pwd").Return(tc.Pwd)
@@ -170,606 +83,27 @@ func TestParent(t *testing.T) {
 	}
 }
 
-func TestAgnosterPathStyles(t *testing.T) {
-	cases := []struct {
-		CygpathError        error
-		GOOS                string
-		Shell               string
-		Pswd                string
-		Pwd                 string
-		PathSeparator       string
-		HomeIcon            string
-		HomePath            string
-		Style               string
-		FolderSeparatorIcon string
-		Cygpath             string
-		Expected            string
-		MaxDepth            int
-		MaxWidth            int
-		HideRootLocation    bool
-		Cygwin              bool
-	}{
-		{
-			Style:               Unique,
-			Expected:            "~ > a > ab > abcd",
-			HomePath:            homeDir,
-			Pwd:                 homeDir + "/ab/abc/abcd",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               Unique,
-			Expected:            "~ > a > .a > abcd",
-			HomePath:            homeDir,
-			Pwd:                 homeDir + "/ab/.abc/abcd",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               Unique,
-			Expected:            "~ > a > ab > abcd",
-			HomePath:            homeDir,
-			Pwd:                 homeDir + "/ab/ab/abcd",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               Unique,
-			Expected:            "C > a > ab > abcd",
-			HomePath:            homeDirWindows,
-			Pwd:                 "C:\\ab\\ab\\abcd",
-			GOOS:                runtime.WINDOWS,
-			PathSeparator:       "\\",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               Unique,
-			Expected:            "a",
-			HomePath:            homeDir,
-			Pwd:                 "/ab",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-		},
-
-		{
-			Style:               Powerlevel,
-			Expected:            "t > w > o > a > v > l > p > wh > we > i > wa > th > the > d > f > u > it > c > to > a > co > stream",
-			HomePath:            homeDir,
-			Pwd:                 "/there/was/once/a/very/long/path/which/wended/its/way/through/the/dark/forest/until/it/came/to/a/cold/stream",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-			MaxWidth:            20,
-		},
-		{
-			Style:               Powerlevel,
-			Expected:            "t > w > o > a > v > l > p > which > wended > its > way > through > the",
-			HomePath:            homeDir,
-			Pwd:                 "/there/was/once/a/very/long/path/which/wended/its/way/through/the",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-			MaxWidth:            70,
-		},
-		{
-			Style:               Powerlevel,
-			Expected:            "var/cache/pacman",
-			HomePath:            homeDir,
-			Pwd:                 "/var/cache/pacman",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: "/",
-			MaxWidth:            50,
-		},
-
-		{
-			Style:               Letter,
-			Expected:            "~",
-			HomePath:            homeDir,
-			Pwd:                 homeDir,
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               Letter,
-			Expected:            "~ > a > w > man",
-			HomePath:            homeDir,
-			Pwd:                 homeDir + "/ab/whatever/man",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               Letter,
-			Expected:            "u > b > a > w > man",
-			HomePath:            homeDir,
-			Pwd:                 "/usr/burp/ab/whatever/man",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               Letter,
-			Expected:            "u > .b > a > w > man",
-			HomePath:            homeDir,
-			Pwd:                 "/usr/.burp/ab/whatever/man",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               Letter,
-			Expected:            "u > .b > a > .w > man",
-			HomePath:            homeDir,
-			Pwd:                 "/usr/.burp/ab/.whatever/man",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               Letter,
-			Expected:            "u > .b > a > ._w > man",
-			HomePath:            homeDir,
-			Pwd:                 "/usr/.burp/ab/._whatever/man",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               Letter,
-			Expected:            "u > .ä > ū > .w > man",
-			HomePath:            homeDir,
-			Pwd:                 "/usr/.äufbau/ūmgebung/.whatever/man",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               Letter,
-			Expected:            "u > .b > 1 > .w > man",
-			HomePath:            homeDir,
-			Pwd:                 "/usr/.burp/12345/.whatever/man",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               Letter,
-			Expected:            "u > .b > 1 > .w > man",
-			HomePath:            homeDir,
-			Pwd:                 "/usr/.burp/12345abc/.whatever/man",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               Letter,
-			Expected:            "u > .b > __p > .w > man",
-			HomePath:            homeDir,
-			Pwd:                 "/usr/.burp/__pycache__/.whatever/man",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               Letter,
-			Expected:            "➼ > .w > man",
-			HomePath:            homeDir,
-			Pwd:                 "/➼/.whatever/man",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               Letter,
-			Expected:            "➼ s > .w > man",
-			HomePath:            homeDir,
-			Pwd:                 "/➼ something/.whatever/man",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               Letter,
-			Expected:            "C: > ",
-			HomePath:            homeDirWindows,
-			Pwd:                 "C:\\",
-			GOOS:                runtime.WINDOWS,
-			PathSeparator:       "\\",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               Letter,
-			Expected:            "C > s > .w > man",
-			HomePath:            homeDirWindows,
-			Pwd:                 "C:\\something\\.whatever\\man",
-			GOOS:                runtime.WINDOWS,
-			PathSeparator:       "\\",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               Letter,
-			Expected:            "~ > s > man",
-			HomePath:            homeDirWindows,
-			Pwd:                 homeDirWindows + "\\something\\man",
-			GOOS:                runtime.WINDOWS,
-			PathSeparator:       "\\",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               Letter,
-			Expected:            "w",
-			HomePath:            homeDir,
-			Pwd:                 "/whatever",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-		},
-
-		{
-			Style:               Mixed,
-			Expected:            "~ > .. > man",
-			HomePath:            homeDir,
-			Pwd:                 homeDir + "/whatever/man",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               Mixed,
-			Expected:            "~ > ab > .. > man",
-			HomePath:            homeDir,
-			Pwd:                 homeDir + "/ab/whatever/man",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               Mixed,
-			Expected:            "usr > foo > bar > .. > man",
-			HomePath:            homeDir,
-			Pwd:                 "/usr/foo/bar/foobar/man",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               Mixed,
-			Expected:            "whatever > .. > foo > bar",
-			HomePath:            homeDir,
-			Pwd:                 "/whatever/foobar/foo/bar",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               Mixed,
-			Expected:            "C: > .. > foo > .. > man",
-			HomePath:            homeDirWindows,
-			Pwd:                 "C:\\Users\\foo\\foobar\\man",
-			GOOS:                runtime.WINDOWS,
-			PathSeparator:       "\\",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               Mixed,
-			Expected:            "c > .. > foo > .. > man",
-			HomePath:            homeDirWindows,
-			Pwd:                 "C:\\Users\\foo\\foobar\\man",
-			GOOS:                runtime.WINDOWS,
-			Shell:               shell.BASH,
-			Cygwin:              true,
-			Cygpath:             "/c/Users/foo/foobar/man",
-			PathSeparator:       "\\",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               Mixed,
-			Expected:            "C: > .. > foo > .. > man",
-			HomePath:            homeDirWindows,
-			Pwd:                 "C:\\Users\\foo\\foobar\\man",
-			GOOS:                runtime.WINDOWS,
-			Shell:               shell.BASH,
-			CygpathError:        errors.New("oh no"),
-			PathSeparator:       "\\",
-			FolderSeparatorIcon: " > ",
-		},
-
-		{
-			Style:               AgnosterFull,
-			Expected:            "usr > location > whatever",
-			HomePath:            homeDir,
-			Pwd:                 "/usr/location/whatever",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               AgnosterFull,
-			Expected:            "PSDRIVE: | src",
-			HomePath:            homeDir,
-			Pwd:                 "/foo",
-			Pswd:                "PSDRIVE:/src",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " | ",
-		},
-
-		{
-			Style:               AgnosterShort,
-			Expected:            ".. | src | init",
-			HomePath:            homeDir,
-			Pwd:                 "/foo",
-			Pswd:                "PSDRIVE:/src/init",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " | ",
-			MaxDepth:            2,
-			HideRootLocation:    true,
-		},
-		{
-			Style:               AgnosterShort,
-			Expected:            "usr > foo > bar > man",
-			HomePath:            homeDir,
-			Pwd:                 "/usr/foo/bar/man",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-			MaxDepth:            3,
-		},
-		{
-			Style:               AgnosterShort,
-			Expected:            "PSDRIVE: | src",
-			HomePath:            homeDir,
-			Pwd:                 "/foo",
-			Pswd:                "PSDRIVE:/src",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " | ",
-			MaxDepth:            2,
-			HideRootLocation:    true,
-		},
-		{
-			Style:               AgnosterShort,
-			Expected:            "~ > projects",
-			HomePath:            homeDir,
-			Pwd:                 homeDir + "/projects",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               AgnosterShort,
-			Expected:            "\\\\localhost\\c$ > some",
-			HomePath:            homeDirWindows,
-			Pwd:                 "\\\\localhost\\c$\\some",
-			GOOS:                runtime.WINDOWS,
-			PathSeparator:       "\\",
-			FolderSeparatorIcon: " > ",
-		},
+type testAgnosterPathStyleCase struct {
+	CygpathError        error
+	GOOS                string
+	Shell               string
+	Pswd                string
+	Pwd                 string
+	PathSeparator       string
+	HomeIcon            string
+	HomePath            string
+	Style               string
+	FolderSeparatorIcon string
+	Cygpath             string
+	Expected            string
+	MaxDepth            int
+	MaxWidth            int
+	HideRootLocation    bool
+	Cygwin              bool
+}
 
-		{
-			Style:               AgnosterShort,
-			Expected:            "~",
-			HomePath:            homeDir,
-			Pwd:                 homeDir,
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-			MaxDepth:            1,
-			HideRootLocation:    true,
-		},
-		{
-			Style:               AgnosterShort,
-			Expected:            "\\\\localhost\\c$",
-			HomePath:            homeDirWindows,
-			Pwd:                 "\\\\localhost\\c$",
-			GOOS:                runtime.WINDOWS,
-			PathSeparator:       "\\",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               AgnosterShort,
-			Expected:            "usr > .. > bar > man",
-			HomePath:            homeDir,
-			Pwd:                 "/usr/foo/bar/man",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-			MaxDepth:            2,
-		},
-		{
-			Style:               AgnosterShort,
-			Expected:            "~ > .. > man",
-			HomePath:            homeDir,
-			Pwd:                 homeDir + "/whatever/man",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               AgnosterShort,
-			Expected:            "usr > .. > man",
-			HomePath:            homeDir,
-			Pwd:                 "/usr/location/whatever/man",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               AgnosterShort,
-			Expected:            ".. > bar > man",
-			HomePath:            homeDirWindows,
-			Pwd:                 homeDirWindows + fooBarMan,
-			GOOS:                runtime.WINDOWS,
-			PathSeparator:       "\\",
-			FolderSeparatorIcon: " > ",
-			MaxDepth:            2,
-			HideRootLocation:    true,
-		},
-		{
-			Style:               AgnosterShort,
-			Expected:            "~ > .. > bar > man",
-			HomePath:            homeDir,
-			Pwd:                 homeDir + "/foo/bar/man",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-			MaxDepth:            2,
-		},
-		{
-			Style:               AgnosterShort,
-			Expected:            "~ > foo > bar > man",
-			HomePath:            homeDir,
-			Pwd:                 homeDir + "/foo/bar/man",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-			MaxDepth:            3,
-		},
-		{
-			Style:               AgnosterShort,
-			Expected:            "PSDRIVE: | .. | init",
-			HomePath:            homeDir,
-			Pwd:                 "/foo",
-			Pswd:                "PSDRIVE:/src/init",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " | ",
-		},
-		{
-			Style:               AgnosterShort,
-			Expected:            ".. > foo",
-			HomePath:            homeDir,
-			Pwd:                 homeDir + "/foo",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-			MaxDepth:            1,
-			HideRootLocation:    true,
-		},
-		{
-			Style:               AgnosterShort,
-			Expected:            ".. > bar > man",
-			HomePath:            homeDir,
-			Pwd:                 homeDir + "/bar/man",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-			MaxDepth:            2,
-			HideRootLocation:    true,
-		},
-		{
-			Style:               AgnosterShort,
-			Expected:            ".. > foo > bar > man",
-			HomePath:            homeDir,
-			Pwd:                 "/usr/foo/bar/man",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-			MaxDepth:            3,
-			HideRootLocation:    true,
-		},
-		{
-			Style:               AgnosterShort,
-			Expected:            "~ > foo",
-			HomePath:            homeDir,
-			Pwd:                 homeDir + "/foo",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-			MaxDepth:            2,
-			HideRootLocation:    true,
-		},
-		{
-			Style:               AgnosterShort,
-			Expected:            "~ > foo > bar",
-			HomePath:            homeDir,
-			Pwd:                 homeDir + "/foo/bar",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " > ",
-			MaxDepth:            3,
-			HideRootLocation:    true,
-		},
-		{
-			Style:               AgnosterShort,
-			Expected:            "C: | ",
-			HomePath:            homeDir,
-			Pwd:                 "/mnt/c",
-			Pswd:                "C:",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " | ",
-			MaxDepth:            2,
-			HideRootLocation:    true,
-		},
-		{
-			Style:               AgnosterShort,
-			Expected:            "~ | space foo",
-			HomePath:            homeDir,
-			Pwd:                 homeDir + "/space foo",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " | ",
-			MaxDepth:            2,
-			HideRootLocation:    true,
-		},
-		{
-			Style:               AgnosterShort,
-			Expected:            ".. | space foo",
-			HomePath:            homeDir,
-			Pwd:                 homeDir + "/space foo",
-			PathSeparator:       "/",
-			FolderSeparatorIcon: " | ",
-			MaxDepth:            1,
-			HideRootLocation:    true,
-		},
-		{
-			Style:               AgnosterShort,
-			Expected:            "C: > ",
-			HomePath:            homeDirWindows,
-			Pwd:                 "C:",
-			GOOS:                runtime.WINDOWS,
-			PathSeparator:       "\\",
-			FolderSeparatorIcon: " > ",
-		},
-		{
-			Style:               AgnosterShort,
-			Expected:            "C: > .. > bar > man",
-			HomePath:            homeDirWindows,
-			Pwd:                 "C:\\usr\\foo\\bar\\man",
-			GOOS:                runtime.WINDOWS,
-			PathSeparator:       "\\",
-			FolderSeparatorIcon: " > ",
-			MaxDepth:            2,
-		},
-		{
-			Style:               AgnosterShort,
-			Expected:            "C: > .. > foo > bar > man",
-			HomePath:            homeDirWindows,
-			Pwd:                 "C:\\usr\\foo\\bar\\man",
-			GOOS:                runtime.WINDOWS,
-			PathSeparator:       "\\",
-			FolderSeparatorIcon: " > ",
-			MaxDepth:            3,
-		},
-		{
-			Style:               AgnosterShort,
-			Expected:            "~ > .. > bar > man",
-			HomePath:            homeDirWindows,
-			Pwd:                 homeDirWindows + fooBarMan,
-			GOOS:                runtime.WINDOWS,
-			PathSeparator:       "\\",
-			FolderSeparatorIcon: " > ",
-			MaxDepth:            2,
-		},
-		{
-			Style:               AgnosterShort,
-			Expected:            "~ > foo > bar > man",
-			HomePath:            homeDirWindows,
-			Pwd:                 homeDirWindows + fooBarMan,
-			GOOS:                runtime.WINDOWS,
-			PathSeparator:       "\\",
-			FolderSeparatorIcon: " > ",
-			MaxDepth:            3,
-		},
-		{
-			Style:               AgnosterShort,
-			Expected:            "~",
-			HomePath:            homeDirWindows,
-			Pwd:                 homeDirWindows,
-			GOOS:                runtime.WINDOWS,
-			PathSeparator:       "\\",
-			FolderSeparatorIcon: " > ",
-			MaxDepth:            1,
-			HideRootLocation:    true,
-		},
-		{
-			Style:               AgnosterShort,
-			Expected:            ".. > foo",
-			HomePath:            homeDirWindows,
-			Pwd:                 homeDirWindows + "\\foo",
-			GOOS:                runtime.WINDOWS,
-			PathSeparator:       "\\",
-			FolderSeparatorIcon: " > ",
-			MaxDepth:            1,
-			HideRootLocation:    true,
-		},
-		{
-			Style:               AgnosterShort,
-			Expected:            "~ > foo",
-			HomePath:            homeDirWindows,
-			Pwd:                 homeDirWindows + "\\foo",
-			GOOS:                runtime.WINDOWS,
-			PathSeparator:       "\\",
-			FolderSeparatorIcon: " > ",
-			MaxDepth:            2,
-			HideRootLocation:    true,
-		},
-	}
-	for _, tc := range cases {
+func TestAgnosterPathStyles(t *testing.T) {
+	for _, tc := range testAgnosterPathStyleCases {
 		env := new(mock.Environment)
 		env.On("PathSeparator").Return(tc.PathSeparator)
 		env.On("Home").Return(tc.HomePath)
@@ -815,94 +149,22 @@ func TestAgnosterPathStyles(t *testing.T) {
 	}
 }
 
-func TestFullAndFolderPath(t *testing.T) {
-	cases := []struct {
-		Style                  string
-		HomePath               string
-		FolderSeparatorIcon    string
-		Pwd                    string
-		Pswd                   string
-		Expected               string
-		GOOS                   string
-		PathSeparator          string
-		Template               string
-		StackCount             int
-		DisableMappedLocations bool
-	}{
-		{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", Expected: "/"},
-		{Style: Full, Pwd: "/", Expected: "/"},
-		{Style: Full, Pwd: homeDir, Expected: "~"},
-		{Style: Full, Pwd: homeDir + abc, Expected: "~/abc"},
-		{Style: Full, Pwd: homeDir + abc, Expected: homeDir + abc, DisableMappedLocations: true},
-		{Style: Full, Pwd: abcd, Expected: abcd},
-
-		{Style: Full, FolderSeparatorIcon: "|", Pwd: homeDir, Expected: "~"},
-		{Style: Full, FolderSeparatorIcon: "|", Pwd: homeDir, Expected: "/home|someone", DisableMappedLocations: true},
-		{Style: Full, FolderSeparatorIcon: "|", Pwd: homeDir + abc, Expected: "~|abc"},
-		{Style: Full, FolderSeparatorIcon: "|", Pwd: abcd, Expected: "/a|b|c|d"},
-
-		{Style: FolderType, Pwd: "/", Expected: "/"},
-		{Style: FolderType, Pwd: homeDir, Expected: "~"},
-		{Style: FolderType, Pwd: homeDir, Expected: "someone", DisableMappedLocations: true},
-		{Style: FolderType, Pwd: homeDir + abc, Expected: "abc"},
-		{Style: FolderType, Pwd: abcd, Expected: "d"},
-
-		{Style: FolderType, FolderSeparatorIcon: "|", Pwd: "/", Expected: "/"},
-		{Style: FolderType, FolderSeparatorIcon: "|", Pwd: homeDir, Expected: "~"},
-		{Style: FolderType, FolderSeparatorIcon: "|", Pwd: homeDir, Expected: "someone", DisableMappedLocations: true},
-		{Style: FolderType, FolderSeparatorIcon: "|", Pwd: homeDir + abc, Expected: "abc"},
-		{Style: FolderType, FolderSeparatorIcon: "|", Pwd: abcd, Expected: "d"},
-
-		// for Windows paths
-		{Style: FolderType, FolderSeparatorIcon: "\\", Pwd: "C:\\", Expected: "C:\\", PathSeparator: "\\", GOOS: runtime.WINDOWS},
-		{Style: FolderType, FolderSeparatorIcon: "\\", Pwd: "\\\\localhost\\d$", Expected: "\\\\localhost\\d$", PathSeparator: "\\", GOOS: runtime.WINDOWS},
-		{Style: FolderType, FolderSeparatorIcon: "\\", Pwd: homeDirWindows, Expected: "~", PathSeparator: "\\", GOOS: runtime.WINDOWS},
-		{Style: Full, FolderSeparatorIcon: "\\", Pwd: homeDirWindows, Expected: "~", PathSeparator: "\\", GOOS: runtime.WINDOWS},
-		{Style: Full, FolderSeparatorIcon: "\\", Pwd: homeDirWindows + "\\abc", Expected: "~\\abc", PathSeparator: "\\", GOOS: runtime.WINDOWS},
-		{Style: Full, FolderSeparatorIcon: "\\", Pwd: "C:\\Users\\posh", Expected: "C:\\Users\\posh", PathSeparator: "\\", GOOS: runtime.WINDOWS},
-
-		// StackCountEnabled=true and StackCount=2
-		{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", StackCount: 2, Expected: "2 /"},
-		{Style: Full, Pwd: "/", StackCount: 2, Expected: "2 /"},
-		{Style: Full, Pwd: homeDir, StackCount: 2, Expected: "2 ~"},
-		{Style: Full, Pwd: homeDir + abc, StackCount: 2, Expected: "2 ~/abc"},
-		{Style: Full, Pwd: homeDir + abc, StackCount: 2, Expected: "2 " + homeDir + abc, DisableMappedLocations: true},
-		{Style: Full, Pwd: abcd, StackCount: 2, Expected: "2 /a/b/c/d"},
-
-		// StackCountEnabled=false and StackCount=2
-		{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", Template: "{{ .Path }}", StackCount: 2, Expected: "/"},
-		{Style: Full, Pwd: "/", Template: "{{ .Path }}", StackCount: 2, Expected: "/"},
-		{Style: Full, Pwd: homeDir, Template: "{{ .Path }}", StackCount: 2, Expected: "~"},
-
-		{Style: Full, Pwd: homeDir + abc, Template: "{{ .Path }}", StackCount: 2, Expected: homeDir + abc, DisableMappedLocations: true},
-		{Style: Full, Pwd: abcd, Template: "{{ .Path }}", StackCount: 2, Expected: abcd},
-
-		// StackCountEnabled=true and StackCount=0
-		{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", StackCount: 0, Expected: "/"},
-		{Style: Full, Pwd: "/", StackCount: 0, Expected: "/"},
-		{Style: Full, Pwd: homeDir, StackCount: 0, Expected: "~"},
-		{Style: Full, Pwd: homeDir + abc, StackCount: 0, Expected: "~/abc"},
-		{Style: Full, Pwd: homeDir + abc, StackCount: 0, Expected: homeDir + abc, DisableMappedLocations: true},
-		{Style: Full, Pwd: abcd, StackCount: 0, Expected: abcd},
-
-		// StackCountEnabled=true and StackCount<0
-		{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", StackCount: -1, Expected: "/"},
-		{Style: Full, Pwd: "/", StackCount: -1, Expected: "/"},
-		{Style: Full, Pwd: homeDir, StackCount: -1, Expected: "~"},
-		{Style: Full, Pwd: homeDir + abc, StackCount: -1, Expected: "~/abc"},
-		{Style: Full, Pwd: homeDir + abc, StackCount: -1, Expected: homeDir + abc, DisableMappedLocations: true},
-		{Style: Full, Pwd: abcd, StackCount: -1, Expected: abcd},
-
-		// StackCountEnabled=true and StackCount not set
-		{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", Expected: "/"},
-		{Style: Full, Pwd: "/", Expected: "/"},
-		{Style: Full, Pwd: homeDir, Expected: "~"},
-		{Style: Full, Pwd: homeDir + abc, Expected: "~/abc"},
-		{Style: Full, Pwd: homeDir + abc, Expected: homeDir + abc, DisableMappedLocations: true},
-		{Style: Full, Pwd: abcd, Expected: abcd},
-	}
+type testFullAndFolderPathCase struct {
+	Style                  string
+	HomePath               string
+	FolderSeparatorIcon    string
+	Pwd                    string
+	Pswd                   string
+	Expected               string
+	GOOS                   string
+	PathSeparator          string
+	Template               string
+	StackCount             int
+	DisableMappedLocations bool
+}
 
-	for _, tc := range cases {
+func TestFullAndFolderPath(t *testing.T) {
+	for _, tc := range testFullAndFolderPathCases {
 		env := new(mock.Environment)
 		if len(tc.PathSeparator) == 0 {
 			tc.PathSeparator = "/"
@@ -947,25 +209,16 @@ func TestFullAndFolderPath(t *testing.T) {
 	}
 }
 
-func TestFullPathCustomMappedLocations(t *testing.T) {
-	cases := []struct {
-		Pwd             string
-		MappedLocations map[string]string
-		GOOS            string
-		PathSeparator   string
-		Expected        string
-	}{
-		{Pwd: homeDir + "/d", MappedLocations: map[string]string{"{{ .Env.HOME }}/d": "#"}, Expected: "#"},
-		{Pwd: abcd, MappedLocations: map[string]string{abcd: "#"}, Expected: "#"},
-		{Pwd: "\\a\\b\\c\\d", MappedLocations: map[string]string{"\\a\\b": "#"}, GOOS: runtime.WINDOWS, PathSeparator: "\\", Expected: "#\\c\\d"},
-		{Pwd: abcd, MappedLocations: map[string]string{"/a/b": "#"}, Expected: "#/c/d"},
-		{Pwd: abcd, MappedLocations: map[string]string{"/a/b": "/e/f"}, Expected: "/e/f/c/d"},
-		{Pwd: homeDir + abcd, MappedLocations: map[string]string{"~/a/b": "#"}, Expected: "#/c/d"},
-		{Pwd: "/a" + homeDir + "/b/c/d", MappedLocations: map[string]string{"/a~": "#"}, Expected: "/a" + homeDir + "/b/c/d"},
-		{Pwd: homeDir + abcd, MappedLocations: map[string]string{"/a/b": "#"}, Expected: homeDir + abcd},
-	}
+type testFullPathCustomMappedLocationsCase struct {
+	Pwd             string
+	MappedLocations map[string]string
+	GOOS            string
+	PathSeparator   string
+	Expected        string
+}
 
-	for _, tc := range cases {
+func TestFullPathCustomMappedLocations(t *testing.T) {
+	for _, tc := range testFullPathCustomMappedLocationsCases {
 		env := new(mock.Environment)
 		env.On("Home").Return(homeDir)
 		env.On("Pwd").Return(tc.Pwd)
@@ -987,12 +240,10 @@ func TestFullPathCustomMappedLocations(t *testing.T) {
 
 		env.On("Flags").Return(args)
 		env.On("Shell").Return(shell.GENERIC)
-		env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
-		env.On("TemplateCache").Return(&cache.Template{})
 		env.On("Getenv", "HOME").Return(homeDir)
-		env.On("Trace", testify_.Anything, testify_.Anything).Return(nil)
 
-		template.Init(env)
+		template.Cache = new(cache.Template)
+		template.Init(env, nil)
 
 		props := properties.Map{
 			properties.Style:       Full,
@@ -1011,194 +262,19 @@ func TestFullPathCustomMappedLocations(t *testing.T) {
 	}
 }
 
-func TestFolderPathCustomMappedLocations(t *testing.T) {
-	pwd := abcd
-	env := new(mock.Environment)
-	env.On("PathSeparator").Return("/")
-	env.On("Home").Return(homeDir)
-	env.On("Pwd").Return(pwd)
-	env.On("GOOS").Return("")
-	args := &runtime.Flags{
-		PSWD: pwd,
-	}
-	env.On("Flags").Return(args)
-	env.On("Shell").Return(shell.GENERIC)
-	env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
-	env.On("Trace", testify_.Anything, testify_.Anything).Return(nil)
-
-	template.Init(env)
-
-	props := properties.Map{
-		properties.Style: FolderType,
-		MappedLocations: map[string]string{
-			abcd: "#",
-		},
-	}
-
-	path := &Path{}
-	path.Init(props, env)
-
-	path.setPaths()
-	path.setStyle()
-
-	got := renderTemplateNoTrimSpace(env, "{{ .Path }}", path)
-	assert.Equal(t, "#", got)
+type testAgnosterPathCase struct {
+	Case           string
+	Expected       string
+	Home           string
+	PWD            string
+	GOOS           string
+	PathSeparator  string
+	Cycle          []string
+	ColorSeparator bool
 }
 
 func TestAgnosterPath(t *testing.T) {
-	cases := []struct {
-		Case           string
-		Expected       string
-		Home           string
-		PWD            string
-		GOOS           string
-		PathSeparator  string
-		Cycle          []string
-		ColorSeparator bool
-	}{
-		{
-			Case:          "Windows registry drive case sensitive",
-			Expected:      "\uf013 > f > magnetic:TOAST",
-			Home:          homeDirWindows,
-			PWD:           "HKLM:\\SOFTWARE\\magnetic:TOAST\\",
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: "\\",
-		},
-		{
-			Case:          "Windows outside home",
-			Expected:      "C: > f > f > location",
-			Home:          homeDirWindows,
-			PWD:           "C:\\Program Files\\Go\\location",
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: "\\",
-		},
-		{
-			Case:          "Windows oustide home",
-			Expected:      "~ > f > f > location",
-			Home:          homeDirWindows,
-			PWD:           homeDirWindows + "\\Documents\\Bill\\location",
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: "\\",
-		},
-		{
-			Case:          "Windows inside home zero levels",
-			Expected:      "C: > location",
-			Home:          homeDirWindows,
-			PWD:           "C:\\location",
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: "\\",
-		},
-		{
-			Case:          "Windows inside home one level",
-			Expected:      "C: > f > location",
-			Home:          homeDirWindows,
-			PWD:           "C:\\Program Files\\location",
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: "\\",
-		},
-		{
-			Case:          "Windows lower case drive letter",
-			Expected:      "C: > Windows",
-			Home:          homeDirWindows,
-			PWD:           "C:\\Windows\\",
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: "\\",
-		},
-		{
-			Case:          "Windows lower case drive letter (other)",
-			Expected:      "P: > Other",
-			Home:          homeDirWindows,
-			PWD:           "P:\\Other\\",
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: "\\",
-		},
-		{
-			Case:          "Windows lower word drive",
-			Expected:      "some: > some",
-			Home:          homeDirWindows,
-			PWD:           "some:\\some\\",
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: "\\",
-		},
-		{
-			Case:          "Windows lower word drive (ending with c)",
-			Expected:      "src: > source",
-			Home:          homeDirWindows,
-			PWD:           "src:\\source\\",
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: "\\",
-		},
-		{
-			Case:          "Windows lower word drive (arbitrary cases)",
-			Expected:      "sRc: > source",
-			Home:          homeDirWindows,
-			PWD:           "sRc:\\source\\",
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: "\\",
-		},
-		{
-			Case:          "Windows registry drive",
-			Expected:      "\uf013 > f > magnetic:test",
-			Home:          homeDirWindows,
-			PWD:           "HKLM:\\SOFTWARE\\magnetic:test\\",
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: "\\",
-		},
-		{
-			Case:          "Unix outside home",
-			Expected:      "mnt > f > f > location",
-			Home:          homeDir,
-			PWD:           "/mnt/go/test/location",
-			PathSeparator: "/",
-		},
-		{
-			Case:          "Unix inside home",
-			Expected:      "~ > f > f > location",
-			Home:          homeDir,
-			PWD:           homeDir + "/docs/jan/location",
-			PathSeparator: "/",
-		},
-		{
-			Case:          "Unix outside home zero levels",
-			Expected:      "mnt > location",
-			Home:          homeDir,
-			PWD:           "/mnt/location",
-			PathSeparator: "/",
-		},
-		{
-			Case:          "Unix outside home one level",
-			Expected:      "mnt > f > location",
-			Home:          homeDir,
-			PWD:           "/mnt/folder/location",
-			PathSeparator: "/",
-		},
-		{
-			Case:          "Unix, colorize",
-			Expected:      "<blue>mnt</> > <yellow>f</> > <blue>location</>",
-			Home:          homeDir,
-			PWD:           "/mnt/folder/location",
-			PathSeparator: "/",
-			Cycle:         []string{"blue", "yellow"},
-		},
-		{
-			Case:           "Unix, colorize with folder separator",
-			Expected:       "<blue>mnt</><yellow> > </><yellow>f</><blue> > </><blue>location</>",
-			Home:           homeDir,
-			PWD:            "/mnt/folder/location",
-			PathSeparator:  "/",
-			Cycle:          []string{"blue", "yellow"},
-			ColorSeparator: true,
-		},
-		{
-			Case:          "Unix one level",
-			Expected:      "mnt",
-			Home:          homeDir,
-			PWD:           "/mnt",
-			PathSeparator: "/",
-		},
-	}
-
-	for _, tc := range cases {
+	for _, tc := range testAgnosterPathCases {
 		env := new(mock.Environment)
 		env.On("Home").Return(tc.Home)
 		env.On("PathSeparator").Return(tc.PathSeparator)
@@ -1229,134 +305,17 @@ func TestAgnosterPath(t *testing.T) {
 	}
 }
 
-func TestAgnosterLeftPath(t *testing.T) {
-	cases := []struct {
-		Case          string
-		Expected      string
-		Home          string
-		PWD           string
-		GOOS          string
-		PathSeparator string
-	}{
-		{
-			Case:          "Windows inside home",
-			Expected:      "~ > Documents > f > f",
-			Home:          homeDirWindows,
-			PWD:           homeDirWindows + "\\Documents\\Bill\\location",
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: "\\",
-		},
-		{
-			Case:          "Windows outside home",
-			Expected:      "C: > Program Files > f > f",
-			Home:          homeDirWindows,
-			PWD:           "C:\\Program Files\\Go\\location",
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: "\\",
-		},
-		{
-			Case:          "Windows inside home zero levels",
-			Expected:      "C: > location",
-			Home:          homeDirWindows,
-			PWD:           "C:\\location",
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: "\\",
-		},
-		{
-			Case:          "Windows inside home one level",
-			Expected:      "C: > Program Files > f",
-			Home:          homeDirWindows,
-			PWD:           "C:\\Program Files\\location",
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: "\\",
-		},
-		{
-			Case:          "Windows lower case drive letter",
-			Expected:      "C: > Windows",
-			Home:          homeDirWindows,
-			PWD:           "C:\\Windows\\",
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: "\\",
-		},
-		{
-			Case:          "Windows lower case drive letter (other)",
-			Expected:      "P: > Other",
-			Home:          homeDirWindows,
-			PWD:           "P:\\Other\\",
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: "\\",
-		},
-		{
-			Case:          "Windows lower word drive",
-			Expected:      "some: > some",
-			Home:          homeDirWindows,
-			PWD:           "some:\\some\\",
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: "\\",
-		},
-		{
-			Case:          "Windows lower word drive (ending with c)",
-			Expected:      "src: > source",
-			Home:          homeDirWindows,
-			PWD:           "src:\\source\\",
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: "\\",
-		},
-		{
-			Case:          "Windows lower word drive (arbitrary cases)",
-			Expected:      "sRc: > source",
-			Home:          homeDirWindows,
-			PWD:           "sRc:\\source\\",
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: "\\",
-		},
-		{
-			Case:          "Windows registry drive",
-			Expected:      "\uf013 > SOFTWARE > f",
-			Home:          homeDirWindows,
-			PWD:           "HKLM:\\SOFTWARE\\magnetic:test\\",
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: "\\",
-		},
-		{
-			Case:          "Windows registry drive case sensitive",
-			Expected:      "\uf013 > SOFTWARE > f",
-			Home:          homeDirWindows,
-			PWD:           "HKLM:\\SOFTWARE\\magnetic:TOAST\\",
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: "\\",
-		},
-		{
-			Case:          "Unix outside home",
-			Expected:      "mnt > go > f > f",
-			Home:          homeDir,
-			PWD:           "/mnt/go/test/location",
-			PathSeparator: "/",
-		},
-		{
-			Case:          "Unix inside home",
-			Expected:      "~ > docs > f > f",
-			Home:          homeDir,
-			PWD:           homeDir + "/docs/jan/location",
-			PathSeparator: "/",
-		},
-		{
-			Case:          "Unix outside home zero levels",
-			Expected:      "mnt > location",
-			Home:          homeDir,
-			PWD:           "/mnt/location",
-			PathSeparator: "/",
-		},
-		{
-			Case:          "Unix outside home one level",
-			Expected:      "mnt > folder > f",
-			Home:          homeDir,
-			PWD:           "/mnt/folder/location",
-			PathSeparator: "/",
-		},
-	}
+type testAgnosterLeftPathCase struct {
+	Case          string
+	Expected      string
+	Home          string
+	PWD           string
+	GOOS          string
+	PathSeparator string
+}
 
-	for _, tc := range cases {
+func TestAgnosterLeftPath(t *testing.T) {
+	for _, tc := range testAgnosterLeftPathCases {
 		env := new(mock.Environment)
 		env.On("Home").Return(tc.Home)
 		env.On("PathSeparator").Return(tc.PathSeparator)
@@ -1385,63 +344,6 @@ func TestAgnosterLeftPath(t *testing.T) {
 	}
 }
 
-func TestGetPwd(t *testing.T) {
-	cases := []struct {
-		Pwd                    string
-		Pswd                   string
-		Expected               string
-		MappedLocationsEnabled bool
-	}{
-		{MappedLocationsEnabled: true, Pwd: homeDir, Expected: "~"},
-		{MappedLocationsEnabled: true, Pwd: homeDir + "-test", Expected: homeDir + "-test"},
-		{MappedLocationsEnabled: true},
-		{MappedLocationsEnabled: true, Pwd: "/usr", Expected: "/usr"},
-		{MappedLocationsEnabled: true, Pwd: homeDir + abc, Expected: "~/abc"},
-		{MappedLocationsEnabled: true, Pwd: abcd, Expected: "#"},
-		{MappedLocationsEnabled: true, Pwd: "/a/b/c/d/e/f/g", Expected: "#/e/f/g"},
-		{MappedLocationsEnabled: true, Pwd: "/z/y/x/w", Expected: "/z/y/x/w"},
-
-		{MappedLocationsEnabled: false},
-		{MappedLocationsEnabled: false, Pwd: homeDir + abc, Expected: homeDir + abc},
-		{MappedLocationsEnabled: false, Pwd: "/a/b/c/d/e/f/g", Expected: "#/e/f/g"},
-		{MappedLocationsEnabled: false, Pwd: homeDir + cdefg, Expected: homeDir + cdefg},
-		{MappedLocationsEnabled: true, Pwd: homeDir + cdefg, Expected: "~/c/d/e/f/g"},
-
-		{MappedLocationsEnabled: true, Pwd: "/w/d/x/w", Pswd: "/z/y/x/w", Expected: "/z/y/x/w"},
-		{MappedLocationsEnabled: false, Pwd: "/f/g/k/d/e/f/g", Pswd: "/a/b/c/d/e/f/g", Expected: "#/e/f/g"},
-	}
-
-	for _, tc := range cases {
-		env := new(mock.Environment)
-		env.On("PathSeparator").Return("/")
-		env.On("Home").Return(homeDir)
-		env.On("Pwd").Return(tc.Pwd)
-		env.On("GOOS").Return("")
-		args := &runtime.Flags{
-			PSWD: tc.Pswd,
-		}
-		env.On("Flags").Return(args)
-		env.On("Shell").Return(shell.PWSH)
-		env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
-		env.On("Trace", testify_.Anything, testify_.Anything).Return(nil)
-
-		template.Init(env)
-
-		props := properties.Map{
-			MappedLocationsEnabled: tc.MappedLocationsEnabled,
-			MappedLocations: map[string]string{
-				abcd: "#",
-			},
-		}
-
-		path := &Path{}
-		path.Init(props, env)
-
-		path.setPaths()
-		assert.Equal(t, tc.Expected, path.pwd)
-	}
-}
-
 func TestGetFolderSeparator(t *testing.T) {
 	cases := []struct {
 		Case                    string
@@ -1459,14 +361,12 @@ func TestGetFolderSeparator(t *testing.T) {
 	for _, tc := range cases {
 		env := new(mock.Environment)
 		env.On("Error", testify_.Anything)
-		env.On("Debug", testify_.Anything)
-		env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
 		env.On("Shell").Return(shell.GENERIC)
-		env.On("Trace", testify_.Anything, testify_.Anything).Return(nil)
-		env.On("TemplateCache").Return(&cache.Template{
+
+		template.Cache = &cache.Template{
 			Shell: "bash",
-		})
-		template.Init(env)
+		}
+		template.Init(env, nil)
 
 		props := properties.Map{}
 
@@ -1488,126 +388,17 @@ func TestGetFolderSeparator(t *testing.T) {
 	}
 }
 
-func TestNormalizePath(t *testing.T) {
-	cases := []struct {
-		Case          string
-		Input         string
-		HomeDir       string
-		GOOS          string
-		PathSeparator string
-		Expected      string
-	}{
-		{
-			Case:          "Windows: absolute w/o drive letter, forward slash included",
-			Input:         "/foo/~/bar",
-			HomeDir:       homeDirWindows,
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: `\`,
-			Expected:      "\\foo\\~\\bar",
-		},
-		{
-			Case:          "Windows: absolute",
-			Input:         homeDirWindows + "\\Foo",
-			HomeDir:       homeDirWindows,
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: `\`,
-			Expected:      "c:\\users\\someone\\foo",
-		},
-		{
-			Case:     "Linux: home prefix, backslash included",
-			Input:    "~/Bob\\Foo",
-			HomeDir:  homeDir,
-			GOOS:     runtime.LINUX,
-			Expected: homeDir + "/Bob\\Foo",
-		},
-		{
-			Case:     "macOS: home prefix, backslash included",
-			Input:    "~/Bob\\Foo",
-			HomeDir:  homeDir,
-			GOOS:     runtime.DARWIN,
-			Expected: homeDir + "/bob\\foo",
-		},
-		{
-			Case:          "Windows: home prefix",
-			Input:         "~\\Bob\\Foo",
-			HomeDir:       homeDirWindows,
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: `\`,
-			Expected:      "c:\\users\\someone\\bob\\foo",
-		},
-		{
-			Case:     "Linux: absolute",
-			Input:    "/foo/~/bar",
-			HomeDir:  homeDir,
-			GOOS:     runtime.LINUX,
-			Expected: "/foo/~/bar",
-		},
-		{
-			Case:     "Linux: home prefix",
-			Input:    "~/baz",
-			HomeDir:  homeDir,
-			GOOS:     runtime.LINUX,
-			Expected: homeDir + "/baz",
-		},
-		{
-			Case:          "Windows: home prefix",
-			Input:         "~/baz",
-			HomeDir:       homeDirWindows,
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: `\`,
-			Expected:      "c:\\users\\someone\\baz",
-		},
-		{
-			Case:          "Windows: UNC root w/ prefix",
-			Input:         `\\.\UNC\localhost\c$`,
-			HomeDir:       homeDirWindows,
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: `\`,
-			Expected:      "\\\\localhost\\c$",
-		},
-		{
-			Case:          "Windows: UNC root w/ prefix, forward slash included",
-			Input:         "//./UNC/localhost/c$",
-			HomeDir:       homeDirWindows,
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: `\`,
-			Expected:      "\\\\localhost\\c$",
-		},
-		{
-			Case:          "Windows: UNC root",
-			Input:         `\\localhost\c$\`,
-			HomeDir:       homeDirWindows,
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: `\`,
-			Expected:      "\\\\localhost\\c$",
-		},
-		{
-			Case:          "Windows: UNC root, forward slash included",
-			Input:         "//localhost/c$",
-			HomeDir:       homeDirWindows,
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: `\`,
-			Expected:      "\\\\localhost\\c$",
-		},
-		{
-			Case:          "Windows: UNC",
-			Input:         `\\localhost\c$\some`,
-			HomeDir:       homeDirWindows,
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: `\`,
-			Expected:      "\\\\localhost\\c$\\some",
-		},
-		{
-			Case:          "Windows: UNC, forward slash included",
-			Input:         "//localhost/c$/some",
-			HomeDir:       homeDirWindows,
-			GOOS:          runtime.WINDOWS,
-			PathSeparator: `\`,
-			Expected:      "\\\\localhost\\c$\\some",
-		},
-	}
+type testNormalizePathCase struct {
+	Case          string
+	Input         string
+	HomeDir       string
+	GOOS          string
+	PathSeparator string
+	Expected      string
+}
 
-	for _, tc := range cases {
+func TestNormalizePath(t *testing.T) {
+	for _, tc := range testNormalizePathCases {
 		env := new(mock.Environment)
 		env.On("Home").Return(tc.HomeDir)
 		env.On("GOOS").Return(tc.GOOS)
@@ -1626,105 +417,18 @@ func TestNormalizePath(t *testing.T) {
 	}
 }
 
-func TestReplaceMappedLocations(t *testing.T) {
-	cases := []struct {
-		Case                   string
-		Pwd                    string
-		Expected               string
-		MappedLocationsEnabled bool
-	}{
-		{Pwd: "/c/l/k/f", Expected: "f"},
-		{Pwd: "/f/g/h", Expected: "/f/g/h"},
-		{Pwd: "/f/g/h/e", Expected: "^/e"},
-		{Pwd: abcd, Expected: "#"},
-		{Pwd: "/a/b/c/d/e", Expected: "#/e"},
-		{Pwd: "/a/b/c/D/e", Expected: "#/e"},
-		{Pwd: "/a/b/k/j/e", Expected: "e"},
-		{Pwd: "/a/b/k/l", Expected: "@/l"},
-		{Pwd: "/a/b/k/l", MappedLocationsEnabled: true, Expected: "~/l"},
-	}
-
-	for _, tc := range cases {
-		env := new(mock.Environment)
-		env.On("PathSeparator").Return("/")
-		env.On("Pwd").Return(tc.Pwd)
-		env.On("Shell").Return(shell.FISH)
-		env.On("GOOS").Return(runtime.DARWIN)
-		env.On("Home").Return("/a/b/k")
-		env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
-		env.On("Trace", testify_.Anything, testify_.Anything).Return(nil)
-
-		template.Init(env)
-
-		props := properties.Map{
-			MappedLocationsEnabled: tc.MappedLocationsEnabled,
-			MappedLocations: map[string]string{
-				abcd:       "#",
-				"/f/g/h/*": "^",
-				"/c/l/k/*": "",
-				"~":        "@",
-				"~/j/*":    "",
-			},
-		}
-
-		path := &Path{}
-		path.Init(props, env)
-
-		path.setPaths()
-		assert.Equal(t, tc.Expected, path.pwd)
-	}
+type testSplitPathCase struct {
+	Case         string
+	GOOS         string
+	Relative     string
+	Root         string
+	GitDir       *runtime.FileInfo
+	GitDirFormat string
+	Expected     Folders
 }
 
 func TestSplitPath(t *testing.T) {
-	cases := []struct {
-		Case         string
-		GOOS         string
-		Relative     string
-		Root         string
-		GitDir       *runtime.FileInfo
-		GitDirFormat string
-		Expected     Folders
-	}{
-		{Case: "Root directory", Root: "/", Expected: Folders{}},
-		{
-			Case:     "Regular directory",
-			Root:     "/",
-			Relative: "c/d",
-			GOOS:     runtime.DARWIN,
-			Expected: Folders{
-				{Name: "c", Path: "/c"},
-				{Name: "d", Path: "/c/d"},
-			},
-		},
-		{
-			Case:         "Home directory - git folder",
-			Root:         "~",
-			Relative:     "c/d",
-			GOOS:         runtime.DARWIN,
-			GitDir:       &runtime.FileInfo{IsDir: true, ParentFolder: "/a/b/c"},
-			GitDirFormat: "<b>%s</b>",
-			Expected: Folders{
-				{Name: "<b>c</b>", Path: "~/c", Display: true},
-				{Name: "d", Path: "~/c/d"},
-			},
-		},
-		{
-			Case:         "Home directory - git folder on Windows",
-			Root:         "C:",
-			Relative:     "a/b/c/d",
-			GOOS:         runtime.WINDOWS,
-			GitDir:       &runtime.FileInfo{IsDir: true, ParentFolder: "C:/a/b/c"},
-			GitDirFormat: "<b>%s</b>",
-			Expected: Folders{
-				{Name: "a", Path: "C:/a"},
-				{Name: "b", Path: "C:/a/b"},
-				{Name: "<b>c</b>", Path: "C:/a/b/c", Display: true},
-				{Name: "d", Path: "C:/a/b/c/d"},
-			},
-		},
-	}
-
-	for _, tc := range cases {
+	for _, tc := range testSplitPathCases {
 		env := new(mock.Environment)
 		env.On("PathSeparator").Return("/")
 		env.On("Home").Return("/a/b")
@@ -1777,14 +481,12 @@ func TestGetMaxWidth(t *testing.T) {
 
 	for _, tc := range cases {
 		env := new(mock.Environment)
-		env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
 		env.On("Error", testify_.Anything).Return(nil)
-		env.On("TemplateCache").Return(&cache.Template{})
 		env.On("Getenv", "MAX_WIDTH").Return("120")
 		env.On("Shell").Return(shell.BASH)
-		env.On("Trace", testify_.Anything, testify_.Anything).Return(nil)
 
-		template.Init(env)
+		template.Cache = new(cache.Template)
+		template.Init(env, nil)
 
 		props := properties.Map{
 			MaxWidth: tc.MaxWidth,
diff --git a/src/segments/path_unix_test.go b/src/segments/path_unix_test.go
new file mode 100644
index 00000000..05ca4cf7
--- /dev/null
+++ b/src/segments/path_unix_test.go
@@ -0,0 +1,812 @@
+//go:build !windows
+
+package segments
+
+import (
+	"testing"
+
+	"github.com/jandedobbeleer/oh-my-posh/src/cache"
+	"github.com/jandedobbeleer/oh-my-posh/src/properties"
+	"github.com/jandedobbeleer/oh-my-posh/src/runtime"
+	"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
+	"github.com/jandedobbeleer/oh-my-posh/src/shell"
+	"github.com/jandedobbeleer/oh-my-posh/src/template"
+	"github.com/stretchr/testify/assert"
+)
+
+var testParentCases = []testParentCase{
+	{
+		Case:          "Inside Home folder",
+		Expected:      "~/",
+		HomePath:      homeDir,
+		Pwd:           homeDir + "/test",
+		GOOS:          runtime.DARWIN,
+		PathSeparator: "/",
+	},
+	{
+		Case:          "Home folder",
+		HomePath:      homeDir,
+		Pwd:           homeDir,
+		GOOS:          runtime.DARWIN,
+		PathSeparator: "/",
+	},
+	{
+		Case:          "Home folder with a trailing separator",
+		HomePath:      homeDir,
+		Pwd:           homeDir + "/",
+		GOOS:          runtime.DARWIN,
+		PathSeparator: "/",
+	},
+	{
+		Case:          "Root",
+		HomePath:      homeDir,
+		Pwd:           "/",
+		GOOS:          runtime.DARWIN,
+		PathSeparator: "/",
+	},
+	{
+		Case:          "Root + 1",
+		Expected:      "/",
+		HomePath:      homeDir,
+		Pwd:           "/usr",
+		GOOS:          runtime.DARWIN,
+		PathSeparator: "/",
+	},
+}
+
+var testAgnosterPathStyleCases = []testAgnosterPathStyleCase{
+	{
+		Style:               Unique,
+		Expected:            "~ > a > ab > abcd",
+		HomePath:            homeDir,
+		Pwd:                 homeDir + "/ab/abc/abcd",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               Unique,
+		Expected:            "~ > a > .a > abcd",
+		HomePath:            homeDir,
+		Pwd:                 homeDir + "/ab/.abc/abcd",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               Unique,
+		Expected:            "~ > a > ab > abcd",
+		HomePath:            homeDir,
+		Pwd:                 homeDir + "/ab/ab/abcd",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               Unique,
+		Expected:            "a",
+		HomePath:            homeDir,
+		Pwd:                 "/ab",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+	},
+
+	{
+		Style:               Powerlevel,
+		Expected:            "t > w > o > a > v > l > p > wh > we > i > wa > th > the > d > f > u > it > c > to > a > co > stream",
+		HomePath:            homeDir,
+		Pwd:                 "/there/was/once/a/very/long/path/which/wended/its/way/through/the/dark/forest/until/it/came/to/a/cold/stream",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+		MaxWidth:            20,
+	},
+	{
+		Style:               Powerlevel,
+		Expected:            "t > w > o > a > v > l > p > which > wended > its > way > through > the",
+		HomePath:            homeDir,
+		Pwd:                 "/there/was/once/a/very/long/path/which/wended/its/way/through/the",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+		MaxWidth:            70,
+	},
+	{
+		Style:               Powerlevel,
+		Expected:            "var/cache/pacman",
+		HomePath:            homeDir,
+		Pwd:                 "/var/cache/pacman",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: "/",
+		MaxWidth:            50,
+	},
+
+	{
+		Style:               Letter,
+		Expected:            "~",
+		HomePath:            homeDir,
+		Pwd:                 homeDir,
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               Letter,
+		Expected:            "~ > a > w > man",
+		HomePath:            homeDir,
+		Pwd:                 homeDir + "/ab/whatever/man",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               Letter,
+		Expected:            "u > b > a > w > man",
+		HomePath:            homeDir,
+		Pwd:                 "/usr/burp/ab/whatever/man",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               Letter,
+		Expected:            "u > .b > a > w > man",
+		HomePath:            homeDir,
+		Pwd:                 "/usr/.burp/ab/whatever/man",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               Letter,
+		Expected:            "u > .b > a > .w > man",
+		HomePath:            homeDir,
+		Pwd:                 "/usr/.burp/ab/.whatever/man",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               Letter,
+		Expected:            "u > .b > a > ._w > man",
+		HomePath:            homeDir,
+		Pwd:                 "/usr/.burp/ab/._whatever/man",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               Letter,
+		Expected:            "u > .ä > ū > .w > man",
+		HomePath:            homeDir,
+		Pwd:                 "/usr/.äufbau/ūmgebung/.whatever/man",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               Letter,
+		Expected:            "u > .b > 1 > .w > man",
+		HomePath:            homeDir,
+		Pwd:                 "/usr/.burp/12345/.whatever/man",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               Letter,
+		Expected:            "u > .b > 1 > .w > man",
+		HomePath:            homeDir,
+		Pwd:                 "/usr/.burp/12345abc/.whatever/man",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               Letter,
+		Expected:            "u > .b > __p > .w > man",
+		HomePath:            homeDir,
+		Pwd:                 "/usr/.burp/__pycache__/.whatever/man",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               Letter,
+		Expected:            "➼ > .w > man",
+		HomePath:            homeDir,
+		Pwd:                 "/➼/.whatever/man",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               Letter,
+		Expected:            "➼ s > .w > man",
+		HomePath:            homeDir,
+		Pwd:                 "/➼ something/.whatever/man",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               Letter,
+		Expected:            "w",
+		HomePath:            homeDir,
+		Pwd:                 "/whatever",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+	},
+
+	{
+		Style:               Mixed,
+		Expected:            "~ > .. > man",
+		HomePath:            homeDir,
+		Pwd:                 homeDir + "/whatever/man",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               Mixed,
+		Expected:            "~ > ab > .. > man",
+		HomePath:            homeDir,
+		Pwd:                 homeDir + "/ab/whatever/man",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               Mixed,
+		Expected:            "usr > foo > bar > .. > man",
+		HomePath:            homeDir,
+		Pwd:                 "/usr/foo/bar/foobar/man",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               Mixed,
+		Expected:            "whatever > .. > foo > bar",
+		HomePath:            homeDir,
+		Pwd:                 "/whatever/foobar/foo/bar",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               AgnosterFull,
+		Expected:            "usr > location > whatever",
+		HomePath:            homeDir,
+		Pwd:                 "/usr/location/whatever",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               AgnosterFull,
+		Expected:            "PSDRIVE: | src",
+		HomePath:            homeDir,
+		Pwd:                 "/foo",
+		Pswd:                "PSDRIVE:/src",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " | ",
+	},
+
+	{
+		Style:               AgnosterShort,
+		Expected:            ".. | src | init",
+		HomePath:            homeDir,
+		Pwd:                 "/foo",
+		Pswd:                "PSDRIVE:/src/init",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " | ",
+		MaxDepth:            2,
+		HideRootLocation:    true,
+	},
+	{
+		Style:               AgnosterShort,
+		Expected:            "usr > foo > bar > man",
+		HomePath:            homeDir,
+		Pwd:                 "/usr/foo/bar/man",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+		MaxDepth:            3,
+	},
+	{
+		Style:               AgnosterShort,
+		Expected:            "PSDRIVE: | src",
+		HomePath:            homeDir,
+		Pwd:                 "/foo",
+		Pswd:                "PSDRIVE:/src",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " | ",
+		MaxDepth:            2,
+		HideRootLocation:    true,
+	},
+	{
+		Style:               AgnosterShort,
+		Expected:            "~ > projects",
+		HomePath:            homeDir,
+		Pwd:                 homeDir + "/projects",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               AgnosterShort,
+		Expected:            "~",
+		HomePath:            homeDir,
+		Pwd:                 homeDir,
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+		MaxDepth:            1,
+		HideRootLocation:    true,
+	},
+	{
+		Style:               AgnosterShort,
+		Expected:            "usr > .. > bar > man",
+		HomePath:            homeDir,
+		Pwd:                 "/usr/foo/bar/man",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+		MaxDepth:            2,
+	},
+	{
+		Style:               AgnosterShort,
+		Expected:            "~ > .. > man",
+		HomePath:            homeDir,
+		Pwd:                 homeDir + "/whatever/man",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               AgnosterShort,
+		Expected:            "usr > .. > man",
+		HomePath:            homeDir,
+		Pwd:                 "/usr/location/whatever/man",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               AgnosterShort,
+		Expected:            "~ > .. > bar > man",
+		HomePath:            homeDir,
+		Pwd:                 homeDir + "/foo/bar/man",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+		MaxDepth:            2,
+	},
+	{
+		Style:               AgnosterShort,
+		Expected:            "~ > foo > bar > man",
+		HomePath:            homeDir,
+		Pwd:                 homeDir + "/foo/bar/man",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+		MaxDepth:            3,
+	},
+	{
+		Style:               AgnosterShort,
+		Expected:            "PSDRIVE: | .. | init",
+		HomePath:            homeDir,
+		Pwd:                 "/foo",
+		Pswd:                "PSDRIVE:/src/init",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " | ",
+	},
+	{
+		Style:               AgnosterShort,
+		Expected:            ".. > foo",
+		HomePath:            homeDir,
+		Pwd:                 homeDir + "/foo",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+		MaxDepth:            1,
+		HideRootLocation:    true,
+	},
+	{
+		Style:               AgnosterShort,
+		Expected:            ".. > bar > man",
+		HomePath:            homeDir,
+		Pwd:                 homeDir + "/bar/man",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+		MaxDepth:            2,
+		HideRootLocation:    true,
+	},
+	{
+		Style:               AgnosterShort,
+		Expected:            ".. > foo > bar > man",
+		HomePath:            homeDir,
+		Pwd:                 "/usr/foo/bar/man",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+		MaxDepth:            3,
+		HideRootLocation:    true,
+	},
+	{
+		Style:               AgnosterShort,
+		Expected:            "~ > foo",
+		HomePath:            homeDir,
+		Pwd:                 homeDir + "/foo",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+		MaxDepth:            2,
+		HideRootLocation:    true,
+	},
+	{
+		Style:               AgnosterShort,
+		Expected:            "~ > foo > bar",
+		HomePath:            homeDir,
+		Pwd:                 homeDir + "/foo/bar",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " > ",
+		MaxDepth:            3,
+		HideRootLocation:    true,
+	},
+	{
+		Style:               AgnosterShort,
+		Expected:            "C: | ",
+		HomePath:            homeDir,
+		Pwd:                 "/mnt/c",
+		Pswd:                "C:",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " | ",
+		MaxDepth:            2,
+		HideRootLocation:    true,
+	},
+	{
+		Style:               AgnosterShort,
+		Expected:            "~ | space foo",
+		HomePath:            homeDir,
+		Pwd:                 homeDir + "/space foo",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " | ",
+		MaxDepth:            2,
+		HideRootLocation:    true,
+	},
+	{
+		Style:               AgnosterShort,
+		Expected:            ".. | space foo",
+		HomePath:            homeDir,
+		Pwd:                 homeDir + "/space foo",
+		PathSeparator:       "/",
+		FolderSeparatorIcon: " | ",
+		MaxDepth:            1,
+		HideRootLocation:    true,
+	},
+}
+
+var testAgnosterPathCases = []testAgnosterPathCase{
+	{
+		Case:          "Unix outside home",
+		Expected:      "mnt > f > f > location",
+		Home:          homeDir,
+		PWD:           "/mnt/go/test/location",
+		PathSeparator: "/",
+	},
+	{
+		Case:          "Unix inside home",
+		Expected:      "~ > f > f > location",
+		Home:          homeDir,
+		PWD:           homeDir + "/docs/jan/location",
+		PathSeparator: "/",
+	},
+	{
+		Case:          "Unix outside home zero levels",
+		Expected:      "mnt > location",
+		Home:          homeDir,
+		PWD:           "/mnt/location",
+		PathSeparator: "/",
+	},
+	{
+		Case:          "Unix outside home one level",
+		Expected:      "mnt > f > location",
+		Home:          homeDir,
+		PWD:           "/mnt/folder/location",
+		PathSeparator: "/",
+	},
+	{
+		Case:          "Unix, colorize",
+		Expected:      "<blue>mnt</> > <yellow>f</> > <blue>location</>",
+		Home:          homeDir,
+		PWD:           "/mnt/folder/location",
+		PathSeparator: "/",
+		Cycle:         []string{"blue", "yellow"},
+	},
+	{
+		Case:           "Unix, colorize with folder separator",
+		Expected:       "<blue>mnt</><yellow> > </><yellow>f</><blue> > </><blue>location</>",
+		Home:           homeDir,
+		PWD:            "/mnt/folder/location",
+		PathSeparator:  "/",
+		Cycle:          []string{"blue", "yellow"},
+		ColorSeparator: true,
+	},
+	{
+		Case:          "Unix one level",
+		Expected:      "mnt",
+		Home:          homeDir,
+		PWD:           "/mnt",
+		PathSeparator: "/",
+	},
+}
+
+var testAgnosterLeftPathCases = []testAgnosterLeftPathCase{
+	{
+		Case:          "Unix outside home",
+		Expected:      "mnt > go > f > f",
+		Home:          homeDir,
+		PWD:           "/mnt/go/test/location",
+		PathSeparator: "/",
+	},
+	{
+		Case:          "Unix inside home",
+		Expected:      "~ > docs > f > f",
+		Home:          homeDir,
+		PWD:           homeDir + "/docs/jan/location",
+		PathSeparator: "/",
+	},
+	{
+		Case:          "Unix outside home zero levels",
+		Expected:      "mnt > location",
+		Home:          homeDir,
+		PWD:           "/mnt/location",
+		PathSeparator: "/",
+	},
+	{
+		Case:          "Unix outside home one level",
+		Expected:      "mnt > folder > f",
+		Home:          homeDir,
+		PWD:           "/mnt/folder/location",
+		PathSeparator: "/",
+	},
+}
+
+var testFullAndFolderPathCases = []testFullAndFolderPathCase{
+	{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", Expected: "/"},
+	{Style: Full, Pwd: "/", Expected: "/"},
+	{Style: Full, Pwd: homeDir, Expected: "~"},
+	{Style: Full, Pwd: homeDir + abc, Expected: "~/abc"},
+	{Style: Full, Pwd: homeDir + abc, Expected: homeDir + abc, DisableMappedLocations: true},
+	{Style: Full, Pwd: abcd, Expected: abcd},
+
+	{Style: Full, FolderSeparatorIcon: "|", Pwd: homeDir, Expected: "~"},
+	{Style: Full, FolderSeparatorIcon: "|", Pwd: homeDir, Expected: "/home|someone", DisableMappedLocations: true},
+	{Style: Full, FolderSeparatorIcon: "|", Pwd: homeDir + abc, Expected: "~|abc"},
+	{Style: Full, FolderSeparatorIcon: "|", Pwd: abcd, Expected: "/a|b|c|d"},
+
+	{Style: FolderType, Pwd: "/", Expected: "/"},
+	{Style: FolderType, Pwd: homeDir, Expected: "~"},
+	{Style: FolderType, Pwd: homeDir, Expected: "someone", DisableMappedLocations: true},
+	{Style: FolderType, Pwd: homeDir + abc, Expected: "abc"},
+	{Style: FolderType, Pwd: abcd, Expected: "d"},
+
+	{Style: FolderType, FolderSeparatorIcon: "|", Pwd: "/", Expected: "/"},
+	{Style: FolderType, FolderSeparatorIcon: "|", Pwd: homeDir, Expected: "~"},
+	{Style: FolderType, FolderSeparatorIcon: "|", Pwd: homeDir, Expected: "someone", DisableMappedLocations: true},
+	{Style: FolderType, FolderSeparatorIcon: "|", Pwd: homeDir + abc, Expected: "abc"},
+	{Style: FolderType, FolderSeparatorIcon: "|", Pwd: abcd, Expected: "d"},
+
+	// StackCountEnabled=true and StackCount=2
+	{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", StackCount: 2, Expected: "2 /"},
+	{Style: Full, Pwd: "/", StackCount: 2, Expected: "2 /"},
+	{Style: Full, Pwd: homeDir, StackCount: 2, Expected: "2 ~"},
+	{Style: Full, Pwd: homeDir + abc, StackCount: 2, Expected: "2 ~/abc"},
+	{Style: Full, Pwd: homeDir + abc, StackCount: 2, Expected: "2 " + homeDir + abc, DisableMappedLocations: true},
+	{Style: Full, Pwd: abcd, StackCount: 2, Expected: "2 /a/b/c/d"},
+
+	// StackCountEnabled=false and StackCount=2
+	{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", Template: "{{ .Path }}", StackCount: 2, Expected: "/"},
+	{Style: Full, Pwd: "/", Template: "{{ .Path }}", StackCount: 2, Expected: "/"},
+	{Style: Full, Pwd: homeDir, Template: "{{ .Path }}", StackCount: 2, Expected: "~"},
+
+	{Style: Full, Pwd: homeDir + abc, Template: "{{ .Path }}", StackCount: 2, Expected: homeDir + abc, DisableMappedLocations: true},
+	{Style: Full, Pwd: abcd, Template: "{{ .Path }}", StackCount: 2, Expected: abcd},
+
+	// StackCountEnabled=true and StackCount=0
+	{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", StackCount: 0, Expected: "/"},
+	{Style: Full, Pwd: "/", StackCount: 0, Expected: "/"},
+	{Style: Full, Pwd: homeDir, StackCount: 0, Expected: "~"},
+	{Style: Full, Pwd: homeDir + abc, StackCount: 0, Expected: "~/abc"},
+	{Style: Full, Pwd: homeDir + abc, StackCount: 0, Expected: homeDir + abc, DisableMappedLocations: true},
+	{Style: Full, Pwd: abcd, StackCount: 0, Expected: abcd},
+
+	// StackCountEnabled=true and StackCount<0
+	{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", StackCount: -1, Expected: "/"},
+	{Style: Full, Pwd: "/", StackCount: -1, Expected: "/"},
+	{Style: Full, Pwd: homeDir, StackCount: -1, Expected: "~"},
+	{Style: Full, Pwd: homeDir + abc, StackCount: -1, Expected: "~/abc"},
+	{Style: Full, Pwd: homeDir + abc, StackCount: -1, Expected: homeDir + abc, DisableMappedLocations: true},
+	{Style: Full, Pwd: abcd, StackCount: -1, Expected: abcd},
+
+	// StackCountEnabled=true and StackCount not set
+	{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", Expected: "/"},
+	{Style: Full, Pwd: "/", Expected: "/"},
+	{Style: Full, Pwd: homeDir, Expected: "~"},
+	{Style: Full, Pwd: homeDir + abc, Expected: "~/abc"},
+	{Style: Full, Pwd: homeDir + abc, Expected: homeDir + abc, DisableMappedLocations: true},
+	{Style: Full, Pwd: abcd, Expected: abcd},
+}
+
+var testFullPathCustomMappedLocationsCases = []testFullPathCustomMappedLocationsCase{
+	{Pwd: homeDir + "/d", MappedLocations: map[string]string{"{{ .Env.HOME }}/d": "#"}, Expected: "#"},
+	{Pwd: abcd, MappedLocations: map[string]string{abcd: "#"}, Expected: "#"},
+	{Pwd: abcd, MappedLocations: map[string]string{"/a/b": "#"}, Expected: "#/c/d"},
+	{Pwd: abcd, MappedLocations: map[string]string{"/a/b": "/e/f"}, Expected: "/e/f/c/d"},
+	{Pwd: homeDir + abcd, MappedLocations: map[string]string{"~/a/b": "#"}, Expected: "#/c/d"},
+	{Pwd: "/a" + homeDir + "/b/c/d", MappedLocations: map[string]string{"/a~": "#"}, Expected: "/a" + homeDir + "/b/c/d"},
+	{Pwd: homeDir + abcd, MappedLocations: map[string]string{"/a/b": "#"}, Expected: homeDir + abcd},
+}
+
+var testSplitPathCases = []testSplitPathCase{
+	{Case: "Root directory", Root: "/", Expected: Folders{}},
+	{
+		Case:     "Regular directory",
+		Root:     "/",
+		Relative: "c/d",
+		GOOS:     runtime.DARWIN,
+		Expected: Folders{
+			{Name: "c", Path: "/c"},
+			{Name: "d", Path: "/c/d"},
+		},
+	},
+	{
+		Case:         "Home directory - git folder",
+		Root:         "~",
+		Relative:     "c/d",
+		GOOS:         runtime.DARWIN,
+		GitDir:       &runtime.FileInfo{IsDir: true, ParentFolder: "/a/b/c"},
+		GitDirFormat: "<b>%s</b>",
+		Expected: Folders{
+			{Name: "<b>c</b>", Path: "~/c", Display: true},
+			{Name: "d", Path: "~/c/d"},
+		},
+	},
+}
+
+var testNormalizePathCases = []testNormalizePathCase{
+	{
+		Case:     "Linux: home prefix, backslash included",
+		Input:    "~/Bob\\Foo",
+		HomeDir:  homeDir,
+		GOOS:     runtime.LINUX,
+		Expected: homeDir + "/Bob\\Foo",
+	},
+	{
+		Case:     "macOS: home prefix, backslash included",
+		Input:    "~/Bob\\Foo",
+		HomeDir:  homeDir,
+		GOOS:     runtime.DARWIN,
+		Expected: homeDir + "/bob\\foo",
+	},
+	{
+		Case:     "Linux: absolute",
+		Input:    "/foo/~/bar",
+		HomeDir:  homeDir,
+		GOOS:     runtime.LINUX,
+		Expected: "/foo/~/bar",
+	},
+	{
+		Case:     "Linux: home prefix",
+		Input:    "~/baz",
+		HomeDir:  homeDir,
+		GOOS:     runtime.LINUX,
+		Expected: homeDir + "/baz",
+	},
+}
+
+func TestFolderPathCustomMappedLocations(t *testing.T) {
+	pwd := abcd
+	env := new(mock.Environment)
+	env.On("PathSeparator").Return("/")
+	env.On("Home").Return(homeDir)
+	env.On("Pwd").Return(pwd)
+	env.On("GOOS").Return("")
+	args := &runtime.Flags{
+		PSWD: pwd,
+	}
+	env.On("Flags").Return(args)
+	env.On("Shell").Return(shell.GENERIC)
+
+	template.Cache = new(cache.Template)
+	template.Init(env, nil)
+
+	props := properties.Map{
+		properties.Style: FolderType,
+		MappedLocations: map[string]string{
+			abcd: "#",
+		},
+	}
+
+	path := &Path{}
+	path.Init(props, env)
+
+	path.setPaths()
+	path.setStyle()
+
+	got := renderTemplateNoTrimSpace(env, "{{ .Path }}", path)
+	assert.Equal(t, "#", got)
+}
+
+func TestReplaceMappedLocations(t *testing.T) {
+	cases := []struct {
+		Case                   string
+		Pwd                    string
+		Expected               string
+		MappedLocationsEnabled bool
+	}{
+		{Pwd: "/c/l/k/f", Expected: "f"},
+		{Pwd: "/f/g/h", Expected: "/f/g/h"},
+		{Pwd: "/f/g/h/e", Expected: "^/e"},
+		{Pwd: abcd, Expected: "#"},
+		{Pwd: "/a/b/c/d/e", Expected: "#/e"},
+		{Pwd: "/a/b/c/D/e", Expected: "#/e"},
+		{Pwd: "/a/b/k/j/e", Expected: "e"},
+		{Pwd: "/a/b/k/l", Expected: "@/l"},
+		{Pwd: "/a/b/k/l", MappedLocationsEnabled: true, Expected: "~/l"},
+	}
+
+	for _, tc := range cases {
+		env := new(mock.Environment)
+		env.On("PathSeparator").Return("/")
+		env.On("Pwd").Return(tc.Pwd)
+		env.On("Shell").Return(shell.FISH)
+		env.On("GOOS").Return(runtime.DARWIN)
+		env.On("Home").Return("/a/b/k")
+
+		template.Cache = new(cache.Template)
+		template.Init(env, nil)
+
+		props := properties.Map{
+			MappedLocationsEnabled: tc.MappedLocationsEnabled,
+			MappedLocations: map[string]string{
+				abcd:       "#",
+				"/f/g/h/*": "^",
+				"/c/l/k/*": "",
+				"~":        "@",
+				"~/j/*":    "",
+			},
+		}
+
+		path := &Path{}
+		path.Init(props, env)
+
+		path.setPaths()
+		assert.Equal(t, tc.Expected, path.pwd)
+	}
+}
+
+func TestGetPwd(t *testing.T) {
+	cases := []struct {
+		Pwd                    string
+		Pswd                   string
+		Expected               string
+		MappedLocationsEnabled bool
+	}{
+		{MappedLocationsEnabled: true, Pwd: homeDir, Expected: "~"},
+		{MappedLocationsEnabled: true, Pwd: homeDir + "-test", Expected: homeDir + "-test"},
+		{MappedLocationsEnabled: true},
+		{MappedLocationsEnabled: true, Pwd: "/usr", Expected: "/usr"},
+		{MappedLocationsEnabled: true, Pwd: homeDir + abc, Expected: "~/abc"},
+		{MappedLocationsEnabled: true, Pwd: abcd, Expected: "#"},
+		{MappedLocationsEnabled: true, Pwd: "/a/b/c/d/e/f/g", Expected: "#/e/f/g"},
+		{MappedLocationsEnabled: true, Pwd: "/z/y/x/w", Expected: "/z/y/x/w"},
+
+		{MappedLocationsEnabled: false},
+		{MappedLocationsEnabled: false, Pwd: homeDir + abc, Expected: homeDir + abc},
+		{MappedLocationsEnabled: false, Pwd: "/a/b/c/d/e/f/g", Expected: "#/e/f/g"},
+		{MappedLocationsEnabled: false, Pwd: homeDir + cdefg, Expected: homeDir + cdefg},
+		{MappedLocationsEnabled: true, Pwd: homeDir + cdefg, Expected: "~/c/d/e/f/g"},
+
+		{MappedLocationsEnabled: true, Pwd: "/w/d/x/w", Pswd: "/z/y/x/w", Expected: "/z/y/x/w"},
+		{MappedLocationsEnabled: false, Pwd: "/f/g/k/d/e/f/g", Pswd: "/a/b/c/d/e/f/g", Expected: "#/e/f/g"},
+	}
+
+	for _, tc := range cases {
+		env := new(mock.Environment)
+		env.On("PathSeparator").Return("/")
+		env.On("Home").Return(homeDir)
+		env.On("Pwd").Return(tc.Pwd)
+		env.On("GOOS").Return("")
+		args := &runtime.Flags{
+			PSWD: tc.Pswd,
+		}
+		env.On("Flags").Return(args)
+		env.On("Shell").Return(shell.PWSH)
+
+		template.Cache = new(cache.Template)
+		template.Init(env, nil)
+
+		props := properties.Map{
+			MappedLocationsEnabled: tc.MappedLocationsEnabled,
+			MappedLocations: map[string]string{
+				abcd: "#",
+			},
+		}
+
+		path := &Path{}
+		path.Init(props, env)
+
+		path.setPaths()
+		assert.Equal(t, tc.Expected, path.pwd)
+	}
+}
diff --git a/src/segments/path_windows_test.go b/src/segments/path_windows_test.go
new file mode 100644
index 00000000..b2efa942
--- /dev/null
+++ b/src/segments/path_windows_test.go
@@ -0,0 +1,524 @@
+package segments
+
+import (
+	"errors"
+
+	"github.com/jandedobbeleer/oh-my-posh/src/runtime"
+	"github.com/jandedobbeleer/oh-my-posh/src/shell"
+)
+
+var testParentCases = []testParentCase{
+	{
+		Case:          "Windows Home folder",
+		HomePath:      homeDirWindows,
+		Pwd:           homeDirWindows,
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: "\\",
+	},
+	{
+		Case:          "Windows drive root",
+		HomePath:      homeDirWindows,
+		Pwd:           "C:",
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: "\\",
+	},
+	{
+		Case:          "Windows drive root with a trailing separator",
+		HomePath:      homeDirWindows,
+		Pwd:           "C:\\",
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: "\\",
+	},
+	{
+		Case:          "Windows drive root + 1",
+		Expected:      "C:\\",
+		HomePath:      homeDirWindows,
+		Pwd:           "C:\\test",
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: "\\",
+	},
+	{
+		Case:          "PSDrive root",
+		HomePath:      homeDirWindows,
+		Pwd:           "HKLM:",
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: "\\",
+	},
+}
+
+var testAgnosterPathStyleCases = []testAgnosterPathStyleCase{
+	{
+		Style:               Unique,
+		Expected:            "C > a > ab > abcd",
+		HomePath:            homeDirWindows,
+		Pwd:                 "C:\\ab\\ab\\abcd",
+		GOOS:                runtime.WINDOWS,
+		PathSeparator:       "\\",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               Letter,
+		Expected:            "C: > ",
+		HomePath:            homeDirWindows,
+		Pwd:                 "C:\\",
+		GOOS:                runtime.WINDOWS,
+		PathSeparator:       "\\",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               Letter,
+		Expected:            "C > s > .w > man",
+		HomePath:            homeDirWindows,
+		Pwd:                 "C:\\something\\.whatever\\man",
+		GOOS:                runtime.WINDOWS,
+		PathSeparator:       "\\",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               Letter,
+		Expected:            "~ > s > man",
+		HomePath:            homeDirWindows,
+		Pwd:                 homeDirWindows + "\\something\\man",
+		GOOS:                runtime.WINDOWS,
+		PathSeparator:       "\\",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               Mixed,
+		Expected:            "C: > .. > foo > .. > man",
+		HomePath:            homeDirWindows,
+		Pwd:                 "C:\\Users\\foo\\foobar\\man",
+		GOOS:                runtime.WINDOWS,
+		PathSeparator:       "\\",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               Mixed,
+		Expected:            "c > .. > foo > .. > man",
+		HomePath:            homeDirWindows,
+		Pwd:                 "C:\\Users\\foo\\foobar\\man",
+		GOOS:                runtime.WINDOWS,
+		Shell:               shell.BASH,
+		Cygwin:              true,
+		Cygpath:             "/c/Users/foo/foobar/man",
+		PathSeparator:       "\\",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               Mixed,
+		Expected:            "C: > .. > foo > .. > man",
+		HomePath:            homeDirWindows,
+		Pwd:                 "C:\\Users\\foo\\foobar\\man",
+		GOOS:                runtime.WINDOWS,
+		Shell:               shell.BASH,
+		CygpathError:        errors.New("oh no"),
+		PathSeparator:       "\\",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               AgnosterShort,
+		Expected:            "\\\\localhost\\c$ > some",
+		HomePath:            homeDirWindows,
+		Pwd:                 "\\\\localhost\\c$\\some",
+		GOOS:                runtime.WINDOWS,
+		PathSeparator:       "\\",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               AgnosterShort,
+		Expected:            "\\\\localhost\\c$",
+		HomePath:            homeDirWindows,
+		Pwd:                 "\\\\localhost\\c$",
+		GOOS:                runtime.WINDOWS,
+		PathSeparator:       "\\",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               AgnosterShort,
+		Expected:            ".. > bar > man",
+		HomePath:            homeDirWindows,
+		Pwd:                 homeDirWindows + fooBarMan,
+		GOOS:                runtime.WINDOWS,
+		PathSeparator:       "\\",
+		FolderSeparatorIcon: " > ",
+		MaxDepth:            2,
+		HideRootLocation:    true,
+	},
+	{
+		Style:               AgnosterShort,
+		Expected:            "C: > ",
+		HomePath:            homeDirWindows,
+		Pwd:                 "C:",
+		GOOS:                runtime.WINDOWS,
+		PathSeparator:       "\\",
+		FolderSeparatorIcon: " > ",
+	},
+	{
+		Style:               AgnosterShort,
+		Expected:            "C: > .. > bar > man",
+		HomePath:            homeDirWindows,
+		Pwd:                 "C:\\usr\\foo\\bar\\man",
+		GOOS:                runtime.WINDOWS,
+		PathSeparator:       "\\",
+		FolderSeparatorIcon: " > ",
+		MaxDepth:            2,
+	},
+	{
+		Style:               AgnosterShort,
+		Expected:            "C: > .. > foo > bar > man",
+		HomePath:            homeDirWindows,
+		Pwd:                 "C:\\usr\\foo\\bar\\man",
+		GOOS:                runtime.WINDOWS,
+		PathSeparator:       "\\",
+		FolderSeparatorIcon: " > ",
+		MaxDepth:            3,
+	},
+	{
+		Style:               AgnosterShort,
+		Expected:            "~ > .. > bar > man",
+		HomePath:            homeDirWindows,
+		Pwd:                 homeDirWindows + fooBarMan,
+		GOOS:                runtime.WINDOWS,
+		PathSeparator:       "\\",
+		FolderSeparatorIcon: " > ",
+		MaxDepth:            2,
+	},
+	{
+		Style:               AgnosterShort,
+		Expected:            "~ > foo > bar > man",
+		HomePath:            homeDirWindows,
+		Pwd:                 homeDirWindows + fooBarMan,
+		GOOS:                runtime.WINDOWS,
+		PathSeparator:       "\\",
+		FolderSeparatorIcon: " > ",
+		MaxDepth:            3,
+	},
+	{
+		Style:               AgnosterShort,
+		Expected:            "~",
+		HomePath:            homeDirWindows,
+		Pwd:                 homeDirWindows,
+		GOOS:                runtime.WINDOWS,
+		PathSeparator:       "\\",
+		FolderSeparatorIcon: " > ",
+		MaxDepth:            1,
+		HideRootLocation:    true,
+	},
+	{
+		Style:               AgnosterShort,
+		Expected:            ".. > foo",
+		HomePath:            homeDirWindows,
+		Pwd:                 homeDirWindows + "\\foo",
+		GOOS:                runtime.WINDOWS,
+		PathSeparator:       "\\",
+		FolderSeparatorIcon: " > ",
+		MaxDepth:            1,
+		HideRootLocation:    true,
+	},
+	{
+		Style:               AgnosterShort,
+		Expected:            "~ > foo",
+		HomePath:            homeDirWindows,
+		Pwd:                 homeDirWindows + "\\foo",
+		GOOS:                runtime.WINDOWS,
+		PathSeparator:       "\\",
+		FolderSeparatorIcon: " > ",
+		MaxDepth:            2,
+		HideRootLocation:    true,
+	},
+}
+
+var testAgnosterPathCases = []testAgnosterPathCase{
+	{
+		Case:          "Windows registry drive case sensitive",
+		Expected:      "\uf013 > f > magnetic:TOAST",
+		Home:          homeDirWindows,
+		PWD:           "HKLM:\\SOFTWARE\\magnetic:TOAST\\",
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: "\\",
+	},
+	{
+		Case:          "Windows outside home",
+		Expected:      "C: > f > f > location",
+		Home:          homeDirWindows,
+		PWD:           "C:\\Program Files\\Go\\location",
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: "\\",
+	},
+	{
+		Case:          "Windows oustide home",
+		Expected:      "~ > f > f > location",
+		Home:          homeDirWindows,
+		PWD:           homeDirWindows + "\\Documents\\Bill\\location",
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: "\\",
+	},
+	{
+		Case:          "Windows inside home zero levels",
+		Expected:      "C: > location",
+		Home:          homeDirWindows,
+		PWD:           "C:\\location",
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: "\\",
+	},
+	{
+		Case:          "Windows inside home one level",
+		Expected:      "C: > f > location",
+		Home:          homeDirWindows,
+		PWD:           "C:\\Program Files\\location",
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: "\\",
+	},
+	{
+		Case:          "Windows lower case drive letter",
+		Expected:      "C: > Windows",
+		Home:          homeDirWindows,
+		PWD:           "C:\\Windows\\",
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: "\\",
+	},
+	{
+		Case:          "Windows lower case drive letter (other)",
+		Expected:      "P: > Other",
+		Home:          homeDirWindows,
+		PWD:           "P:\\Other\\",
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: "\\",
+	},
+	{
+		Case:          "Windows lower word drive",
+		Expected:      "some: > some",
+		Home:          homeDirWindows,
+		PWD:           "some:\\some\\",
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: "\\",
+	},
+	{
+		Case:          "Windows lower word drive (ending with c)",
+		Expected:      "src: > source",
+		Home:          homeDirWindows,
+		PWD:           "src:\\source\\",
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: "\\",
+	},
+	{
+		Case:          "Windows lower word drive (arbitrary cases)",
+		Expected:      "sRc: > source",
+		Home:          homeDirWindows,
+		PWD:           "sRc:\\source\\",
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: "\\",
+	},
+	{
+		Case:          "Windows registry drive",
+		Expected:      "\uf013 > f > magnetic:test",
+		Home:          homeDirWindows,
+		PWD:           "HKLM:\\SOFTWARE\\magnetic:test\\",
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: "\\",
+	},
+}
+
+var testAgnosterLeftPathCases = []testAgnosterLeftPathCase{
+	{
+		Case:          "Windows inside home",
+		Expected:      "~ > Documents > f > f",
+		Home:          homeDirWindows,
+		PWD:           homeDirWindows + "\\Documents\\Bill\\location",
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: "\\",
+	},
+	{
+		Case:          "Windows outside home",
+		Expected:      "C: > Program Files > f > f",
+		Home:          homeDirWindows,
+		PWD:           "C:\\Program Files\\Go\\location",
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: "\\",
+	},
+	{
+		Case:          "Windows inside home zero levels",
+		Expected:      "C: > location",
+		Home:          homeDirWindows,
+		PWD:           "C:\\location",
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: "\\",
+	},
+	{
+		Case:          "Windows inside home one level",
+		Expected:      "C: > Program Files > f",
+		Home:          homeDirWindows,
+		PWD:           "C:\\Program Files\\location",
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: "\\",
+	},
+	{
+		Case:          "Windows lower case drive letter",
+		Expected:      "C: > Windows",
+		Home:          homeDirWindows,
+		PWD:           "C:\\Windows\\",
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: "\\",
+	},
+	{
+		Case:          "Windows lower case drive letter (other)",
+		Expected:      "P: > Other",
+		Home:          homeDirWindows,
+		PWD:           "P:\\Other\\",
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: "\\",
+	},
+	{
+		Case:          "Windows lower word drive",
+		Expected:      "some: > some",
+		Home:          homeDirWindows,
+		PWD:           "some:\\some\\",
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: "\\",
+	},
+	{
+		Case:          "Windows lower word drive (ending with c)",
+		Expected:      "src: > source",
+		Home:          homeDirWindows,
+		PWD:           "src:\\source\\",
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: "\\",
+	},
+	{
+		Case:          "Windows lower word drive (arbitrary cases)",
+		Expected:      "sRc: > source",
+		Home:          homeDirWindows,
+		PWD:           "sRc:\\source\\",
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: "\\",
+	},
+	{
+		Case:          "Windows registry drive",
+		Expected:      "\uf013 > SOFTWARE > f",
+		Home:          homeDirWindows,
+		PWD:           "HKLM:\\SOFTWARE\\magnetic:test\\",
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: "\\",
+	},
+	{
+		Case:          "Windows registry drive case sensitive",
+		Expected:      "\uf013 > SOFTWARE > f",
+		Home:          homeDirWindows,
+		PWD:           "HKLM:\\SOFTWARE\\magnetic:TOAST\\",
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: "\\",
+	},
+}
+
+var testFullAndFolderPathCases = []testFullAndFolderPathCase{
+	{Style: FolderType, FolderSeparatorIcon: "\\", Pwd: "C:\\", Expected: "C:\\", PathSeparator: "\\", GOOS: runtime.WINDOWS},
+	{Style: FolderType, FolderSeparatorIcon: "\\", Pwd: "\\\\localhost\\d$", Expected: "\\\\localhost\\d$", PathSeparator: "\\", GOOS: runtime.WINDOWS},
+	{Style: FolderType, FolderSeparatorIcon: "\\", Pwd: homeDirWindows, Expected: "~", PathSeparator: "\\", GOOS: runtime.WINDOWS},
+	{Style: Full, FolderSeparatorIcon: "\\", Pwd: homeDirWindows, Expected: "~", PathSeparator: "\\", GOOS: runtime.WINDOWS},
+	{Style: Full, FolderSeparatorIcon: "\\", Pwd: homeDirWindows + "\\abc", Expected: "~\\abc", PathSeparator: "\\", GOOS: runtime.WINDOWS},
+	{Style: Full, FolderSeparatorIcon: "\\", Pwd: "C:\\Users\\posh", Expected: "C:\\Users\\posh", PathSeparator: "\\", GOOS: runtime.WINDOWS},
+}
+
+var testFullPathCustomMappedLocationsCases = []testFullPathCustomMappedLocationsCase{
+	{Pwd: "\\a\\b\\c\\d", MappedLocations: map[string]string{"\\a\\b": "#"}, GOOS: runtime.WINDOWS, PathSeparator: "\\", Expected: "#\\c\\d"},
+}
+
+var testSplitPathCases = []testSplitPathCase{
+	{
+		Case:         "Home directory - git folder on Windows",
+		Root:         "C:",
+		Relative:     "a/b/c/d",
+		GOOS:         runtime.WINDOWS,
+		GitDir:       &runtime.FileInfo{IsDir: true, ParentFolder: "C:/a/b/c"},
+		GitDirFormat: "<b>%s</b>",
+		Expected: Folders{
+			{Name: "a", Path: "C:/a"},
+			{Name: "b", Path: "C:/a/b"},
+			{Name: "<b>c</b>", Path: "C:/a/b/c", Display: true},
+			{Name: "d", Path: "C:/a/b/c/d"},
+		},
+	},
+}
+
+var testNormalizePathCases = []testNormalizePathCase{
+	{
+		Case:          "Windows: absolute w/o drive letter, forward slash included",
+		Input:         "/foo/~/bar",
+		HomeDir:       homeDirWindows,
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: `\`,
+		Expected:      "\\foo\\~\\bar",
+	},
+	{
+		Case:          "Windows: absolute",
+		Input:         homeDirWindows + "\\Foo",
+		HomeDir:       homeDirWindows,
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: `\`,
+		Expected:      "c:\\users\\someone\\foo",
+	},
+	{
+		Case:          "Windows: home prefix",
+		Input:         "~\\Bob\\Foo",
+		HomeDir:       homeDirWindows,
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: `\`,
+		Expected:      "c:\\users\\someone\\bob\\foo",
+	},
+	{
+		Case:          "Windows: home prefix",
+		Input:         "~/baz",
+		HomeDir:       homeDirWindows,
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: `\`,
+		Expected:      "c:\\users\\someone\\baz",
+	},
+	{
+		Case:          "Windows: UNC root w/ prefix",
+		Input:         `\\.\UNC\localhost\c$`,
+		HomeDir:       homeDirWindows,
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: `\`,
+		Expected:      "\\\\localhost\\c$",
+	},
+	{
+		Case:          "Windows: UNC root w/ prefix, forward slash included",
+		Input:         "//./UNC/localhost/c$",
+		HomeDir:       homeDirWindows,
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: `\`,
+		Expected:      "\\\\localhost\\c$",
+	},
+	{
+		Case:          "Windows: UNC root",
+		Input:         `\\localhost\c$\`,
+		HomeDir:       homeDirWindows,
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: `\`,
+		Expected:      "\\\\localhost\\c$",
+	},
+	{
+		Case:          "Windows: UNC root, forward slash included",
+		Input:         "//localhost/c$",
+		HomeDir:       homeDirWindows,
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: `\`,
+		Expected:      "\\\\localhost\\c$",
+	},
+	{
+		Case:          "Windows: UNC",
+		Input:         `\\localhost\c$\some`,
+		HomeDir:       homeDirWindows,
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: `\`,
+		Expected:      "\\\\localhost\\c$\\some",
+	},
+	{
+		Case:          "Windows: UNC, forward slash included",
+		Input:         "//localhost/c$/some",
+		HomeDir:       homeDirWindows,
+		GOOS:          runtime.WINDOWS,
+		PathSeparator: `\`,
+		Expected:      "\\\\localhost\\c$\\some",
+	},
+}
diff --git a/src/segments/pulumi_test.go b/src/segments/pulumi_test.go
index b08091ec..0f07acf3 100644
--- a/src/segments/pulumi_test.go
+++ b/src/segments/pulumi_test.go
@@ -2,11 +2,13 @@ package segments
 
 import (
 	"errors"
+	"fmt"
 	"path/filepath"
 	"testing"
 
 	"github.com/jandedobbeleer/oh-my-posh/src/properties"
 	"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
+	"github.com/jandedobbeleer/oh-my-posh/src/runtime/path"
 	"github.com/stretchr/testify/assert"
 	testify_ "github.com/stretchr/testify/mock"
 )
@@ -161,7 +163,8 @@ description: A Console App
 		env.On("RunCommand", "pulumi", []string{"stack", "ls", "--json"}).Return(tc.Stack, tc.StackError)
 		env.On("RunCommand", "pulumi", []string{"about", "--json"}).Return(tc.About, tc.AboutError)
 
-		env.On("Pwd").Return("/home/foobar/Work/oh-my-posh/pulumi/projects/awesome-project")
+		pwd := "/home/foobar/Work/oh-my-posh/pulumi/projects/awesome-project"
+		env.On("Pwd").Return(pwd)
 		env.On("Home").Return(filepath.Clean("/home/foobar"))
 		env.On("Error", testify_.Anything)
 		env.On("Debug", testify_.Anything)
@@ -173,11 +176,22 @@ description: A Console App
 		env.On("HasFiles", pulumiJSON).Return(len(tc.JSONConfig) > 0)
 		env.On("FileContent", pulumiJSON).Return(tc.JSONConfig, nil)
 
-		env.On("PathSeparator").Return("/")
-
 		env.On("HasFolder", filepath.Clean("/home/foobar/.pulumi/workspaces")).Return(tc.HasWorkspaceFolder)
-		workspaceFile := "oh-my-posh-c62b7b6786c5c5a85896576e46a25d7c9f888e92-workspace.json"
+
+		pulumi := &Pulumi{}
+
+		var fileName string
+		if len(tc.JSONConfig) > 0 {
+			fileName = pulumiJSON
+		} else {
+			fileName = pulumiYAML
+		}
+
+		sha1 := pulumi.sha1HexString(pwd + path.Separator() + fileName)
+		workspaceFile := fmt.Sprintf("oh-my-posh-%s-workspace.json", sha1)
+
 		env.On("HasFilesInDir", filepath.Clean("/home/foobar/.pulumi/workspaces"), workspaceFile).Return(len(tc.WorkSpaceFile) > 0)
+
 		env.On("FileContent", filepath.Clean("/home/foobar/.pulumi/workspaces/"+workspaceFile)).Return(tc.WorkSpaceFile, nil)
 
 		props := properties.Map{
@@ -185,7 +199,6 @@ description: A Console App
 			FetchAbout: tc.FetchAbout,
 		}
 
-		pulumi := &Pulumi{}
 		pulumi.Init(props, env)
 
 		assert.Equal(t, tc.ExpectedEnabled, pulumi.Enabled(), tc.Case)
diff --git a/src/segments/sapling_test.go b/src/segments/sapling_test.go
index dc8461bf..28bc29b8 100644
--- a/src/segments/sapling_test.go
+++ b/src/segments/sapling_test.go
@@ -18,25 +18,13 @@ func TestSetDir(t *testing.T) {
 		GOOS     string
 	}{
 		{
-			Case:     "In home folder",
-			Expected: "~/sapling",
-			Path:     "/usr/home/sapling/.sl",
-			GOOS:     runtime.LINUX,
-		},
-		{
-			Case:     "Outside home folder",
+			Case:     "Linux",
 			Expected: "/usr/sapling/repo",
 			Path:     "/usr/sapling/repo/.sl",
 			GOOS:     runtime.LINUX,
 		},
 		{
-			Case:     "Windows home folder",
-			Expected: "~\\sapling",
-			Path:     "\\usr\\home\\sapling\\.sl",
-			GOOS:     runtime.WINDOWS,
-		},
-		{
-			Case:     "Windows outside home folder",
+			Case:     "Windows",
 			Expected: "\\usr\\sapling\\repo",
 			Path:     "\\usr\\sapling\\repo\\.sl",
 			GOOS:     runtime.WINDOWS,
diff --git a/src/segments/session_test.go b/src/segments/session_test.go
index 26155c38..3e8d81fb 100644
--- a/src/segments/session_test.go
+++ b/src/segments/session_test.go
@@ -8,6 +8,7 @@ import (
 	"github.com/jandedobbeleer/oh-my-posh/src/properties"
 	"github.com/jandedobbeleer/oh-my-posh/src/runtime"
 	"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
+	"github.com/jandedobbeleer/oh-my-posh/src/template"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -127,12 +128,6 @@ func TestSessionSegmentTemplate(t *testing.T) {
 		env.On("Getenv", "SSH_CLIENT").Return(SSHSession)
 		env.On("Getenv", "POSH_SESSION_DEFAULT_USER").Return(tc.DefaultUserName)
 
-		env.On("TemplateCache").Return(&cache.Template{
-			UserName: tc.UserName,
-			HostName: tc.ComputerName,
-			Root:     tc.Root,
-		})
-
 		env.On("Platform").Return(tc.Platform)
 
 		var whoAmIErr error
@@ -145,6 +140,12 @@ func TestSessionSegmentTemplate(t *testing.T) {
 		session := &Session{}
 		session.Init(properties.Map{}, env)
 
+		template.Cache = &cache.Template{
+			UserName: tc.UserName,
+			HostName: tc.ComputerName,
+			Root:     tc.Root,
+		}
+
 		_ = session.Enabled()
 		assert.Equal(t, tc.ExpectedString, renderTemplate(env, tc.Template, session), tc.Case)
 	}
diff --git a/src/segments/status_test.go b/src/segments/status_test.go
index e48af9d3..b85f2fd8 100644
--- a/src/segments/status_test.go
+++ b/src/segments/status_test.go
@@ -5,11 +5,11 @@ import (
 
 	"github.com/jandedobbeleer/oh-my-posh/src/cache"
 	"github.com/jandedobbeleer/oh-my-posh/src/properties"
-	"github.com/jandedobbeleer/oh-my-posh/src/runtime"
 	"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
+	"github.com/jandedobbeleer/oh-my-posh/src/shell"
+	"github.com/jandedobbeleer/oh-my-posh/src/template"
 
 	"github.com/stretchr/testify/assert"
-	testify_ "github.com/stretchr/testify/mock"
 )
 
 func TestStatusWriterEnabled(t *testing.T) {
@@ -27,18 +27,18 @@ func TestStatusWriterEnabled(t *testing.T) {
 	for _, tc := range cases {
 		env := new(mock.Environment)
 		env.On("StatusCodes").Return(tc.Status, "")
-		env.On("TemplateCache").Return(&cache.Template{
-			Code: 133,
-		})
-		env.On("Error", testify_.Anything).Return(nil)
-		env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
-		env.On("Flags").Return(&runtime.Flags{})
+		env.On("Shell").Return(shell.GENERIC)
 
 		props := properties.Map{}
 		if len(tc.Template) > 0 {
 			props[StatusTemplate] = tc.Template
 		}
 
+		template.Cache = &cache.Template{
+			Code: 133,
+		}
+		template.Init(env, nil)
+
 		s := &Status{}
 		s.Init(props, env)
 
diff --git a/src/segments/text_test.go b/src/segments/text_test.go
index b10ea67a..ea196a2f 100644
--- a/src/segments/text_test.go
+++ b/src/segments/text_test.go
@@ -6,6 +6,7 @@ import (
 	"github.com/jandedobbeleer/oh-my-posh/src/cache"
 	"github.com/jandedobbeleer/oh-my-posh/src/properties"
 	"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
+	"github.com/jandedobbeleer/oh-my-posh/src/template"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -29,19 +30,20 @@ func TestTextSegment(t *testing.T) {
 	for _, tc := range cases {
 		env := new(mock.Environment)
 		env.On("PathSeparator").Return("/")
-		env.On("TemplateCache").Return(&cache.Template{
-			UserName: "Posh",
-			HostName: "MyHost",
-			Shell:    "terminal",
-			Root:     true,
-			Folder:   "posh",
-		})
 		env.On("Getenv", "HELLO").Return("hello")
 		env.On("Getenv", "WORLD").Return("")
 
 		txt := &Text{}
 		txt.Init(properties.Map{}, env)
 
+		template.Cache = &cache.Template{
+			UserName: "Posh",
+			HostName: "MyHost",
+			Shell:    "terminal",
+			Root:     true,
+			Folder:   "posh",
+		}
+
 		assert.Equal(t, tc.ExpectedString, renderTemplate(env, tc.Template, txt), tc.Case)
 	}
 }
diff --git a/src/segments/ui5tooling_test.go b/src/segments/ui5tooling_test.go
index 386c8e1b..6bc2b81f 100644
--- a/src/segments/ui5tooling_test.go
+++ b/src/segments/ui5tooling_test.go
@@ -10,7 +10,6 @@ import (
 	"github.com/jandedobbeleer/oh-my-posh/src/template"
 
 	"github.com/stretchr/testify/assert"
-	testify_ "github.com/stretchr/testify/mock"
 )
 
 const (
@@ -93,10 +92,10 @@ func TestUI5Tooling(t *testing.T) {
 			tc.Template = ui5tooling.Template()
 		}
 
+		// this is needed to build the version URL as before renderTemplate, the template is not initialized
 		env.On("Shell").Return("foo")
-		env.On("TemplateCache").Return(&cache.Template{})
-		env.On("Trace", testify_.Anything, testify_.Anything).Return(nil)
-		template.Init(env)
+		template.Cache = &cache.Template{}
+		template.Init(env, nil)
 
 		failMsg := fmt.Sprintf("Failed in case: %s", tc.Case)
 		assert.True(t, ui5tooling.Enabled(), failMsg)
diff --git a/src/template/files_test.go b/src/template/files_test.go
index 4d3da849..b8f86238 100644
--- a/src/template/files_test.go
+++ b/src/template/files_test.go
@@ -7,7 +7,6 @@ import (
 	"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
 
 	"github.com/stretchr/testify/assert"
-	testify_ "github.com/stretchr/testify/mock"
 )
 
 func TestGlob(t *testing.T) {
@@ -23,12 +22,10 @@ func TestGlob(t *testing.T) {
 	}
 
 	env := &mock.Environment{}
-	env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
-	env.On("TemplateCache").Return(&cache.Template{})
 	env.On("Shell").Return("foo")
-	env.On("Trace", testify_.Anything, testify_.Anything).Return(nil)
 
-	Init(env)
+	Cache = new(cache.Template)
+	Init(env, nil)
 
 	for _, tc := range cases {
 		tmpl := &Text{
diff --git a/src/template/link_test.go b/src/template/link_test.go
index 1f80551f..136755d3 100644
--- a/src/template/link_test.go
+++ b/src/template/link_test.go
@@ -7,7 +7,6 @@ import (
 	"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
 
 	"github.com/stretchr/testify/assert"
-	testify_ "github.com/stretchr/testify/mock"
 )
 
 func TestUrl(t *testing.T) {
@@ -22,14 +21,11 @@ func TestUrl(t *testing.T) {
 	}
 
 	env := &mock.Environment{}
-	env.On("TemplateCache").Return(&cache.Template{})
-	env.On("Error", testify_.Anything)
-	env.On("Debug", testify_.Anything)
-	env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
 	env.On("Shell").Return("foo")
-	env.On("Trace", testify_.Anything, testify_.Anything).Return(nil)
 
-	Init(env)
+	Cache = new(cache.Template)
+
+	Init(env, nil)
 
 	for _, tc := range cases {
 		tmpl := &Text{
diff --git a/src/template/text_test.go b/src/template/text_test.go
index 85ede36a..40b1f11d 100644
--- a/src/template/text_test.go
+++ b/src/template/text_test.go
@@ -5,11 +5,9 @@ import (
 
 	"github.com/jandedobbeleer/oh-my-posh/src/cache"
 	"github.com/jandedobbeleer/oh-my-posh/src/maps"
-	"github.com/jandedobbeleer/oh-my-posh/src/runtime"
 	"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
 
 	"github.com/stretchr/testify/assert"
-	testify_ "github.com/stretchr/testify/mock"
 )
 
 func TestRenderTemplate(t *testing.T) {
@@ -238,20 +236,16 @@ func TestRenderTemplateEnvVar(t *testing.T) {
 	}
 	for _, tc := range cases {
 		env := &mock.Environment{}
-		env.On("Error", testify_.Anything)
-		env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
-		env.On("Flags").Return(&runtime.Flags{})
 		env.On("Shell").Return("foo")
-		env.On("Trace", testify_.Anything, testify_.Anything).Return(nil)
-		env.On("TemplateCache").Return(&cache.Template{
-			OS: "darwin",
-		})
 
 		for k, v := range tc.Env {
 			env.On("Getenv", k).Return(v)
 		}
 
-		Init(env)
+		Cache = &cache.Template{
+			OS: "darwin",
+		}
+		Init(env, nil)
 
 		tmpl := &Text{
 			Template: tc.Template,
@@ -344,7 +338,7 @@ func TestPatchTemplate(t *testing.T) {
 	env := &mock.Environment{}
 	env.On("Shell").Return("foo")
 
-	Init(env)
+	Init(env, nil)
 
 	for _, tc := range cases {
 		tmpl := &Text{
@@ -370,14 +364,12 @@ func TestSegmentContains(t *testing.T) {
 	env := &mock.Environment{}
 	segments := maps.NewConcurrent()
 	segments.Set("Git", "foo")
-	env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
-	env.On("TemplateCache").Return(&cache.Template{
-		Segments: segments,
-	})
 	env.On("Shell").Return("foo")
-	env.On("Trace", testify_.Anything, testify_.Anything).Return(nil)
 
-	Init(env)
+	Cache = &cache.Template{
+		Segments: segments,
+	}
+	Init(env, nil)
 
 	for _, tc := range cases {
 		tmpl := &Text{