Repository: JanDeDobbeleer/oh-my-posh
Pull request #2856 (2022-09-30 15:32:49)

fix(path): parse path correctly
### Prerequisites

- [x] I have read and understood the [contributing guide][CONTRIBUTING.md]
- [x] The commit message follows the [conventional commits][cc] guidelines
- [x] Tests for the changes have been added (for bug fixes/features)
- [x] Docs have been added/updated (for bug fixes/features)

### Description

Refactor most of the logic for rendering a `path` segment. For a full path, parse it to a root and a path, replace mapped locations and join results with separators to get a clean path.

With these changes, we can handle various types of paths (Unix, Windows, PSDrive and UNC). I've considered lots of annoying edge cases, especially a Windows drive root and a UNC path. The following bugs in a `path` segment will be fixed:

1. In PowerShell, when the CWD is a Windows root path, e.g., `C:\`, the `.Parent` should be empty as expected, however it is actually `C:.\`.
2. In PowerShell, mapped locations don't work for some PSDrive paths like `HKLM:\SOFTWARE` (Windows only) and `Function:/`.
3. Using `\` as the path separator for a mapped location can cause a path misidentification on Unix-like systems. In fact, `\` is a valid character in a file/directory name on Linux/macOS, which means it cannot be used to separate path elements.
4. The custom folder separator (`folder_separator_icon`) does not work in the `.Parent`.
5. The `.Parent` is not properly set based on the actual value of the `.Path`. E.g., when the CWD is the Home path, it is always set to empty even if the Home path is not replaced with a single tilde (`~`). To make sense, a mapped location replacement, if any, should be done before we start to extract the parent path.

[CONTRIBUTING.md]: https://github.com/JanDeDobbeleer/oh-my-posh/blob/main/CONTRIBUTING.md
[cc]: https://www.conventionalcommits.org/en/v1.0.0/#summary


JanDeDobbeleer: This is going to take a while to go through. Kudos on the bravery though, I can already credit that. This is one of the oldest and most annoying segments.
lewis-yeung: > Can we do this outside of the style logic's?

@JanDeDobbeleer Yes, we can. Will do it later, maybe when I'm free.

lewis-yeung: @JanDeDobbeleer Updated. Should we move on?

Patch:
diff --git a/src/engine/block.go b/src/engine/block.go
index 618c088e..83c37e31 100644
--- a/src/engine/block.go
+++ b/src/engine/block.go
@@ -22,7 +22,7 @@ const (
 	Prompt BlockType = "prompt"
 	// LineBreak creates a line break in the prompt
 	LineBreak BlockType = "newline"
-	// RPrompt a right aligned prompt in ZSH and Powershell
+	// RPrompt is a right aligned prompt
 	RPrompt BlockType = "rprompt"
 	// Left aligns left
 	Left BlockAlignment = "left"
diff --git a/src/engine/engine.go b/src/engine/engine.go
index 8b11a63f..4d0d88d4 100644
--- a/src/engine/engine.go
+++ b/src/engine/engine.go
@@ -130,7 +130,7 @@ func (e *Engine) shouldFill(block *Block, length int) (string, bool) {
 
 func (e *Engine) renderBlock(block *Block) {
 	defer func() {
-		// Due to a bug in Powershell, the end of the line needs to be cleared.
+		// Due to a bug in PowerShell, the end of the line needs to be cleared.
 		// If this doesn't happen, the portion after the prompt gets colored in the background
 		// color of the line above the new input line. Clearing the line fixes this,
 		// but can hopefully one day be removed when this is resolved natively.
diff --git a/src/environment/shell.go b/src/environment/shell.go
index a31bb717..b1d2763f 100644
--- a/src/environment/shell.go
+++ b/src/environment/shell.go
@@ -337,11 +337,16 @@ func (env *ShellEnvironment) Pwd() string {
 	}
 	correctPath := func(pwd string) string {
 		// on Windows, and being case sensitive and not consistent and all, this gives silly issues
-		driveLetter := regex.GetCompiledRegex(`^[a-z]:`)
-		return driveLetter.ReplaceAllStringFunc(pwd, strings.ToUpper)
+		if env.GOOS() == WINDOWS {
+			driveLetter := regex.GetCompiledRegex(`^[a-z]:`)
+			return driveLetter.ReplaceAllStringFunc(pwd, strings.ToUpper)
+		}
+		return pwd
 	}
 	if env.CmdFlags != nil && env.CmdFlags.PWD != "" {
-		env.cwd = correctPath(env.CmdFlags.PWD)
+		// ensure a clean path
+		root, path := ParsePath(env, correctPath(env.CmdFlags.PWD))
+		env.cwd = root + path
 		return env.cwd
 	}
 	dir, err := os.Getwd()
@@ -735,6 +740,9 @@ func (env *ShellEnvironment) TemplateCache() *TemplateCache {
 	pwd := env.Pwd()
 	tmplCache.PWD = ReplaceHomeDirPrefixWithTilde(env, pwd)
 	tmplCache.Folder = Base(env, pwd)
+	if env.GOOS() == WINDOWS && strings.HasSuffix(tmplCache.Folder, ":") {
+		tmplCache.Folder += `\`
+	}
 	tmplCache.UserName = env.User()
 	if host, err := env.Host(); err == nil {
 		tmplCache.HostName = host
@@ -766,19 +774,21 @@ func (env *ShellEnvironment) DirMatchesOneOf(dir string, regexes []string) (matc
 }
 
 func dirMatchesOneOf(dir, home, goos string, regexes []string) bool {
-	normalizedCwd := strings.ReplaceAll(dir, "\\", "/")
-	normalizedHomeDir := strings.ReplaceAll(home, "\\", "/")
+	if goos == WINDOWS {
+		dir = strings.ReplaceAll(dir, "\\", "/")
+		home = strings.ReplaceAll(home, "\\", "/")
+	}
 
 	for _, element := range regexes {
 		normalizedElement := strings.ReplaceAll(element, "\\\\", "/")
 		if strings.HasPrefix(normalizedElement, "~") {
-			normalizedElement = strings.Replace(normalizedElement, "~", normalizedHomeDir, 1)
+			normalizedElement = strings.Replace(normalizedElement, "~", home, 1)
 		}
 		pattern := fmt.Sprintf("^%s$", normalizedElement)
 		if goos == WINDOWS || goos == DARWIN {
 			pattern = "(?i)" + pattern
 		}
-		matched := regex.MatchString(pattern, normalizedCwd)
+		matched := regex.MatchString(pattern, dir)
 		if matched {
 			return true
 		}
@@ -786,7 +796,7 @@ func dirMatchesOneOf(dir, home, goos string, regexes []string) bool {
 	return false
 }
 
-func isPathSeparator(env Environment, c uint8) bool {
+func IsPathSeparator(env Environment, c uint8) bool {
 	if c == '/' {
 		return true
 	}
@@ -800,14 +810,14 @@ func isPathSeparator(env Environment, c uint8) bool {
 // 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 {
-	if path == "/" {
-		return path
-	}
 	volumeName := filepath.VolumeName(path)
 	// Strip trailing slashes.
-	for len(path) > 0 && isPathSeparator(env, path[len(path)-1]) {
+	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
 	}
@@ -815,22 +825,69 @@ func Base(env Environment, path string) string {
 	path = path[len(filepath.VolumeName(path)):]
 	// Find the last element
 	i := len(path) - 1
-	for i >= 0 && !isPathSeparator(env, path[i]) {
+	for i >= 0 && !IsPathSeparator(env, path[i]) {
 		i--
 	}
 	if i >= 0 {
 		path = path[i+1:]
 	}
 	// If empty now, it had only slashes.
-	if path == "" {
+	if len(path) == 0 {
 		return env.PathSeparator()
 	}
 	return path
 }
 
+// ParsePath parses an input path and returns a clean root and a clean path.
+func ParsePath(env Environment, inputPath string) (root, path string) {
+	if len(inputPath) == 0 {
+		return
+	}
+	separator := env.PathSeparator()
+	clean := func(path string) string {
+		matches := regex.FindAllNamedRegexMatch(fmt.Sprintf(`(?P<element>[^\%s]+)`, separator), path)
+		n := len(matches) - 1
+		s := new(strings.Builder)
+		for i, m := range matches {
+			s.WriteString(m["element"])
+			if i != n {
+				s.WriteString(separator)
+			}
+		}
+		return s.String()
+	}
+
+	if env.GOOS() == WINDOWS {
+		inputPath = strings.ReplaceAll(inputPath, "/", `\`)
+		// for a UNC path, extract \\hostname\sharename as the root
+		matches := regex.FindNamedRegexMatch(`^\\\\(?P<hostname>[^\\]+)\\+(?P<sharename>[^\\]+)\\*(?P<path>[\s\S]*)$`, inputPath)
+		if len(matches) > 0 {
+			root = `\\` + matches["hostname"] + `\` + matches["sharename"] + `\`
+			path = clean(matches["path"])
+			return
+		}
+	}
+	s := strings.SplitAfterN(inputPath, separator, 2)
+	root = s[0]
+	if !strings.HasSuffix(root, separator) {
+		// a root should end with a separator
+		root += separator
+	}
+	if len(s) == 2 {
+		path = clean(s[1])
+	}
+	return root, path
+}
+
 func ReplaceHomeDirPrefixWithTilde(env Environment, path string) string {
-	if strings.HasPrefix(path, env.Home()) {
-		return strings.Replace(path, env.Home(), "~", 1)
+	home := env.Home()
+	// match Home directory exactly
+	if !strings.HasPrefix(path, home) {
+		return path
+	}
+	rem := path[len(home):]
+	if len(rem) == 0 || IsPathSeparator(env, rem[0]) {
+		return "~" + rem
 	}
 	return path
 }
diff --git a/src/segments/path.go b/src/segments/path.go
index fbaa33cd..120e1fc6 100644
--- a/src/segments/path.go
+++ b/src/segments/path.go
@@ -5,8 +5,8 @@ import (
 	"oh-my-posh/environment"
 	"oh-my-posh/properties"
 	"oh-my-posh/regex"
+	"oh-my-posh/shell"
 	"oh-my-posh/template"
-	"path/filepath"
 	"sort"
 	"strings"
 )
@@ -45,7 +45,7 @@ const (
 	Full string = "full"
 	// Folder displays the current folder
 	Folder string = "folder"
-	// Mixed like agnoster, but if the path is short it displays it
+	// Mixed like agnoster, but if a folder name is short enough, it is displayed as-is
 	Mixed string = "mixed"
 	// Letter like agnoster, but with the first letter of each folder name
 	Letter string = "letter"
@@ -70,64 +70,33 @@ func (pt *Path) Template() string {
 }
 
 func (pt *Path) Enabled() bool {
-	pt.pwd = pt.env.Pwd()
-	switch style := pt.props.GetString(properties.Style, Agnoster); style {
-	case Agnoster:
-		pt.Path = pt.getAgnosterPath()
-	case AgnosterFull:
-		pt.Path = pt.getAgnosterFullPath()
-	case AgnosterShort:
-		pt.Path = pt.getAgnosterShortPath()
-	case Mixed:
-		pt.Path = pt.getMixedPath()
-	case Letter:
-		pt.Path = pt.getLetterPath()
-	case Unique:
-		pt.Path = pt.getUniqueLettersPath()
-	case AgnosterLeft:
-		pt.Path = pt.getAgnosterLeftPath()
-	case Short:
-		// "short" is a duplicate of "full", just here for backwards compatibility
-		fallthrough
-	case Full:
-		pt.Path = pt.getFullPath()
-	case Folder:
-		pt.Path = pt.getFolderPath()
-	default:
-		pt.Path = fmt.Sprintf("Path style: %s is not available", style)
-	}
-	pt.Path = pt.formatWindowsDrive(pt.Path)
+	pt.setPath()
 	if pt.env.IsWsl() {
 		pt.Location, _ = pt.env.RunCommand("wslpath", "-m", pt.pwd)
 	} else {
 		pt.Location = pt.pwd
 	}
-
 	pt.StackCount = pt.env.StackCount()
 	pt.Writable = pt.env.DirIsWritable(pt.pwd)
 	return true
 }
 
 func (pt *Path) Parent() string {
-	if pt.pwd == pt.env.Home() {
+	pwd := pt.getPwd()
+	if len(pwd) == 0 {
 		return ""
 	}
-	parent := filepath.Dir(pt.pwd)
-	if pt.pwd == parent {
+	root, path := environment.ParsePath(pt.env, pwd)
+	if len(path) == 0 {
+		// a root path has no parent
 		return ""
 	}
-	separator := pt.env.PathSeparator()
-	if parent == pt.rootLocation() || parent == separator {
-		separator = ""
-	}
-	return pt.replaceMappedLocations(parent) + separator
-}
-
-func (pt *Path) formatWindowsDrive(pwd string) string {
-	if pt.env.GOOS() != environment.WINDOWS || !strings.HasSuffix(pwd, ":") {
-		return pwd
+	base := environment.Base(pt.env, path)
+	path = pt.replaceFolderSeparators(path[:len(path)-len(base)])
+	if root != pt.env.PathSeparator() {
+		root = root[:len(root)-1] + pt.getFolderSeparator()
 	}
-	return pwd + "\\"
+	return root + path
 }
 
 func (pt *Path) Init(props properties.Properties, env environment.Environment) {
@@ -135,10 +104,52 @@ func (pt *Path) Init(props properties.Properties, env environment.Environment) {
 	pt.env = env
 }
 
+func (pt *Path) setPath() {
+	pwd := pt.getPwd()
+	if len(pwd) == 0 {
+		return
+	}
+	root, path := environment.ParsePath(pt.env, pwd)
+	if len(path) == 0 {
+		pt.Path = pt.formatRoot(root)
+		return
+	}
+	switch style := pt.props.GetString(properties.Style, Agnoster); style {
+	case Agnoster:
+		pt.Path = pt.getAgnosterPath(root, path)
+	case AgnosterFull:
+		pt.Path = pt.getAgnosterFullPath(root, path)
+	case AgnosterShort:
+		pt.Path = pt.getAgnosterShortPath(root, path)
+	case Mixed:
+		pt.Path = pt.getMixedPath(root, path)
+	case Letter:
+		pt.Path = pt.getLetterPath(root, path)
+	case Unique:
+		pt.Path = pt.getUniqueLettersPath(root, path)
+	case AgnosterLeft:
+		pt.Path = pt.getAgnosterLeftPath(root, path)
+	case Short:
+		// "short" is a duplicate of "full", just here for backwards compatibility
+		fallthrough
+	case Full:
+		pt.Path = pt.getFullPath(root, path)
+	case Folder:
+		pt.Path = pt.getFolderPath(path)
+	default:
+		pt.Path = fmt.Sprintf("Path style: %s is not available", style)
+	}
+}
+
 func (pt *Path) getFolderSeparator() string {
 	separatorTemplate := pt.props.GetString(FolderSeparatorTemplate, "")
 	if len(separatorTemplate) == 0 {
-		return pt.props.GetString(FolderSeparatorIcon, pt.env.PathSeparator())
+		separator := pt.props.GetString(FolderSeparatorIcon, pt.env.PathSeparator())
+		// if empty, use the default separator
+		if len(separator) == 0 {
+			return pt.env.PathSeparator()
+		}
+		return separator
 	}
 	tmpl := &template.Text{
 		Template: separatorTemplate,
@@ -149,67 +160,66 @@ func (pt *Path) getFolderSeparator() string {
 	if err != nil {
 		pt.env.Log(environment.Error, "getFolderSeparator", err.Error())
 	}
+	if len(text) == 0 {
+		return pt.env.PathSeparator()
+	}
 	return text
 }
 
-func (pt *Path) getMixedPath() string {
+func (pt *Path) getMixedPath(root, path string) string {
 	var buffer strings.Builder
-	pwd := pt.getPwd()
-	splitted := strings.Split(pwd, pt.env.PathSeparator())
 	threshold := int(pt.props.GetFloat64(MixedThreshold, 4))
-	for i, part := range splitted {
-		if part == "" {
-			continue
-		}
-
-		folder := part
-		if len(part) > threshold && i != 0 && i != len(splitted)-1 {
-			folder = pt.props.GetString(FolderIcon, "..")
-		}
-		separator := pt.getFolderSeparator()
-		if i == 0 {
-			separator = ""
+	folderIcon := pt.props.GetString(FolderIcon, "..")
+	separator := pt.getFolderSeparator()
+	elements := strings.Split(path, pt.env.PathSeparator())
+	if root != pt.env.PathSeparator() {
+		elements = append([]string{root[:len(root)-1]}, elements...)
+	}
+	n := len(elements)
+	buffer.WriteString(elements[0])
+	for i := 1; i < n; i++ {
+		folder := elements[i]
+		if len(folder) > threshold && i != n-1 {
+			folder = folderIcon
 		}
 		buffer.WriteString(fmt.Sprintf("%s%s", separator, folder))
 	}
-
 	return buffer.String()
 }
 
-func (pt *Path) getAgnosterPath() string {
+func (pt *Path) getAgnosterPath(root, path string) string {
 	var buffer strings.Builder
-	pwd := pt.getPwd()
-	buffer.WriteString(pt.rootLocation())
-	pathDepth := pt.pathDepth(pwd)
 	folderIcon := pt.props.GetString(FolderIcon, "..")
 	separator := pt.getFolderSeparator()
-	for i := 1; i < pathDepth; i++ {
+	elements := strings.Split(path, pt.env.PathSeparator())
+	if root != pt.env.PathSeparator() {
+		elements = append([]string{root[:len(root)-1]}, elements...)
+	}
+	n := len(elements)
+	buffer.WriteString(elements[0])
+	for i := 2; i < n; i++ {
 		buffer.WriteString(fmt.Sprintf("%s%s", separator, folderIcon))
 	}
-	if pathDepth > 0 {
-		buffer.WriteString(fmt.Sprintf("%s%s", separator, environment.Base(pt.env, pwd)))
+	if n > 1 {
+		buffer.WriteString(fmt.Sprintf("%s%s", separator, elements[n-1]))
 	}
 	return buffer.String()
 }
 
-func (pt *Path) getAgnosterLeftPath() string {
-	pwd := pt.getPwd()
-	separator := pt.env.PathSeparator()
-	pwd = strings.Trim(pwd, separator)
-	splitted := strings.Split(pwd, separator)
+func (pt *Path) getAgnosterLeftPath(root, path string) string {
+	var buffer strings.Builder
 	folderIcon := pt.props.GetString(FolderIcon, "..")
-	separator = pt.getFolderSeparator()
-	switch len(splitted) {
-	case 0:
-		return ""
-	case 1:
-		return splitted[0]
-	case 2:
-		return fmt.Sprintf("%s%s%s", splitted[0], separator, splitted[1])
+	separator := pt.getFolderSeparator()
+	elements := strings.Split(path, pt.env.PathSeparator())
+	if root != pt.env.PathSeparator() {
+		elements = append([]string{root[:len(root)-1]}, elements...)
 	}
-	var buffer strings.Builder
-	buffer.WriteString(fmt.Sprintf("%s%s%s", splitted[0], separator, splitted[1]))
-	for i := 2; i < len(splitted); i++ {
+	n := len(elements)
+	buffer.WriteString(elements[0])
+	if n > 1 {
+		buffer.WriteString(fmt.Sprintf("%s%s", separator, elements[1]))
+	}
+	for i := 2; i < n; i++ {
 		buffer.WriteString(fmt.Sprintf("%s%s", separator, folderIcon))
 	}
 	return buffer.String()
@@ -218,7 +228,7 @@ func (pt *Path) getAgnosterLeftPath() string {
 func (pt *Path) getRelevantLetter(folder string) string {
 	// check if there is at least a letter we can use
 	matches := regex.FindNamedRegexMatch(`(?P<letter>[\p{L}0-9]).*`, folder)
-	if matches == nil || matches["letter"] == "" {
+	if matches == nil || len(matches["letter"]) == 0 {
 		// no letter found, keep the folder unchanged
 		return folder
 	}
@@ -228,36 +238,36 @@ func (pt *Path) getRelevantLetter(folder string) string {
 	return letter
 }
 
-func (pt *Path) getLetterPath() string {
+func (pt *Path) getLetterPath(root, path string) string {
 	var buffer strings.Builder
-	pwd := pt.getPwd()
-	splitted := strings.Split(pwd, pt.env.PathSeparator())
 	separator := pt.getFolderSeparator()
-	for i := 0; i < len(splitted)-1; i++ {
-		folder := splitted[i]
-		if len(folder) == 0 {
-			continue
+	elements := strings.Split(path, pt.env.PathSeparator())
+	if root != pt.env.PathSeparator() {
+		elements = append([]string{root[:len(root)-1]}, elements...)
+	}
+	n := len(elements)
+	for i := 0; i < n-1; i++ {
+		letter := pt.getRelevantLetter(elements[i])
+		if i != 0 {
+			buffer.WriteString(separator)
 		}
-		letter := pt.getRelevantLetter(folder)
-		buffer.WriteString(fmt.Sprintf("%s%s", letter, separator))
-	}
-	if len(splitted) > 0 {
-		buffer.WriteString(splitted[len(splitted)-1])
+		buffer.WriteString(letter)
 	}
+	buffer.WriteString(fmt.Sprintf("%s%s", separator, elements[n-1]))
 	return buffer.String()
 }
 
-func (pt *Path) getUniqueLettersPath() string {
+func (pt *Path) getUniqueLettersPath(root, path string) string {
 	var buffer strings.Builder
-	pwd := pt.getPwd()
-	splitted := strings.Split(pwd, pt.env.PathSeparator())
 	separator := pt.getFolderSeparator()
-	letters := make(map[string]bool, len(splitted))
-	for i := 0; i < len(splitted)-1; i++ {
-		folder := splitted[i]
-		if len(folder) == 0 {
-			continue
-		}
+	elements := strings.Split(path, pt.env.PathSeparator())
+	if root != pt.env.PathSeparator() {
+		elements = append([]string{root[:len(root)-1]}, elements...)
+	}
+	n := len(elements)
+	letters := make(map[string]bool)
+	for i := 0; i < n-1; i++ {
+		folder := elements[i]
 		letter := pt.getRelevantLetter(folder)
 		for letters[letter] {
 			if letter == folder {
@@ -266,102 +276,126 @@ func (pt *Path) getUniqueLettersPath() string {
 			letter += folder[len(letter) : len(letter)+1]
 		}
 		letters[letter] = true
-		buffer.WriteString(fmt.Sprintf("%s%s", letter, separator))
-	}
-	if len(splitted) > 0 {
-		buffer.WriteString(splitted[len(splitted)-1])
+		if i != 0 {
+			buffer.WriteString(separator)
+		}
+		buffer.WriteString(letter)
 	}
+	buffer.WriteString(fmt.Sprintf("%s%s", separator, elements[n-1]))
 	return buffer.String()
 }
 
-func (pt *Path) getAgnosterFullPath() string {
-	pwd := pt.getPwd()
-	for len(pwd) > 1 && string(pwd[0]) == pt.env.PathSeparator() {
-		pwd = pwd[1:]
+func (pt *Path) getAgnosterFullPath(root, path string) string {
+	path = pt.replaceFolderSeparators(path)
+	if root == pt.env.PathSeparator() {
+		return path
 	}
-	return pt.replaceFolderSeparators(pwd)
+	root = root[:len(root)-1] + pt.getFolderSeparator()
+	return root + path
 }
 
-func (pt *Path) getAgnosterShortPath() string {
-	pwd := pt.getPwd()
-	pathDepth := pt.pathDepth(pwd)
+func (pt *Path) getAgnosterShortPath(root, path string) string {
+	elements := strings.Split(path, pt.env.PathSeparator())
+	if root != pt.env.PathSeparator() {
+		elements = append([]string{root[:len(root)-1]}, elements...)
+	}
+	depth := len(elements)
 	maxDepth := pt.props.GetInt(MaxDepth, 1)
 	if maxDepth < 1 {
 		maxDepth = 1
 	}
 	hideRootLocation := pt.props.GetBool(HideRootLocation, false)
-	if hideRootLocation {
-		// 1-indexing to avoid showing the root location when exceeding the max depth
-		pathDepth++
+	if !hideRootLocation {
+		maxDepth++
 	}
-	if pathDepth <= maxDepth {
-		return pt.getAgnosterFullPath()
+	if depth <= maxDepth {
+		return pt.getAgnosterFullPath(root, path)
 	}
-	folderSeparator := pt.getFolderSeparator()
-	pathSeparator := pt.env.PathSeparator()
-	splitted := strings.Split(pwd, pathSeparator)
-	fullPathDepth := len(splitted)
-	splitPos := fullPathDepth - maxDepth
+	separator := pt.getFolderSeparator()
+	folderIcon := pt.props.GetString(FolderIcon, "..")
 	var buffer strings.Builder
-	if hideRootLocation {
-		buffer.WriteString(splitted[splitPos])
-		splitPos++
-	} else {
-		folderIcon := pt.props.GetString(FolderIcon, "..")
-		root := pt.rootLocation()
-		buffer.WriteString(fmt.Sprintf("%s%s%s", root, folderSeparator, folderIcon))
-	}
-	for i := splitPos; i < fullPathDepth; i++ {
-		buffer.WriteString(fmt.Sprintf("%s%s", folderSeparator, splitted[i]))
+	if !hideRootLocation {
+		buffer.WriteString(fmt.Sprintf("%s%s", elements[0], separator))
+		maxDepth--
+	}
+	splitPos := depth - maxDepth
+	if splitPos != 1 {
+		buffer.WriteString(fmt.Sprintf("%s%s", folderIcon, separator))
+	}
+	for i := splitPos; i < depth; i++ {
+		buffer.WriteString(elements[i])
+		if i != depth-1 {
+			buffer.WriteString(separator)
+		}
 	}
 	return buffer.String()
 }
 
-func (pt *Path) getFullPath() string {
-	pwd := pt.getPwd()
-	return pt.replaceFolderSeparators(pwd)
+func (pt *Path) getFullPath(root, path string) string {
+	if root != pt.env.PathSeparator() {
+		root = root[:len(root)-1] + pt.getFolderSeparator()
+	}
+	path = pt.replaceFolderSeparators(path)
+	return root + path
 }
 
-func (pt *Path) getFolderPath() string {
-	pwd := pt.getPwd()
-	pwd = environment.Base(pt.env, pwd)
-	return pt.replaceFolderSeparators(pwd)
+func (pt *Path) getFolderPath(path string) string {
+	return environment.Base(pt.env, path)
+}
+
+func (pt *Path) setPwd() {
+	if len(pt.pwd) > 0 {
+		return
+	}
+	if pt.env.Shell() == shell.PWSH || pt.env.Shell() == shell.PWSH5 {
+		pt.pwd = pt.env.Flags().PSWD
+	}
+	if len(pt.pwd) == 0 {
+		pt.pwd = pt.env.Pwd()
+		return
+	}
+	// ensure a clean path
+	root, path := environment.ParsePath(pt.env, pt.pwd)
+	pt.pwd = root + path
 }
 
 func (pt *Path) getPwd() string {
-	pwd := pt.env.Flags().PSWD
-	if pwd == "" {
-		pwd = pt.env.Pwd()
+	pt.setPwd()
+	return pt.replaceMappedLocations(pt.pwd)
+}
+
+func (pt *Path) formatRoot(root string) string {
+	n := len(root)
+	// trim the trailing separator first
+	root = root[:n-1]
+	// only preserve the trailing separator for a Unix/Windows/PSDrive root
+	if len(root) == 0 || (strings.HasPrefix(pt.pwd, root) && strings.HasSuffix(root, ":")) {
+		return root + pt.env.PathSeparator()
 	}
-	pwd = pt.replaceMappedLocations(pwd)
-	return pwd
+	return root
 }
 
 func (pt *Path) normalize(inputPath string) string {
 	normalized := inputPath
-	if strings.HasPrefix(inputPath, "~") {
+	if strings.HasPrefix(normalized, "~") && (len(normalized) == 1 || environment.IsPathSeparator(pt.env, normalized[1])) {
 		normalized = pt.env.Home() + normalized[1:]
 	}
-	normalized = strings.ReplaceAll(normalized, "\\", "/")
-	goos := pt.env.GOOS()
-	if goos == environment.WINDOWS || goos == environment.DARWIN {
+	switch pt.env.GOOS() {
+	case environment.WINDOWS:
+		normalized = strings.ReplaceAll(normalized, "/", `\`)
+		fallthrough
+	case environment.DARWIN:
 		normalized = strings.ToLower(normalized)
 	}
-	if !strings.HasSuffix(normalized, "/") {
-		normalized += "/"
-	}
 	return normalized
 }
 
 func (pt *Path) replaceMappedLocations(pwd string) string {
-	if strings.HasPrefix(pwd, "Microsoft.PowerShell.Core\\FileSystem::") {
-		pwd = strings.Replace(pwd, "Microsoft.PowerShell.Core\\FileSystem::", "", 1)
-	}
-
 	mappedLocations := map[string]string{}
+	// predefined mapped locations, can be disabled
 	if pt.props.GetBool(MappedLocationsEnabled, true) {
-		mappedLocations[pt.normalize("hkcu:")] = pt.props.GetString(WindowsRegistryIcon, "\uF013")
-		mappedLocations[pt.normalize("hklm:")] = pt.props.GetString(WindowsRegistryIcon, "\uF013")
+		mappedLocations["hkcu:"] = pt.props.GetString(WindowsRegistryIcon, "\uF013")
+		mappedLocations["hklm:"] = pt.props.GetString(WindowsRegistryIcon, "\uF013")
 		mappedLocations[pt.normalize(pt.env.Home())] = pt.props.GetString(HomeIcon, "~")
 	}
 
@@ -369,37 +403,48 @@ func (pt *Path) replaceMappedLocations(pwd string) string {
 	// mapped locations can override predefined locations
 	keyValues := pt.props.GetKeyValueMap(MappedLocations, make(map[string]string))
 	for key, val := range keyValues {
-		mappedLocations[pt.normalize(key)] = val
+		if key != "" {
+			mappedLocations[pt.normalize(key)] = val
+		}
 	}
 
 	// sort map keys in reverse order
 	// fixes case when a subfoder and its parent are mapped
 	// ex /users/test and /users/test/dev
-	keys := make([]string, len(mappedLocations))
-	i := 0
+	keys := make([]string, 0, len(mappedLocations))
 	for k := range mappedLocations {
-		keys[i] = k
-		i++
+		keys = append(keys, k)
 	}
 	sort.Sort(sort.Reverse(sort.StringSlice(keys)))
 
-	normalizedPwd := pt.normalize(pwd)
+	cleanPwdRoot, cleanPwdPath := environment.ParsePath(pt.env, pwd)
+	pwdRoot := pt.normalize(cleanPwdRoot)
+	pwdPath := pt.normalize(cleanPwdPath)
 	for _, key := range keys {
-		if strings.HasPrefix(normalizedPwd, key) {
-			replacement := mappedLocations[key]
-			// -1 as we want to ignore the trailing slash
-			// set by the normalize function
-			return replacement + pwd[len(key)-1:]
+		keyRoot, keyPath := environment.ParsePath(pt.env, key)
+		if keyRoot != pwdRoot || !strings.HasPrefix(pwdPath, keyPath) {
+			continue
+		}
+		value := mappedLocations[key]
+		rem := cleanPwdPath[len(keyPath):]
+		if len(rem) == 0 {
+			// exactly match the full path
+			return value
+		}
+		if len(keyPath) == 0 {
+			// only match the root
+			return value + pt.env.PathSeparator() + cleanPwdPath
+		}
+		// match several prefix elements
+		if rem[0:1] == pt.env.PathSeparator() {
+			return value + rem
 		}
 	}
-	return pwd
+	return cleanPwdRoot + cleanPwdPath
 }
 
 func (pt *Path) replaceFolderSeparators(pwd string) string {
 	defaultSeparator := pt.env.PathSeparator()
-	if pwd == defaultSeparator {
-		return pwd
-	}
 	folderSeparator := pt.getFolderSeparator()
 	if folderSeparator == defaultSeparator {
 		return pwd
@@ -408,22 +453,3 @@ func (pt *Path) replaceFolderSeparators(pwd string) string {
 	pwd = strings.ReplaceAll(pwd, defaultSeparator, folderSeparator)
 	return pwd
 }
-
-func (pt *Path) rootLocation() string {
-	pwd := pt.getPwd()
-	pwd = strings.TrimPrefix(pwd, pt.env.PathSeparator())
-	splitted := strings.Split(pwd, pt.env.PathSeparator())
-	rootLocation := splitted[0]
-	return rootLocation
-}
-
-func (pt *Path) pathDepth(pwd string) int {
-	splitted := strings.Split(pwd, pt.env.PathSeparator())
-	depth := 0
-	for _, part := range splitted {
-		if part != "" {
-			depth++
-		}
-	}
-	return depth - 1
-}
diff --git a/src/shell/scripts/omp.ps1 b/src/shell/scripts/omp.ps1
index 8069771d..335fb6c2 100644
--- a/src/shell/scripts/omp.ps1
+++ b/src/shell/scripts/omp.ps1
@@ -100,22 +100,22 @@ New-Module -Name "oh-my-posh-core" -ScriptBlock {
 
     function Set-PoshContext {}
 
-    function Get-PoshContext {
-        $cleanPWD = $PWD.ProviderPath
-        $cleanPSWD = $PWD.ToString()
-        $cleanPWD = $cleanPWD.TrimEnd('\')
-        $cleanPSWD = $cleanPSWD.TrimEnd('\')
-        return $cleanPWD, $cleanPSWD
+    function Get-CleanPSWD {
+        $pswd = $PWD.ToString()
+        if ($pswd -ne '/') {
+            return $pswd.TrimEnd('\') -replace '^Microsoft\.PowerShell\.Core\\FileSystem::', ''
+        }
+        return $pswd
     }
 
     if (("::TOOLTIPS::" -eq "true") -and ($ExecutionContext.SessionState.LanguageMode -ne "ConstrainedLanguage")) {
         Set-PSReadLineKeyHandler -Key Spacebar -BriefDescription 'OhMyPoshSpaceKeyHandler' -ScriptBlock {
             [Microsoft.PowerShell.PSConsoleReadLine]::Insert(' ')
             $position = $host.UI.RawUI.CursorPosition
-            $cleanPWD, $cleanPSWD = Get-PoshContext
+            $cleanPSWD = Get-CleanPSWD
             $command = $null
             [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$command, [ref]$null)
-            $standardOut = @(Start-Utf8Process $script:OMPExecutable @("print", "tooltip", "--error=$script:ErrorCode", "--pwd=$cleanPWD", "--shell=$script:ShellName", "--pswd=$cleanPSWD", "--config=$env:POSH_THEME", "--command=$command", "--shell-version=$script:PSVersion"))
+            $standardOut = @(Start-Utf8Process $script:OMPExecutable @("print", "tooltip", "--error=$script:ErrorCode", "--shell=$script:ShellName", "--pswd=$cleanPSWD", "--config=$env:POSH_THEME", "--command=$command", "--shell-version=$script:PSVersion"))
             Write-Host $standardOut -NoNewline
             $host.UI.RawUI.CursorPosition = $position
             # we need this workaround to prevent the text after cursor from disappearing when the tooltip is rendered
@@ -259,9 +259,10 @@ New-Module -Name "oh-my-posh-core" -ScriptBlock {
         if ($List -eq $true) {
             $themes | Select-Object @{ Name = 'hyperlink'; Expression = { Get-FileHyperlink -uri $_.FullName } } | Format-Table -HideTableHeaders
         } else {
+            $cleanPSWD = Get-CleanPSWD
             $themes | ForEach-Object -Process {
                 Write-Host "Theme: $(Get-FileHyperlink -uri $_.FullName -Name ($_.BaseName -replace '\.omp$', ''))`n"
-                @(Start-Utf8Process $script:OMPExecutable @("print", "primary", "--config=$($_.FullName)", "--pwd=$PWD", "--shell=$script:ShellName"))
+                @(Start-Utf8Process $script:OMPExecutable @("print", "primary", "--config=$($_.FullName)", "--pswd=$cleanPSWD", "--shell=$script:ShellName"))
                 Write-Host "`n"
             }
         }
@@ -331,7 +332,7 @@ Example:
         if ($script:PromptType -ne 'transient') {
             Update-PoshErrorCode
         }
-        $cleanPWD, $cleanPSWD = Get-PoshContext
+        $cleanPSWD = Get-CleanPSWD
         $stackCount = global:Get-PoshStackCount
         Set-PoshContext
         $terminalWidth = $Host.UI.RawUI.WindowSize.Width
@@ -339,7 +340,7 @@ Example:
         if (-not $terminalWidth) {
             $terminalWidth = 0
         }
-        $standardOut = @(Start-Utf8Process $script:OMPExecutable @("print", $script:PromptType, "--error=$script:ErrorCode", "--pwd=$cleanPWD", "--pswd=$cleanPSWD", "--execution-time=$script:ExecutionTime", "--stack-count=$stackCount", "--config=$env:POSH_THEME", "--shell-version=$script:PSVersion", "--terminal-width=$terminalWidth", "--shell=$script:ShellName"))
+        $standardOut = @(Start-Utf8Process $script:OMPExecutable @("print", $script:PromptType, "--error=$script:ErrorCode", "--pswd=$cleanPSWD", "--execution-time=$script:ExecutionTime", "--stack-count=$stackCount", "--config=$env:POSH_THEME", "--shell-version=$script:PSVersion", "--terminal-width=$terminalWidth", "--shell=$script:ShellName"))
         # make sure PSReadLine knows if we have a multiline prompt
         Set-PSReadLineOption -ExtraPromptLineCount (($standardOut | Measure-Object -Line).Lines - 1)
         # the output can be multiline, joining these ensures proper rendering by adding line breaks with `n
diff --git a/website/docs/segments/path.mdx b/website/docs/segments/path.mdx
index 821327d6..d727188b 100644
--- a/website/docs/segments/path.mdx
+++ b/website/docs/segments/path.mdx
@@ -42,9 +42,9 @@ Display the current path.
 
 ## Mapped Locations
 
-Allows you to override a location with an icon. It validates if the current path **starts with** the value and replaces
-it with the icon if there's a match. To avoid issues with nested overrides, Oh My Posh will sort the list of mapped
-locations before doing a replacement.
+Allows you to override a location with an icon/string.
+It validates if the current path **starts with the specific elements** and replaces it with the icon/string if there's a match.
+To avoid issues with nested overrides, Oh My Posh will sort the list of mapped locations before doing a replacement.
 
 | Name                       | Type      | Description                                                                                              |
 | -------------------------- | --------- | -------------------------------------------------------------------------------------------------------- |
@@ -63,8 +63,8 @@ For example, to swap out `C:\Users\Leet\GitHub` with a GitHub icon, you can do t
 
 ### Notes
 
-- Oh My Posh will accept both `/` and `\` as path separators for a mapped location and will match regardless of which
-  is used by the current operating system.
+- To make mapped Locations work cross-platform, you should use `/` as the path separator, Oh My Posh will
+automatically match effective separators based on the running operating system.
 - The character `~` at the start of a mapped location will match the user's home directory.
 - The match is case-insensitive on Windows and macOS, but case-sensitive on other operating systems.
 
@@ -87,8 +87,8 @@ Style sets the way the path is displayed. Based on previous experience and popul
 
 ### Agnoster
 
-Renders each folder as the `folder_icon` separated by the `folder_separator_icon`.
-Only the current folder name is displayed at the end.
+Renders each intermediate folder as the `folder_icon` separated by the `folder_separator_icon`.
+The first and the last (current) folder name are always displayed as-is.
 
 ### Agnoster Full
 
@@ -96,17 +96,18 @@ Renders each folder name separated by the `folder_separator_icon`.
 
 ### Agnoster Short
 
-When more than `max_depth` levels deep, it renders one `folder_icon` (if `hide_root_location` is `false`) followed by
-the names of the last `max_depth` folders, separated by the `folder_separator_icon`.
+When more than `max_depth` levels deep, it renders one `folder_icon` (if `hide_root_location` is `false`,
+which means the root folder does not count for depth) followed by the names of the last `max_depth` folders,
+separated by the `folder_separator_icon`.
 
 ### Agnoster Left
 
 Renders each folder as the `folder_icon` separated by the `folder_separator_icon`.
-Only the root folder name and it's child are displayed in full.
+Only the first folder name and its child are displayed in full.
 
 ### Full
 
-Display `$PWD` as a string.
+Display the current working directory as a full string with each folder separated by the `folder_separator_icon`.
 
 ### Folder
 
@@ -114,13 +115,13 @@ Display the name of the current folder.
 
 ### Mixed
 
-Works like `Agnoster Full`, but for any middle folder short enough it will display its name instead. The maximum length
-for the folders to display is governed by the `mixed_threshold` property.
+Works like `Agnoster`, but for any intermediate folder name that is short enough, it will be displayed as-is.
+The maximum length for the folders to display is governed by the `mixed_threshold` property.
 
 ### Letter
 
-Works like `Full`, but will write every subfolder name using the first letter only, except when the folder name
-starts with a symbol or icon.
+Works like `Agnoster Full`, but will write every folder name using the first letter only, except when the folder name
+starts with a symbol or icon. Specially, the last (current) folder name is always displayed in full.
 
 - `folder` will be shortened to `f`
 - `.config` will be shortened to `.c`
@@ -132,9 +133,9 @@ starts with a symbol or icon.
 Works like `Letter`, but will make sure every folder name is the shortest unique value.
 
 The uniqueness refers to the displayed path, so `C:\dev\dev\dev\development` will be displayed as
-`C:\d\de\dev\development` (instead of `C:\d\d\d\development` for `Letter`). Uniqueness does _not_ refer to other
+`C\d\de\dev\development` (instead of `C\d\d\d\development` for `Letter`). Uniqueness does **not** refer to other
 folders at the same level, so if `C:\projectA\dev` and `C:\projectB\dev` exist, then both will be displayed as
-`C:\p\dev`.
+`C\p\dev`.
 
 ## Template ([info][templates])
 
@@ -148,12 +149,12 @@ folders at the same level, so if `C:\projectA\dev` and `C:\projectB\dev` exist,
 
 ### Properties
 
-| Name          | Type      | Description                                                                  |
+| Name          | Type      | Description                                                                                                                                                            |
 | ------------- | --------- | ---------------------------------------------------------------------------- |
-| `.Path`       | `string`  | the current directory (based on the `style` property)                        |
-| `.Parent`     | `string`  | the current directory's parent folder (designed for use with style `folder`) |
-| `.Location`   | `string`  | the current directory (raw value)                                            |
-| `.StackCount` | `int`     | the stack count                                                              |
-| `.Writable`   | `boolean` | is the current directory writable by the user or not                         |
+| `.Path`       | `string`  | the current directory (based on the `style` property)                                                                                                                  |
+| `.Parent`     | `string`  | the current directory's parent folder which ends with a path separator (designed for use with style `folder`, it is empty if `.Path` contains only one single element) |
+| `.Location`   | `string`  | the current directory (raw value)                                                                                                                                      |
+| `.StackCount` | `int`     | the stack count                                                                                                                                                        |
+| `.Writable`   | `boolean` | is the current directory writable by the user or not                                                                                                                   |
 
 [templates]: /docs/configuration/templates


Test patch:
diff --git a/src/environment/shell_test.go b/src/environment/shell_test.go
index 5653ece8..36432296 100644
--- a/src/environment/shell_test.go
+++ b/src/environment/shell_test.go
@@ -22,29 +22,6 @@ func TestHostNameWithLan(t *testing.T) {
 	assert.Equal(t, "hello", cleanHostName)
 }
 
-func TestWindowsPathWithDriveLetter(t *testing.T) {
-	cases := []struct {
-		Case     string
-		CWD      string
-		Expected string
-	}{
-		{Case: "C drive", CWD: `C:\Windows\`, Expected: `C:\Windows\`},
-		{Case: "C drive lower case", CWD: `c:\Windows\`, Expected: `C:\Windows\`},
-		{Case: "P drive lower case", CWD: `p:\some\`, Expected: `P:\some\`},
-		{Case: "some drive lower case", CWD: `some:\some\`, Expected: `some:\some\`},
-		{Case: "drive ending in c:", CWD: `src:\source\`, Expected: `src:\source\`},
-		{Case: "registry drive", CWD: `HKLM:\SOFTWARE\magnetic:test\`, Expected: `HKLM:\SOFTWARE\magnetic:test\`},
-	}
-	for _, tc := range cases {
-		env := &ShellEnvironment{
-			CmdFlags: &Flags{
-				PWD: tc.CWD,
-			},
-		}
-		assert.Equal(t, env.Pwd(), tc.Expected)
-	}
-}
-
 func TestDirMatchesOneOf(t *testing.T) {
 	cases := []struct {
 		GOOS     string
diff --git a/src/segments/path_test.go b/src/segments/path_test.go
index 78b0921d..89a060eb 100644
--- a/src/segments/path_test.go
+++ b/src/segments/path_test.go
@@ -4,8 +4,8 @@ import (
 	"oh-my-posh/environment"
 	"oh-my-posh/mock"
 	"oh-my-posh/properties"
+	"oh-my-posh/shell"
 	"oh-my-posh/template"
-	"runtime"
 	"strings"
 	"testing"
 
@@ -40,127 +40,117 @@ func renderTemplate(env *mock.MockedEnvironment, segmentTemplate string, context
 }
 
 const (
-	homeJan         = "/usr/home/jan"
-	homeBillWindows = "C:\\Users\\Bill"
-	levelDir        = "/level"
+	homeDir        = "/home/someone"
+	homeDirWindows = "C:\\Users\\someone"
 )
 
-func TestRootLocationHome(t *testing.T) {
+func TestParent(t *testing.T) {
 	cases := []struct {
-		Expected      string
-		HomePath      string
-		Pswd          string
-		Pwd           string
-		GOOS          string
-		PathSeparator string
-		HomeIcon      string
-		RegistryIcon  string
+		Case                string
+		Expected            string
+		HomePath            string
+		Pwd                 string
+		GOOS                string
+		PathSeparator       string
+		FolderSeparatorIcon string
 	}{
-		{Expected: "REG", RegistryIcon: "REG", HomePath: "C:\\Users\\Bill", Pwd: "HKCU:\\Program Files\\Go", GOOS: environment.WINDOWS, PathSeparator: "\\"},
-		{Expected: "~", HomeIcon: "~", HomePath: "/home/bill/", Pwd: "/home/bill/", PathSeparator: "/"},
-		{Expected: "usr", HomePath: "/home/bill/", Pwd: "/usr/error/what", PathSeparator: "/"},
-		{Expected: "C:", HomePath: "C:\\Users\\Bill", Pwd: "C:\\Program Files\\Go", GOOS: environment.WINDOWS, PathSeparator: "\\"},
-		{Expected: "~", HomeIcon: "~", HomePath: "C:\\Users\\Bill", Pwd: "Microsoft.PowerShell.Core\\FileSystem::C:\\Users\\Bill", GOOS: environment.WINDOWS, PathSeparator: "\\"},
-		{Expected: "C:", HomePath: "C:\\Users\\Jack", Pwd: "Microsoft.PowerShell.Core\\FileSystem::C:\\Users\\Bill", GOOS: environment.WINDOWS, PathSeparator: "\\"},
-		{Expected: "", HomePath: "C:\\Users\\Jack", Pwd: "", GOOS: environment.WINDOWS, PathSeparator: "\\"},
-		{Expected: "DRIVE:", HomePath: "/home/bill/", Pwd: "/usr/error/what", Pswd: "DRIVE:", PathSeparator: "/"},
+		{
+			Case:          "Home folder",
+			HomePath:      homeDir,
+			Pwd:           homeDir,
+			GOOS:          environment.DARWIN,
+			PathSeparator: "/",
+		},
+		{
+			Case:          "Home folder with a trailing separator",
+			HomePath:      homeDir,
+			Pwd:           homeDir + "/",
+			GOOS:          environment.DARWIN,
+			PathSeparator: "/",
+		},
+		{
+			Case:          "Inside Home folder",
+			Expected:      "~/",
+			HomePath:      homeDir,
+			Pwd:           homeDir + "/test",
+			GOOS:          environment.DARWIN,
+			PathSeparator: "/",
+		},
+		{
+			Case:          "Root",
+			HomePath:      homeDir,
+			Pwd:           "/",
+			GOOS:          environment.DARWIN,
+			PathSeparator: "/",
+		},
+		{
+			Case:          "Root + 1",
+			Expected:      "/",
+			HomePath:      homeDir,
+			Pwd:           "/usr",
+			GOOS:          environment.DARWIN,
+			PathSeparator: "/",
+		},
+		{
+			Case:          "Windows Home folder",
+			HomePath:      homeDirWindows,
+			Pwd:           homeDirWindows,
+			GOOS:          environment.WINDOWS,
+			PathSeparator: "\\",
+		},
+		{
+			Case:          "Windows drive root",
+			HomePath:      homeDirWindows,
+			Pwd:           "C:",
+			GOOS:          environment.WINDOWS,
+			PathSeparator: "\\",
+		},
+		{
+			Case:          "Windows drive root with a trailing separator",
+			HomePath:      homeDirWindows,
+			Pwd:           "C:\\",
+			GOOS:          environment.WINDOWS,
+			PathSeparator: "\\",
+		},
+		{
+			Case:          "Windows drive root + 1",
+			Expected:      "C:\\",
+			HomePath:      homeDirWindows,
+			Pwd:           "C:\\test",
+			GOOS:          environment.WINDOWS,
+			PathSeparator: "\\",
+		},
+		{
+			Case:          "PSDrive root",
+			HomePath:      homeDirWindows,
+			Pwd:           "HKLM:",
+			GOOS:          environment.WINDOWS,
+			PathSeparator: "\\",
+		},
 	}
 	for _, tc := range cases {
 		env := new(mock.MockedEnvironment)
 		env.On("Home").Return(tc.HomePath)
 		env.On("Pwd").Return(tc.Pwd)
-		args := &environment.Flags{
-			PSWD: tc.Pswd,
-		}
-		env.On("Flags").Return(args)
+		env.On("Flags").Return(&environment.Flags{})
+		env.On("Shell").Return(shell.PLAIN)
 		env.On("PathSeparator").Return(tc.PathSeparator)
 		env.On("GOOS").Return(tc.GOOS)
 		path := &Path{
 			env: env,
 			props: properties.Map{
-				HomeIcon:            tc.HomeIcon,
-				WindowsRegistryIcon: tc.RegistryIcon,
+				FolderSeparatorIcon: tc.FolderSeparatorIcon,
 			},
 		}
-		got := path.rootLocation()
-		assert.EqualValues(t, tc.Expected, got)
-	}
-}
-
-func TestParent(t *testing.T) {
-	// there's no Windows support/validation for this just yet
-	// mainly due to root being a special case
-	if runtime.GOOS == environment.WINDOWS {
-		return
-	}
-	cases := []struct {
-		Case          string
-		Expected      string
-		HomePath      string
-		Pwd           string
-		PathSeparator string
-	}{
-		{Case: "Home folder", Expected: "", HomePath: "/home/bill", Pwd: "/home/bill", PathSeparator: "/"},
-		{Case: "Inside home folder", Expected: "~/", HomePath: "/home/bill", Pwd: "/home/bill/test", PathSeparator: "/"},
-		{Case: "Root", Expected: "", HomePath: "/home/bill", Pwd: "/", PathSeparator: "/"},
-		{Case: "Root + 1", Expected: "/", HomePath: "/home/bill", Pwd: "/usr", PathSeparator: "/"},
-	}
-	for _, tc := range cases {
-		env := new(mock.MockedEnvironment)
-		env.On("Home").Return(tc.HomePath)
-		env.On("Pwd").Return(tc.Pwd)
-		env.On("Flags").Return(&environment.Flags{})
-		env.On("PathSeparator").Return(tc.PathSeparator)
-		env.On("GOOS").Return(environment.DARWIN)
-		path := &Path{
-			env:   env,
-			props: properties.Map{},
-		}
 		path.pwd = tc.Pwd
 		got := path.Parent()
 		assert.EqualValues(t, tc.Expected, got, tc.Case)
 	}
 }
 
-func TestPathDepthMultipleLevelsDeep(t *testing.T) {
-	pwd := "/usr"
-	for i := 0; i < 99; i++ {
-		pwd += levelDir
-	}
-	env := new(mock.MockedEnvironment)
-	env.On("PathSeparator").Return("/")
-	env.On("getRunteGOOS").Return("")
-	path := &Path{
-		env: env,
-	}
-	got := path.pathDepth(pwd)
-	assert.Equal(t, 99, got)
-}
-
-func TestPathDepthZeroLevelsDeep(t *testing.T) {
-	pwd := "/usr/"
-	env := new(mock.MockedEnvironment)
-	env.On("PathSeparator").Return("/")
-	path := &Path{
-		env: env,
-	}
-	got := path.pathDepth(pwd)
-	assert.Equal(t, 0, got)
-}
-
-func TestPathDepthOneLevelDeep(t *testing.T) {
-	pwd := "/usr/location"
-	env := new(mock.MockedEnvironment)
-	env.On("PathSeparator").Return("/")
-	path := &Path{
-		env: env,
-	}
-	got := path.pathDepth(pwd)
-	assert.Equal(t, 1, got)
-}
-
 func TestAgnosterPathStyles(t *testing.T) {
 	cases := []struct {
+		Style               string
 		Expected            string
 		HomePath            string
 		Pswd                string
@@ -168,29 +158,225 @@ func TestAgnosterPathStyles(t *testing.T) {
 		PathSeparator       string
 		HomeIcon            string
 		FolderSeparatorIcon string
-		Style               string
 		GOOS                string
 		MaxDepth            int
 		HideRootLocation    bool
 	}{
-		{Style: AgnosterFull, Expected: "usr > location > whatever", HomePath: "/usr/home", Pwd: "/usr/location/whatever", PathSeparator: "/", FolderSeparatorIcon: " > "},
-		{Style: AgnosterShort, Expected: "usr > .. > man", HomePath: "/usr/home", Pwd: "/usr/location/whatever/man", PathSeparator: "/", FolderSeparatorIcon: " > "},
-		{Style: AgnosterShort, Expected: "~ > .. > man", HomePath: "/usr/home", Pwd: "/usr/home/whatever/man", PathSeparator: "/", FolderSeparatorIcon: " > "},
-		{Style: AgnosterShort, Expected: "~ > projects", HomePath: "/usr/home", Pwd: "/usr/home/projects", PathSeparator: "/", FolderSeparatorIcon: " > "},
-		{Style: AgnosterShort, Expected: "C:", HomePath: homeBillWindows, Pwd: "C:", PathSeparator: "\\", FolderSeparatorIcon: " > "},
-		{Style: AgnosterShort, Expected: "/", HomePath: homeBillWindows, Pwd: "/", PathSeparator: "/", FolderSeparatorIcon: " > "},
-		{Style: AgnosterShort, Expected: "foo", HomePath: homeBillWindows, Pwd: "/foo", PathSeparator: "/", FolderSeparatorIcon: " > "},
-
-		{Style: AgnosterShort, Expected: "usr > .. > bar > man", HomePath: "/usr/home", Pwd: "/usr/foo/bar/man", PathSeparator: "/", FolderSeparatorIcon: " > ", MaxDepth: 2},
-		{Style: AgnosterShort, Expected: "usr > foo > bar > man", HomePath: "/usr/home", Pwd: "/usr/foo/bar/man", PathSeparator: "/", FolderSeparatorIcon: " > ", MaxDepth: 3},
-		{Style: AgnosterShort, Expected: "~ > .. > bar > man", HomePath: "/usr/home", Pwd: "/usr/home/foo/bar/man", PathSeparator: "/", FolderSeparatorIcon: " > ", MaxDepth: 2},
-		{Style: AgnosterShort, Expected: "~ > foo > bar > man", HomePath: "/usr/home", Pwd: "/usr/home/foo/bar/man", PathSeparator: "/", FolderSeparatorIcon: " > ", MaxDepth: 3},
+		{
+			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:            "usr > .. > man",
+			HomePath:            homeDir,
+			Pwd:                 "/usr/location/whatever/man",
+			PathSeparator:       "/",
+			FolderSeparatorIcon: " > ",
+		},
+		{
+			Style:               AgnosterShort,
+			Expected:            "~ > .. > man",
+			HomePath:            homeDir,
+			Pwd:                 homeDir + "/whatever/man",
+			PathSeparator:       "/",
+			FolderSeparatorIcon: " > ",
+		},
+		{
+			Style:               AgnosterShort,
+			Expected:            "~ > projects",
+			HomePath:            homeDir,
+			Pwd:                 homeDir + "/projects",
+			PathSeparator:       "/",
+			FolderSeparatorIcon: " > ",
+		},
+		{
+			Style:               AgnosterShort,
+			Expected:            "usr > .. > bar > man",
+			HomePath:            homeDir,
+			Pwd:                 "/usr/foo/bar/man",
+			PathSeparator:       "/",
+			FolderSeparatorIcon: " > ",
+			MaxDepth:            2,
+		},
+		{
+			Style:               AgnosterShort,
+			Expected:            "usr > foo > bar > man",
+			HomePath:            homeDir,
+			Pwd:                 "/usr/foo/bar/man",
+			PathSeparator:       "/",
+			FolderSeparatorIcon: " > ",
+			MaxDepth:            3,
+		},
+		{
+			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:            "src | init",
+			HomePath:            homeDir,
+			Pwd:                 "/foo",
+			Pswd:                "PSDRIVE:/src/init",
+			PathSeparator:       "/",
+			FolderSeparatorIcon: " | ",
+			MaxDepth:            2,
+			HideRootLocation:    true,
+		},
+		{
+			Style:               AgnosterShort,
+			Expected:            "PSDRIVE: | src",
+			HomePath:            homeDir,
+			Pwd:                 "/foo",
+			Pswd:                "PSDRIVE:/src",
+			PathSeparator:       "/",
+			FolderSeparatorIcon: " | ",
+			MaxDepth:            2,
+			HideRootLocation:    true,
+		},
+		{
+			Style:               AgnosterShort,
+			Expected:            "~",
+			HomePath:            homeDir,
+			Pwd:                 homeDir,
+			PathSeparator:       "/",
+			FolderSeparatorIcon: " > ",
+			MaxDepth:            1,
+			HideRootLocation:    true,
+		},
+		{
+			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:                environment.WINDOWS,
+			PathSeparator:       "\\",
+			FolderSeparatorIcon: " > ",
+		},
 		{
 			Style:               AgnosterShort,
 			Expected:            "C: > .. > bar > man",
-			HomePath:            homeBillWindows,
+			HomePath:            homeDirWindows,
 			Pwd:                 "C:\\usr\\foo\\bar\\man",
+			GOOS:                environment.WINDOWS,
 			PathSeparator:       "\\",
 			FolderSeparatorIcon: " > ",
 			MaxDepth:            2,
@@ -198,8 +384,9 @@ func TestAgnosterPathStyles(t *testing.T) {
 		{
 			Style:               AgnosterShort,
 			Expected:            "C: > .. > foo > bar > man",
-			HomePath:            homeBillWindows,
+			HomePath:            homeDirWindows,
 			Pwd:                 "C:\\usr\\foo\\bar\\man",
+			GOOS:                environment.WINDOWS,
 			PathSeparator:       "\\",
 			FolderSeparatorIcon: " > ",
 			MaxDepth:            3,
@@ -207,8 +394,9 @@ func TestAgnosterPathStyles(t *testing.T) {
 		{
 			Style:               AgnosterShort,
 			Expected:            "~ > .. > bar > man",
-			HomePath:            homeBillWindows,
-			Pwd:                 "C:\\Users\\Bill\\foo\\bar\\man",
+			HomePath:            homeDirWindows,
+			Pwd:                 homeDirWindows + "\\foo\\bar\\man",
+			GOOS:                environment.WINDOWS,
 			PathSeparator:       "\\",
 			FolderSeparatorIcon: " > ",
 			MaxDepth:            2,
@@ -216,61 +404,275 @@ func TestAgnosterPathStyles(t *testing.T) {
 		{
 			Style:               AgnosterShort,
 			Expected:            "~ > foo > bar > man",
-			HomePath:            homeBillWindows,
-			Pwd:                 "C:\\Users\\Bill\\foo\\bar\\man",
+			HomePath:            homeDirWindows,
+			Pwd:                 homeDirWindows + "\\foo\\bar\\man",
+			GOOS:                environment.WINDOWS,
 			PathSeparator:       "\\",
 			FolderSeparatorIcon: " > ",
 			MaxDepth:            3,
 		},
+		{
+			Style:               AgnosterShort,
+			Expected:            "~",
+			HomePath:            homeDirWindows,
+			Pwd:                 homeDirWindows,
+			GOOS:                environment.WINDOWS,
+			PathSeparator:       "\\",
+			FolderSeparatorIcon: " > ",
+			MaxDepth:            1,
+			HideRootLocation:    true,
+		},
+		{
+			Style:               AgnosterShort,
+			Expected:            "foo",
+			HomePath:            homeDirWindows,
+			Pwd:                 homeDirWindows + "\\foo",
+			GOOS:                environment.WINDOWS,
+			PathSeparator:       "\\",
+			FolderSeparatorIcon: " > ",
+			MaxDepth:            1,
+			HideRootLocation:    true,
+		},
+		{
+			Style:               AgnosterShort,
+			Expected:            "~ > foo",
+			HomePath:            homeDirWindows,
+			Pwd:                 homeDirWindows + "\\foo",
+			GOOS:                environment.WINDOWS,
+			PathSeparator:       "\\",
+			FolderSeparatorIcon: " > ",
+			MaxDepth:            2,
+			HideRootLocation:    true,
+		},
+		{
+			Style:               AgnosterShort,
+			Expected:            ".. > bar > man",
+			HomePath:            homeDirWindows,
+			Pwd:                 homeDirWindows + "\\foo\\bar\\man",
+			GOOS:                environment.WINDOWS,
+			PathSeparator:       "\\",
+			FolderSeparatorIcon: " > ",
+			MaxDepth:            2,
+			HideRootLocation:    true,
+		},
+		{
+			Style:               AgnosterShort,
+			Expected:            "\\\\localhost\\c$",
+			HomePath:            homeDirWindows,
+			Pwd:                 "\\\\localhost\\c$",
+			GOOS:                environment.WINDOWS,
+			PathSeparator:       "\\",
+			FolderSeparatorIcon: " > ",
+		},
+		{
+			Style:               AgnosterShort,
+			Expected:            "\\\\localhost\\c$ > some",
+			HomePath:            homeDirWindows,
+			Pwd:                 "\\\\localhost\\c$\\some",
+			GOOS:                environment.WINDOWS,
+			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:                environment.WINDOWS,
+			PathSeparator:       "\\",
+			FolderSeparatorIcon: " > ",
+		},
 
-		{Style: AgnosterFull, Expected: "PSDRIVE: | src", HomePath: homeBillWindows, Pwd: "/foo", Pswd: "PSDRIVE:/src", PathSeparator: "/", FolderSeparatorIcon: " | "},
-		{Style: AgnosterShort, Expected: "PSDRIVE: | .. | init", HomePath: homeBillWindows, Pwd: "/foo", Pswd: "PSDRIVE:/src/init", PathSeparator: "/", FolderSeparatorIcon: " | "},
-
-		{Style: AgnosterShort, Expected: "src | init", HomePath: homeBillWindows, Pwd: "/foo", Pswd: "PSDRIVE:/src/init", PathSeparator: "/", FolderSeparatorIcon: " | ", MaxDepth: 2,
-			HideRootLocation: true},
-		{Style: AgnosterShort, Expected: "PSDRIVE: | src", HomePath: homeBillWindows, Pwd: "/foo", Pswd: "PSDRIVE:/src", PathSeparator: "/", FolderSeparatorIcon: " | ", MaxDepth: 2,
-			HideRootLocation: true},
-		{Style: AgnosterShort, Expected: "~", HomePath: homeBillWindows, Pwd: homeBillWindows, PathSeparator: "\\", FolderSeparatorIcon: " > ", MaxDepth: 1, HideRootLocation: true},
-		{Style: AgnosterShort, Expected: "foo", HomePath: homeBillWindows, Pwd: homeBillWindows + "\\foo", PathSeparator: "\\", FolderSeparatorIcon: "\\", MaxDepth: 1,
-			HideRootLocation: true},
-		{Style: AgnosterShort, Expected: "~\\foo", HomePath: homeBillWindows, Pwd: homeBillWindows + "\\foo", PathSeparator: "\\", FolderSeparatorIcon: "\\", MaxDepth: 2,
-			HideRootLocation: true},
-		{Style: AgnosterShort, Expected: "~", HomePath: "/usr/home", Pwd: "/usr/home", PathSeparator: "/", FolderSeparatorIcon: " > ", MaxDepth: 1, HideRootLocation: true},
-		{Style: AgnosterShort, Expected: "foo", HomePath: "/usr/home", Pwd: "/usr/home/foo", PathSeparator: "/", FolderSeparatorIcon: "/", MaxDepth: 1, HideRootLocation: true},
-		{Style: AgnosterShort, Expected: "bar > man", HomePath: "/usr/home", Pwd: "/usr/foo/bar/man", PathSeparator: "/", FolderSeparatorIcon: " > ", MaxDepth: 2,
-			HideRootLocation: true},
-		{Style: AgnosterShort, Expected: "foo > bar > man", HomePath: "/usr/home", Pwd: "/usr/foo/bar/man", PathSeparator: "/", FolderSeparatorIcon: " > ", MaxDepth: 3,
-			HideRootLocation: true},
-		{Style: AgnosterShort, Expected: "~ > foo", HomePath: "/usr/home", Pwd: "/usr/home/foo", PathSeparator: "/", FolderSeparatorIcon: " > ", MaxDepth: 2, HideRootLocation: true},
-		{Style: AgnosterShort, Expected: "~ > foo > bar > man", HomePath: "/usr/home", Pwd: "/usr/home/foo/bar/man", PathSeparator: "/", FolderSeparatorIcon: " > ", MaxDepth: 4,
-			HideRootLocation: true},
-		{Style: AgnosterShort, Expected: "C:", HomePath: "/usr/home", Pwd: "/mnt/c", Pswd: "C:", PathSeparator: "/", FolderSeparatorIcon: " | ", MaxDepth: 2, HideRootLocation: true},
-		{Style: AgnosterShort, Expected: "~ | space foo", HomePath: "/usr/home", Pwd: "/usr/home/space foo", PathSeparator: "/", FolderSeparatorIcon: " | ", MaxDepth: 2,
-			HideRootLocation: true},
-		{Style: AgnosterShort, Expected: "space foo", HomePath: "/usr/home", Pwd: "/usr/home/space foo", PathSeparator: "/", FolderSeparatorIcon: " | ", MaxDepth: 1,
-			HideRootLocation: true},
-
-		{Style: Mixed, Expected: "~ > .. > man", HomePath: "/usr/home", Pwd: "/usr/home/whatever/man", PathSeparator: "/", FolderSeparatorIcon: " > "},
-		{Style: Mixed, Expected: "~ > ab > .. > man", HomePath: "/usr/home", Pwd: "/usr/home/ab/whatever/man", PathSeparator: "/", FolderSeparatorIcon: " > "},
-
-		{Style: Letter, Expected: "~ > a > w > man", HomePath: "/usr/home", Pwd: "/usr/home/ab/whatever/man", PathSeparator: "/", FolderSeparatorIcon: " > "},
-		{Style: Letter, Expected: "u > b > a > w > man", HomePath: "/usr/home", Pwd: "/usr/burp/ab/whatever/man", PathSeparator: "/", FolderSeparatorIcon: " > "},
-		{Style: Letter, Expected: "u > .b > a > w > man", HomePath: "/usr/home", Pwd: "/usr/.burp/ab/whatever/man", PathSeparator: "/", FolderSeparatorIcon: " > "},
-		{Style: Letter, Expected: "u > .b > a > .w > man", HomePath: "/usr/home", Pwd: "/usr/.burp/ab/.whatever/man", PathSeparator: "/", FolderSeparatorIcon: " > "},
-		{Style: Letter, Expected: "u > .b > a > ._w > man", HomePath: "/usr/home", Pwd: "/usr/.burp/ab/._whatever/man", PathSeparator: "/", FolderSeparatorIcon: " > "},
-		{Style: Letter, Expected: "u > .ä > ū > .w > man", HomePath: "/usr/home", Pwd: "/usr/.äufbau/ūmgebung/.whatever/man", PathSeparator: "/", FolderSeparatorIcon: " > "},
-		{Style: Letter, Expected: "u > .b > 1 > .w > man", HomePath: "/usr/home", Pwd: "/usr/.burp/12345/.whatever/man", PathSeparator: "/", FolderSeparatorIcon: " > "},
-		{Style: Letter, Expected: "u > .b > 1 > .w > man", HomePath: "/usr/home", Pwd: "/usr/.burp/12345abc/.whatever/man", PathSeparator: "/", FolderSeparatorIcon: " > "},
-		{Style: Letter, Expected: "u > .b > __p > .w > man", HomePath: "/usr/home", Pwd: "/usr/.burp/__pycache__/.whatever/man", PathSeparator: "/", FolderSeparatorIcon: " > "},
-		{Style: Letter, Expected: "➼ > .w > man", HomePath: "/usr/home", Pwd: "➼/.whatever/man", PathSeparator: "/", FolderSeparatorIcon: " > "},
-		{Style: Letter, Expected: "➼ s > .w > man", HomePath: "/usr/home", Pwd: "➼ something/.whatever/man", PathSeparator: "/", FolderSeparatorIcon: " > "},
-
-		{Style: Unique, Expected: "~ > a > ab > abcd", HomePath: "/usr/home", Pwd: "/usr/home/ab/abc/abcd", PathSeparator: "/", FolderSeparatorIcon: " > "},
-		{Style: Unique, Expected: "~ > a > .a > abcd", HomePath: "/usr/home", Pwd: "/usr/home/ab/.abc/abcd", PathSeparator: "/", FolderSeparatorIcon: " > "},
-		{Style: Unique, Expected: "~ > a > ab > abcd", HomePath: "/usr/home", Pwd: "/usr/home/ab/ab/abcd", PathSeparator: "/", FolderSeparatorIcon: " > "},
-
-		{Style: AgnosterShort, Expected: "localhost > c$", HomePath: homeBillWindows, Pwd: "\\\\localhost\\c$", PathSeparator: "\\", FolderSeparatorIcon: " > "},
-		{Style: AgnosterShort, Expected: "localhost\\c$", HomePath: homeBillWindows, Pwd: "\\\\localhost\\c$", PathSeparator: "\\", FolderSeparatorIcon: "\\"},
+		{
+			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:                environment.WINDOWS,
+			PathSeparator:       "\\",
+			FolderSeparatorIcon: " > ",
+		},
+		{
+			Style:               Letter,
+			Expected:            "C > s > .w > man",
+			HomePath:            homeDirWindows,
+			Pwd:                 "C:\\something\\.whatever\\man",
+			GOOS:                environment.WINDOWS,
+			PathSeparator:       "\\",
+			FolderSeparatorIcon: " > ",
+		},
+		{
+			Style:               Letter,
+			Expected:            "~ > s > man",
+			HomePath:            homeDirWindows,
+			Pwd:                 homeDirWindows + "\\something\\man",
+			GOOS:                environment.WINDOWS,
+			PathSeparator:       "\\",
+			FolderSeparatorIcon: " > ",
+		},
+
+		{
+			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:                environment.WINDOWS,
+			PathSeparator:       "\\",
+			FolderSeparatorIcon: " > ",
+		},
 	}
 	for _, tc := range cases {
 		env := new(mock.MockedEnvironment)
@@ -280,11 +682,11 @@ func TestAgnosterPathStyles(t *testing.T) {
 		env.On("GOOS").Return(tc.GOOS)
 		env.On("StackCount").Return(0)
 		env.On("IsWsl").Return(false)
-		env.On("DirIsWritable", tc.Pwd).Return(true)
 		args := &environment.Flags{
 			PSWD: tc.Pswd,
 		}
 		env.On("Flags").Return(args)
+		env.On("Shell").Return(shell.PWSH)
 		path := &Path{
 			env: env,
 			props: properties.Map{
@@ -294,15 +696,16 @@ func TestAgnosterPathStyles(t *testing.T) {
 				HideRootLocation:    tc.HideRootLocation,
 			},
 		}
-		_ = path.Enabled()
+		path.setPath()
 		got := renderTemplate(env, "{{ .Path }}", path)
 		assert.Equal(t, tc.Expected, got)
 	}
 }
 
-func TestGetFullPath(t *testing.T) {
+func TestFullAndFolderPath(t *testing.T) {
 	cases := []struct {
 		Style                  string
+		HomePath               string
 		FolderSeparatorIcon    string
 		Pwd                    string
 		Pswd                   string
@@ -313,82 +716,74 @@ func TestGetFullPath(t *testing.T) {
 		StackCount             int
 		Template               string
 	}{
-		{Style: Full, Pwd: "/usr/home/abc", Template: "{{ .Path }}", StackCount: 2, Expected: "~/abc"},
-
 		{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", Expected: "/"},
-		{Style: Full, Pwd: "", Expected: ""},
 		{Style: Full, Pwd: "/", Expected: "/"},
-		{Style: Full, Pwd: "/usr/home", Expected: "~"},
-		{Style: Full, Pwd: "/usr/home/abc", Expected: "~/abc"},
-		{Style: Full, Pwd: "/usr/home/abc", Expected: "/usr/home/abc", DisableMappedLocations: true},
+		{Style: Full, Pwd: homeDir, Expected: "~"},
+		{Style: Full, Pwd: homeDir + "/abc", Expected: "~/abc"},
+		{Style: Full, Pwd: homeDir + "/abc", Expected: homeDir + "/abc", DisableMappedLocations: true},
 		{Style: Full, Pwd: "/a/b/c/d", Expected: "/a/b/c/d"},
 
-		{Style: Full, FolderSeparatorIcon: "|", Pwd: "", Expected: ""},
-		{Style: Full, FolderSeparatorIcon: "|", Pwd: "/usr/home", Expected: "~"},
-		{Style: Full, FolderSeparatorIcon: "|", Pwd: "/usr/home", Expected: "|usr|home", DisableMappedLocations: true},
-		{Style: Full, FolderSeparatorIcon: "|", Pwd: "/usr/home/abc", Expected: "~|abc"},
-		{Style: Full, FolderSeparatorIcon: "|", Pwd: "/a/b/c/d", Expected: "|a|b|c|d"},
+		{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: "/a/b/c/d", Expected: "/a|b|c|d"},
 
-		{Style: Folder, Pwd: "", Expected: ""},
 		{Style: Folder, Pwd: "/", Expected: "/"},
-		{Style: Folder, Pwd: "/usr/home", Expected: "~"},
-		{Style: Folder, Pwd: "/usr/home", Expected: "home", DisableMappedLocations: true},
-		{Style: Folder, Pwd: "/usr/home/abc", Expected: "abc"},
+		{Style: Folder, Pwd: homeDir, Expected: "~"},
+		{Style: Folder, Pwd: homeDir, Expected: "someone", DisableMappedLocations: true},
+		{Style: Folder, Pwd: homeDir + "/abc", Expected: "abc"},
 		{Style: Folder, Pwd: "/a/b/c/d", Expected: "d"},
 
-		{Style: Folder, FolderSeparatorIcon: "|", Pwd: "", Expected: ""},
 		{Style: Folder, FolderSeparatorIcon: "|", Pwd: "/", Expected: "/"},
-		{Style: Folder, FolderSeparatorIcon: "|", Pwd: "/usr/home", Expected: "~"},
-		{Style: Folder, FolderSeparatorIcon: "|", Pwd: "/usr/home", Expected: "home", DisableMappedLocations: true},
-		{Style: Folder, FolderSeparatorIcon: "|", Pwd: "/usr/home/abc", Expected: "abc"},
+		{Style: Folder, FolderSeparatorIcon: "|", Pwd: homeDir, Expected: "~"},
+		{Style: Folder, FolderSeparatorIcon: "|", Pwd: homeDir, Expected: "someone", DisableMappedLocations: true},
+		{Style: Folder, FolderSeparatorIcon: "|", Pwd: homeDir + "/abc", Expected: "abc"},
 		{Style: Folder, FolderSeparatorIcon: "|", Pwd: "/a/b/c/d", Expected: "d"},
 
+		// for Windows paths
 		{Style: Folder, FolderSeparatorIcon: "\\", Pwd: "C:\\", Expected: "C:\\", PathSeparator: "\\", GOOS: environment.WINDOWS},
-		{Style: Full, FolderSeparatorIcon: "\\", Pwd: "C:\\Users\\Jan", Expected: "C:\\Users\\Jan", PathSeparator: "\\", GOOS: environment.WINDOWS},
+		{Style: Folder, FolderSeparatorIcon: "\\", Pwd: homeDirWindows, Expected: "~", PathSeparator: "\\", GOOS: environment.WINDOWS},
+		{Style: Full, FolderSeparatorIcon: "\\", Pwd: homeDirWindows, Expected: "~", PathSeparator: "\\", GOOS: environment.WINDOWS},
+		{Style: Full, FolderSeparatorIcon: "\\", Pwd: homeDirWindows + "\\abc", Expected: "~\\abc", PathSeparator: "\\", GOOS: environment.WINDOWS},
 
 		// StackCountEnabled=true and StackCount=2
 		{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", StackCount: 2, Expected: "2 /"},
-		{Style: Full, Pwd: "", StackCount: 2, Expected: "2"},
 		{Style: Full, Pwd: "/", StackCount: 2, Expected: "2 /"},
-		{Style: Full, Pwd: "/usr/home", StackCount: 2, Expected: "2 ~"},
-		{Style: Full, Pwd: "/usr/home/abc", StackCount: 2, Expected: "2 ~/abc"},
-		{Style: Full, Pwd: "/usr/home/abc", StackCount: 2, Expected: "2 /usr/home/abc", DisableMappedLocations: true},
+		{Style: Full, Pwd: 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: "/a/b/c/d", 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: "/", Template: "{{ .Path }}", StackCount: 2, Expected: "/"},
-		{Style: Full, Pwd: "/usr/home", Template: "{{ .Path }}", StackCount: 2, Expected: "~"},
+		{Style: Full, Pwd: homeDir, Template: "{{ .Path }}", StackCount: 2, Expected: "~"},
 
-		{Style: Full, Pwd: "/usr/home/abc", Template: "{{ .Path }}", StackCount: 2, Expected: "/usr/home/abc", DisableMappedLocations: true},
+		{Style: Full, Pwd: homeDir + "/abc", Template: "{{ .Path }}", StackCount: 2, Expected: homeDir + "/abc", DisableMappedLocations: true},
 		{Style: Full, Pwd: "/a/b/c/d", Template: "{{ .Path }}", StackCount: 2, Expected: "/a/b/c/d"},
 
 		// StackCountEnabled=true and StackCount=0
 		{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", StackCount: 0, Expected: "/"},
-		{Style: Full, Pwd: "", StackCount: 0, Expected: ""},
 		{Style: Full, Pwd: "/", StackCount: 0, Expected: "/"},
-		{Style: Full, Pwd: "/usr/home", StackCount: 0, Expected: "~"},
-		{Style: Full, Pwd: "/usr/home/abc", StackCount: 0, Expected: "~/abc"},
-		{Style: Full, Pwd: "/usr/home/abc", StackCount: 0, Expected: "/usr/home/abc", DisableMappedLocations: true},
+		{Style: Full, Pwd: 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: "/a/b/c/d", StackCount: 0, Expected: "/a/b/c/d"},
 
 		// StackCountEnabled=true and StackCount<0
 		{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", StackCount: -1, Expected: "/"},
-		{Style: Full, Pwd: "", StackCount: -1, Expected: ""},
 		{Style: Full, Pwd: "/", StackCount: -1, Expected: "/"},
-		{Style: Full, Pwd: "/usr/home", StackCount: -1, Expected: "~"},
-		{Style: Full, Pwd: "/usr/home/abc", StackCount: -1, Expected: "~/abc"},
-		{Style: Full, Pwd: "/usr/home/abc", StackCount: -1, Expected: "/usr/home/abc", DisableMappedLocations: true},
+		{Style: Full, Pwd: 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: "/a/b/c/d", StackCount: -1, Expected: "/a/b/c/d"},
 
 		// StackCountEnabled=true and StackCount not set
 		{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", Expected: "/"},
-		{Style: Full, Pwd: "", Expected: ""},
 		{Style: Full, Pwd: "/", Expected: "/"},
-		{Style: Full, Pwd: "/usr/home", Expected: "~"},
-		{Style: Full, Pwd: "/usr/home/abc", Expected: "~/abc"},
-		{Style: Full, Pwd: "/usr/home/abc", Expected: "/usr/home/abc", DisableMappedLocations: true},
+		{Style: Full, Pwd: homeDir, Expected: "~"},
+		{Style: Full, Pwd: homeDir + "/abc", Expected: "~/abc"},
+		{Style: Full, Pwd: homeDir + "/abc", Expected: homeDir + "/abc", DisableMappedLocations: true},
 		{Style: Full, Pwd: "/a/b/c/d", Expected: "/a/b/c/d"},
 	}
 
@@ -398,16 +793,20 @@ func TestGetFullPath(t *testing.T) {
 			tc.PathSeparator = "/"
 		}
 		env.On("PathSeparator").Return(tc.PathSeparator)
-		env.On("Home").Return("/usr/home")
+		if tc.GOOS == environment.WINDOWS {
+			env.On("Home").Return(homeDirWindows)
+		} else {
+			env.On("Home").Return(homeDir)
+		}
 		env.On("Pwd").Return(tc.Pwd)
 		env.On("GOOS").Return(tc.GOOS)
 		env.On("StackCount").Return(tc.StackCount)
 		env.On("IsWsl").Return(false)
-		env.On("DirIsWritable", tc.Pwd).Return(true)
 		args := &environment.Flags{
 			PSWD: tc.Pswd,
 		}
 		env.On("Flags").Return(args)
+		env.On("Shell").Return(shell.PLAIN)
 		if len(tc.Template) == 0 {
 			tc.Template = "{{ if gt .StackCount 0 }}{{ .StackCount }} {{ end }}{{ .Path }}"
 		}
@@ -421,102 +820,87 @@ func TestGetFullPath(t *testing.T) {
 			props[MappedLocationsEnabled] = false
 		}
 		path := &Path{
-			env:   env,
-			props: props,
+			env:        env,
+			props:      props,
+			StackCount: env.StackCount(),
 		}
-		_ = path.Enabled()
+		path.setPath()
 		got := renderTemplate(env, tc.Template, path)
 		assert.Equal(t, tc.Expected, got)
 	}
 }
 
-func TestGetFullPathCustomMappedLocations(t *testing.T) {
+func TestFullPathCustomMappedLocations(t *testing.T) {
 	cases := []struct {
 		Pwd             string
 		MappedLocations map[string]string
+		GOOS            string
+		PathSeparator   string
 		Expected        string
 	}{
 		{Pwd: "/a/b/c/d", MappedLocations: map[string]string{"/a/b/c/d": "#"}, Expected: "#"},
-		{Pwd: "/a/b/c/d", MappedLocations: map[string]string{"\\a\\b": "#"}, Expected: "#/c/d"},
-		{Pwd: "\\a\\b\\c\\d", MappedLocations: map[string]string{"\\a\\b": "#"}, Expected: "#\\c\\d"},
+		{Pwd: "\\a\\b\\c\\d", MappedLocations: map[string]string{"\\a\\b": "#"}, GOOS: environment.WINDOWS, PathSeparator: "\\", Expected: "#\\c\\d"},
 		{Pwd: "/a/b/c/d", MappedLocations: map[string]string{"/a/b": "#"}, Expected: "#/c/d"},
 		{Pwd: "/a/b/c/d", MappedLocations: map[string]string{"/a/b": "/e/f"}, Expected: "/e/f/c/d"},
-		{Pwd: "/usr/home/a/b/c/d", MappedLocations: map[string]string{"~\\a\\b": "#"}, Expected: "#/c/d"},
-		{Pwd: "/usr/home/a/b/c/d", MappedLocations: map[string]string{"~/a/b": "#"}, Expected: "#/c/d"},
-		{Pwd: "/a/usr/home/b/c/d", MappedLocations: map[string]string{"/a~": "#"}, Expected: "/a/usr/home/b/c/d"},
-		{Pwd: "/usr/home/a/b/c/d", MappedLocations: map[string]string{"/a/b": "#"}, Expected: "/usr/home/a/b/c/d"},
+		{Pwd: homeDir + "/a/b/c/d", 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 + "/a/b/c/d", MappedLocations: map[string]string{"/a/b": "#"}, Expected: homeDir + "/a/b/c/d"},
 	}
 
 	for _, tc := range cases {
 		env := new(mock.MockedEnvironment)
-		env.On("PathSeparator").Return("/")
-		env.On("Home").Return("/usr/home")
+		env.On("Home").Return(homeDir)
 		env.On("Pwd").Return(tc.Pwd)
-		env.On("GOOS").Return("")
+		if tc.GOOS == "" {
+			tc.GOOS = environment.DARWIN
+		}
+		env.On("GOOS").Return(tc.GOOS)
+		if tc.PathSeparator == "" {
+			tc.PathSeparator = "/"
+		}
+		env.On("PathSeparator").Return(tc.PathSeparator)
 		args := &environment.Flags{
 			PSWD: tc.Pwd,
 		}
 		env.On("Flags").Return(args)
+		env.On("Shell").Return(shell.PLAIN)
 		path := &Path{
 			env: env,
 			props: properties.Map{
+				properties.Style:       Full,
 				MappedLocationsEnabled: false,
 				MappedLocations:        tc.MappedLocations,
 			},
 		}
-		got := path.getFullPath()
-		assert.Equal(t, tc.Expected, got)
-	}
-}
-
-func TestNormalizePath(t *testing.T) {
-	cases := []struct {
-		Input    string
-		GOOS     string
-		Expected string
-	}{
-		{Input: "C:\\Users\\Bob\\Foo", GOOS: environment.LINUX, Expected: "C:/Users/Bob/Foo/"},
-		{Input: "C:\\Users\\Bob\\Foo", GOOS: environment.WINDOWS, Expected: "c:/users/bob/foo/"},
-		{Input: "~\\Bob\\Foo", GOOS: environment.LINUX, Expected: "/usr/home/Bob/Foo/"},
-		{Input: "~\\Bob\\Foo", GOOS: environment.WINDOWS, Expected: "/usr/home/bob/foo/"},
-		{Input: "/foo/~/bar", GOOS: environment.LINUX, Expected: "/foo/~/bar/"},
-		{Input: "/foo/~/bar", GOOS: environment.WINDOWS, Expected: "/foo/~/bar/"},
-		{Input: "~/baz", GOOS: environment.LINUX, Expected: "/usr/home/baz/"},
-		{Input: "~/baz", GOOS: environment.WINDOWS, Expected: "/usr/home/baz/"},
-	}
-
-	for _, tc := range cases {
-		env := new(mock.MockedEnvironment)
-		env.On("Home").Return("/usr/home")
-		env.On("GOOS").Return(tc.GOOS)
-		pt := &Path{
-			env: env,
-		}
-		got := pt.normalize(tc.Input)
+		path.setPath()
+		got := renderTemplate(env, "{{ .Path }}", path)
 		assert.Equal(t, tc.Expected, got)
 	}
 }
 
-func TestGetFolderPathCustomMappedLocations(t *testing.T) {
+func TestFolderPathCustomMappedLocations(t *testing.T) {
 	pwd := "/a/b/c/d"
 	env := new(mock.MockedEnvironment)
 	env.On("PathSeparator").Return("/")
-	env.On("Home").Return("/usr/home")
+	env.On("Home").Return(homeDir)
 	env.On("Pwd").Return(pwd)
 	env.On("GOOS").Return("")
 	args := &environment.Flags{
 		PSWD: pwd,
 	}
 	env.On("Flags").Return(args)
+	env.On("Shell").Return(shell.PLAIN)
 	path := &Path{
 		env: env,
 		props: properties.Map{
+			properties.Style: Folder,
 			MappedLocations: map[string]string{
 				"/a/b/c/d": "#",
 			},
 		},
 	}
-	got := path.getFolderPath()
+	path.setPath()
+	got := renderTemplate(env, "{{ .Path }}", path)
 	assert.Equal(t, "#", got)
 }
 
@@ -532,7 +916,7 @@ func TestAgnosterPath(t *testing.T) { //nolint:dupl
 		{
 			Case:          "Windows outside home",
 			Expected:      "C: > f > f > location",
-			Home:          homeBillWindows,
+			Home:          homeDirWindows,
 			PWD:           "C:\\Program Files\\Go\\location",
 			GOOS:          environment.WINDOWS,
 			PathSeparator: "\\",
@@ -540,15 +924,15 @@ func TestAgnosterPath(t *testing.T) { //nolint:dupl
 		{
 			Case:          "Windows oustide home",
 			Expected:      "~ > f > f > location",
-			Home:          homeBillWindows,
-			PWD:           homeBillWindows + "\\Documents\\Bill\\location",
+			Home:          homeDirWindows,
+			PWD:           homeDirWindows + "\\Documents\\Bill\\location",
 			GOOS:          environment.WINDOWS,
 			PathSeparator: "\\",
 		},
 		{
 			Case:          "Windows inside home zero levels",
 			Expected:      "C: > location",
-			Home:          homeBillWindows,
+			Home:          homeDirWindows,
 			PWD:           "C:\\location",
 			GOOS:          environment.WINDOWS,
 			PathSeparator: "\\",
@@ -556,7 +940,7 @@ func TestAgnosterPath(t *testing.T) { //nolint:dupl
 		{
 			Case:          "Windows inside home one level",
 			Expected:      "C: > f > location",
-			Home:          homeBillWindows,
+			Home:          homeDirWindows,
 			PWD:           "C:\\Program Files\\location",
 			GOOS:          environment.WINDOWS,
 			PathSeparator: "\\",
@@ -564,7 +948,7 @@ func TestAgnosterPath(t *testing.T) { //nolint:dupl
 		{
 			Case:          "Windows lower case drive letter",
 			Expected:      "C: > Windows",
-			Home:          homeBillWindows,
+			Home:          homeDirWindows,
 			PWD:           "C:\\Windows\\",
 			GOOS:          environment.WINDOWS,
 			PathSeparator: "\\",
@@ -572,7 +956,7 @@ func TestAgnosterPath(t *testing.T) { //nolint:dupl
 		{
 			Case:          "Windows lower case drive letter (other)",
 			Expected:      "P: > Other",
-			Home:          homeBillWindows,
+			Home:          homeDirWindows,
 			PWD:           "P:\\Other\\",
 			GOOS:          environment.WINDOWS,
 			PathSeparator: "\\",
@@ -580,7 +964,7 @@ func TestAgnosterPath(t *testing.T) { //nolint:dupl
 		{
 			Case:          "Windows lower word drive",
 			Expected:      "some: > some",
-			Home:          homeBillWindows,
+			Home:          homeDirWindows,
 			PWD:           "some:\\some\\",
 			GOOS:          environment.WINDOWS,
 			PathSeparator: "\\",
@@ -588,7 +972,7 @@ func TestAgnosterPath(t *testing.T) { //nolint:dupl
 		{
 			Case:          "Windows lower word drive (ending with c)",
 			Expected:      "src: > source",
-			Home:          homeBillWindows,
+			Home:          homeDirWindows,
 			PWD:           "src:\\source\\",
 			GOOS:          environment.WINDOWS,
 			PathSeparator: "\\",
@@ -596,7 +980,7 @@ func TestAgnosterPath(t *testing.T) { //nolint:dupl
 		{
 			Case:          "Windows lower word drive (arbitrary cases)",
 			Expected:      "sRc: > source",
-			Home:          homeBillWindows,
+			Home:          homeDirWindows,
 			PWD:           "sRc:\\source\\",
 			GOOS:          environment.WINDOWS,
 			PathSeparator: "\\",
@@ -604,7 +988,7 @@ func TestAgnosterPath(t *testing.T) { //nolint:dupl
 		{
 			Case:          "Windows registry drive",
 			Expected:      "\uf013 > f > magnetic:test",
-			Home:          homeBillWindows,
+			Home:          homeDirWindows,
 			PWD:           "HKLM:\\SOFTWARE\\magnetic:test\\",
 			GOOS:          environment.WINDOWS,
 			PathSeparator: "\\",
@@ -612,7 +996,7 @@ func TestAgnosterPath(t *testing.T) { //nolint:dupl
 		{
 			Case:          "Windows registry drive case sensitive",
 			Expected:      "\uf013 > f > magnetic:TOAST",
-			Home:          homeBillWindows,
+			Home:          homeDirWindows,
 			PWD:           "HKLM:\\SOFTWARE\\magnetic:TOAST\\",
 			GOOS:          environment.WINDOWS,
 			PathSeparator: "\\",
@@ -620,28 +1004,28 @@ func TestAgnosterPath(t *testing.T) { //nolint:dupl
 		{
 			Case:          "Unix outside home",
 			Expected:      "mnt > f > f > location",
-			Home:          homeJan,
+			Home:          homeDir,
 			PWD:           "/mnt/go/test/location",
 			PathSeparator: "/",
 		},
 		{
 			Case:          "Unix inside home",
 			Expected:      "~ > f > f > location",
-			Home:          homeJan,
-			PWD:           homeJan + "/docs/jan/location",
+			Home:          homeDir,
+			PWD:           homeDir + "/docs/jan/location",
 			PathSeparator: "/",
 		},
 		{
 			Case:          "Unix outside home zero levels",
 			Expected:      "mnt > location",
-			Home:          homeJan,
+			Home:          homeDir,
 			PWD:           "/mnt/location",
 			PathSeparator: "/",
 		},
 		{
 			Case:          "Unix outside home one level",
 			Expected:      "mnt > f > location",
-			Home:          homeJan,
+			Home:          homeDir,
 			PWD:           "/mnt/folder/location",
 			PathSeparator: "/",
 		},
@@ -657,15 +1041,18 @@ func TestAgnosterPath(t *testing.T) { //nolint:dupl
 			PSWD: tc.PWD,
 		}
 		env.On("Flags").Return(args)
+		env.On("Shell").Return(shell.PWSH)
 		path := &Path{
 			env: env,
 			props: properties.Map{
+				properties.Style:    Agnoster,
 				FolderSeparatorIcon: " > ",
 				FolderIcon:          "f",
 				HomeIcon:            "~",
 			},
 		}
-		got := path.getAgnosterPath()
+		path.setPath()
+		got := renderTemplate(env, "{{ .Path }}", path)
 		assert.Equal(t, tc.Expected, got, tc.Case)
 	}
 }
@@ -682,7 +1069,7 @@ func TestAgnosterLeftPath(t *testing.T) { //nolint:dupl
 		{
 			Case:          "Windows outside home",
 			Expected:      "C: > Program Files > f > f",
-			Home:          homeBillWindows,
+			Home:          homeDirWindows,
 			PWD:           "C:\\Program Files\\Go\\location",
 			GOOS:          environment.WINDOWS,
 			PathSeparator: "\\",
@@ -690,15 +1077,15 @@ func TestAgnosterLeftPath(t *testing.T) { //nolint:dupl
 		{
 			Case:          "Windows inside home",
 			Expected:      "~ > Documents > f > f",
-			Home:          homeBillWindows,
-			PWD:           homeBillWindows + "\\Documents\\Bill\\location",
+			Home:          homeDirWindows,
+			PWD:           homeDirWindows + "\\Documents\\Bill\\location",
 			GOOS:          environment.WINDOWS,
 			PathSeparator: "\\",
 		},
 		{
 			Case:          "Windows inside home zero levels",
 			Expected:      "C: > location",
-			Home:          homeBillWindows,
+			Home:          homeDirWindows,
 			PWD:           "C:\\location",
 			GOOS:          environment.WINDOWS,
 			PathSeparator: "\\",
@@ -706,7 +1093,7 @@ func TestAgnosterLeftPath(t *testing.T) { //nolint:dupl
 		{
 			Case:          "Windows inside home one level",
 			Expected:      "C: > Program Files > f",
-			Home:          homeBillWindows,
+			Home:          homeDirWindows,
 			PWD:           "C:\\Program Files\\location",
 			GOOS:          environment.WINDOWS,
 			PathSeparator: "\\",
@@ -714,7 +1101,7 @@ func TestAgnosterLeftPath(t *testing.T) { //nolint:dupl
 		{
 			Case:          "Windows lower case drive letter",
 			Expected:      "C: > Windows",
-			Home:          homeBillWindows,
+			Home:          homeDirWindows,
 			PWD:           "C:\\Windows\\",
 			GOOS:          environment.WINDOWS,
 			PathSeparator: "\\",
@@ -722,7 +1109,7 @@ func TestAgnosterLeftPath(t *testing.T) { //nolint:dupl
 		{
 			Case:          "Windows lower case drive letter (other)",
 			Expected:      "P: > Other",
-			Home:          homeBillWindows,
+			Home:          homeDirWindows,
 			PWD:           "P:\\Other\\",
 			GOOS:          environment.WINDOWS,
 			PathSeparator: "\\",
@@ -730,7 +1117,7 @@ func TestAgnosterLeftPath(t *testing.T) { //nolint:dupl
 		{
 			Case:          "Windows lower word drive",
 			Expected:      "some: > some",
-			Home:          homeBillWindows,
+			Home:          homeDirWindows,
 			PWD:           "some:\\some\\",
 			GOOS:          environment.WINDOWS,
 			PathSeparator: "\\",
@@ -738,7 +1125,7 @@ func TestAgnosterLeftPath(t *testing.T) { //nolint:dupl
 		{
 			Case:          "Windows lower word drive (ending with c)",
 			Expected:      "src: > source",
-			Home:          homeBillWindows,
+			Home:          homeDirWindows,
 			PWD:           "src:\\source\\",
 			GOOS:          environment.WINDOWS,
 			PathSeparator: "\\",
@@ -746,7 +1133,7 @@ func TestAgnosterLeftPath(t *testing.T) { //nolint:dupl
 		{
 			Case:          "Windows lower word drive (arbitrary cases)",
 			Expected:      "sRc: > source",
-			Home:          homeBillWindows,
+			Home:          homeDirWindows,
 			PWD:           "sRc:\\source\\",
 			GOOS:          environment.WINDOWS,
 			PathSeparator: "\\",
@@ -754,7 +1141,7 @@ func TestAgnosterLeftPath(t *testing.T) { //nolint:dupl
 		{
 			Case:          "Windows registry drive",
 			Expected:      "\uf013 > SOFTWARE > f",
-			Home:          homeBillWindows,
+			Home:          homeDirWindows,
 			PWD:           "HKLM:\\SOFTWARE\\magnetic:test\\",
 			GOOS:          environment.WINDOWS,
 			PathSeparator: "\\",
@@ -762,7 +1149,7 @@ func TestAgnosterLeftPath(t *testing.T) { //nolint:dupl
 		{
 			Case:          "Windows registry drive case sensitive",
 			Expected:      "\uf013 > SOFTWARE > f",
-			Home:          homeBillWindows,
+			Home:          homeDirWindows,
 			PWD:           "HKLM:\\SOFTWARE\\magnetic:TOAST\\",
 			GOOS:          environment.WINDOWS,
 			PathSeparator: "\\",
@@ -770,28 +1157,28 @@ func TestAgnosterLeftPath(t *testing.T) { //nolint:dupl
 		{
 			Case:          "Unix outside home",
 			Expected:      "mnt > go > f > f",
-			Home:          homeJan,
+			Home:          homeDir,
 			PWD:           "/mnt/go/test/location",
 			PathSeparator: "/",
 		},
 		{
 			Case:          "Unix inside home",
 			Expected:      "~ > docs > f > f",
-			Home:          homeJan,
-			PWD:           homeJan + "/docs/jan/location",
+			Home:          homeDir,
+			PWD:           homeDir + "/docs/jan/location",
 			PathSeparator: "/",
 		},
 		{
 			Case:          "Unix outside home zero levels",
 			Expected:      "mnt > location",
-			Home:          homeJan,
+			Home:          homeDir,
 			PWD:           "/mnt/location",
 			PathSeparator: "/",
 		},
 		{
 			Case:          "Unix outside home one level",
 			Expected:      "mnt > folder > f",
-			Home:          homeJan,
+			Home:          homeDir,
 			PWD:           "/mnt/folder/location",
 			PathSeparator: "/",
 		},
@@ -807,15 +1194,18 @@ func TestAgnosterLeftPath(t *testing.T) { //nolint:dupl
 			PSWD: tc.PWD,
 		}
 		env.On("Flags").Return(args)
+		env.On("Shell").Return(shell.PWSH)
 		path := &Path{
 			env: env,
 			props: properties.Map{
+				properties.Style:    AgnosterLeft,
 				FolderSeparatorIcon: " > ",
 				FolderIcon:          "f",
 				HomeIcon:            "~",
 			},
 		}
-		got := path.getAgnosterLeftPath()
+		path.setPath()
+		got := renderTemplate(env, "{{ .Path }}", path)
 		assert.Equal(t, tc.Expected, got, tc.Case)
 	}
 }
@@ -827,20 +1217,20 @@ func TestGetPwd(t *testing.T) {
 		Pswd                   string
 		Expected               string
 	}{
-		{MappedLocationsEnabled: true, Pwd: "/usr/home", Expected: "~"},
-		{MappedLocationsEnabled: true, Pwd: "/usr/home-test", Expected: "/usr/home-test"},
-		{MappedLocationsEnabled: true, Pwd: "", Expected: ""},
+		{MappedLocationsEnabled: true, Pwd: homeDir, Expected: "~"},
+		{MappedLocationsEnabled: true, Pwd: homeDir + "-test", Expected: homeDir + "-test"},
+		{MappedLocationsEnabled: true},
 		{MappedLocationsEnabled: true, Pwd: "/usr", Expected: "/usr"},
-		{MappedLocationsEnabled: true, Pwd: "/usr/home/abc", Expected: "~/abc"},
+		{MappedLocationsEnabled: true, Pwd: homeDir + "/abc", Expected: "~/abc"},
 		{MappedLocationsEnabled: true, Pwd: "/a/b/c/d", 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, Pwd: "", Expected: ""},
-		{MappedLocationsEnabled: false, Pwd: "/usr/home/abc", Expected: "/usr/home/abc"},
+		{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: "/usr/home/c/d/e/f/g", Expected: "/usr/home/c/d/e/f/g"},
-		{MappedLocationsEnabled: true, Pwd: "/usr/home/c/d/e/f/g", Expected: "~/c/d/e/f/g"},
+		{MappedLocationsEnabled: false, Pwd: homeDir + "/c/d/e/f/g", Expected: homeDir + "/c/d/e/f/g"},
+		{MappedLocationsEnabled: true, Pwd: homeDir + "/c/d/e/f/g", 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"},
@@ -849,13 +1239,14 @@ func TestGetPwd(t *testing.T) {
 	for _, tc := range cases {
 		env := new(mock.MockedEnvironment)
 		env.On("PathSeparator").Return("/")
-		env.On("Home").Return("/usr/home")
+		env.On("Home").Return(homeDir)
 		env.On("Pwd").Return(tc.Pwd)
 		env.On("GOOS").Return("")
 		args := &environment.Flags{
 			PSWD: tc.Pswd,
 		}
 		env.On("Flags").Return(args)
+		env.On("Shell").Return(shell.PWSH)
 		path := &Path{
 			env: env,
 			props: properties.Map{
@@ -880,8 +1271,8 @@ func TestGetFolderSeparator(t *testing.T) {
 		{Case: "default", Expected: "/"},
 		{Case: "icon - no template", FolderSeparatorIcon: "\ue5fe", Expected: "\ue5fe"},
 		{Case: "template", FolderSeparatorTemplate: "{{ if eq .Shell \"bash\" }}\\{{ end }}", Expected: "\\"},
-		{Case: "template empty", FolderSeparatorTemplate: "{{ if eq .Shell \"pwsh\" }}\\{{ end }}", Expected: ""},
-		{Case: "invalid template", FolderSeparatorTemplate: "{{ if eq .Shell \"pwsh\" }}", Expected: ""},
+		{Case: "template empty", FolderSeparatorTemplate: "{{ if eq .Shell \"pwsh\" }}\\{{ end }}", Expected: "/"},
+		{Case: "invalid template", FolderSeparatorTemplate: "{{ if eq .Shell \"pwsh\" }}", Expected: "/"},
 	}
 
 	for _, tc := range cases {
@@ -907,3 +1298,32 @@ func TestGetFolderSeparator(t *testing.T) {
 		assert.Equal(t, tc.Expected, got)
 	}
 }
+
+func TestNormalizePath(t *testing.T) {
+	cases := []struct {
+		Input    string
+		HomeDir  string
+		GOOS     string
+		Expected string
+	}{
+		{Input: homeDirWindows + "\\Foo", HomeDir: homeDirWindows, GOOS: environment.WINDOWS, Expected: "c:\\users\\someone\\foo"},
+		{Input: "~/Bob\\Foo", HomeDir: homeDir, GOOS: environment.LINUX, Expected: homeDir + "/Bob\\Foo"},
+		{Input: "~/Bob\\Foo", HomeDir: homeDir, GOOS: environment.DARWIN, Expected: homeDir + "/bob\\foo"},
+		{Input: "~\\Bob\\Foo", HomeDir: homeDirWindows, GOOS: environment.WINDOWS, Expected: "c:\\users\\someone\\bob\\foo"},
+		{Input: "/foo/~/bar", HomeDir: homeDir, GOOS: environment.LINUX, Expected: "/foo/~/bar"},
+		{Input: "/foo/~/bar", HomeDir: homeDirWindows, GOOS: environment.WINDOWS, Expected: "\\foo\\~\\bar"},
+		{Input: "~/baz", HomeDir: homeDir, GOOS: environment.LINUX, Expected: homeDir + "/baz"},
+		{Input: "~/baz", HomeDir: homeDirWindows, GOOS: environment.WINDOWS, Expected: "c:\\users\\someone\\baz"},
+	}
+
+	for _, tc := range cases {
+		env := new(mock.MockedEnvironment)
+		env.On("Home").Return(tc.HomeDir)
+		env.On("GOOS").Return(tc.GOOS)
+		pt := &Path{
+			env: env,
+		}
+		got := pt.normalize(tc.Input)
+		assert.Equal(t, tc.Expected, got)
+	}
+}