Repository: JanDeDobbeleer/oh-my-posh
Pull request #2942 (2022-10-14 06:39:45)

fix path
### 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

- fix(path): correct root on full style
- fix(path): format root correctly

<!---

Tips:

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

-->

[CONTRIBUTING.md]: https://github.com/JanDeDobbeleer/oh-my-posh/blob/main/CONTRIBUTING.md
[cc]: https://www.conventionalcommits.org/en/v1.0.0/#summary



Patch:
diff --git a/src/segments/path.go b/src/segments/path.go
index 6dd48276..fb038b41 100644
--- a/src/segments/path.go
+++ b/src/segments/path.go
@@ -364,8 +364,9 @@ func (pt *Path) getAgnosterShortPath() string {
 
 func (pt *Path) getFullPath() string {
 	rel := pt.relative
-	if pt.root != pt.env.PathSeparator() {
-		rel = pt.env.PathSeparator() + rel
+	pathSeparator := pt.env.PathSeparator()
+	if pt.root != pathSeparator && !strings.HasSuffix(pt.root, pathSeparator) {
+		rel = pathSeparator + rel
 	}
 	path := pt.replaceFolderSeparators(rel)
 	return pt.root + path
@@ -408,16 +409,6 @@ func (pt *Path) replaceMappedLocations() (string, string) {
 	relativeN := pt.normalize(relative)
 	pathSeparator := pt.env.PathSeparator()
 
-	formatRoot := func(root string) string {
-		// trim the trailing separator first
-		root = strings.TrimSuffix(root, pathSeparator)
-		// only preserve the trailing separator for a Unix/Windows/PSDrive root
-		if len(root) == 0 || strings.HasSuffix(root, ":") {
-			return root + pathSeparator
-		}
-		return root
-	}
-
 	for _, key := range keys {
 		keyRoot, keyRelative := pt.parsePath(key)
 		if keyRoot != rootN || !strings.HasPrefix(relativeN, keyRelative) {
@@ -427,18 +418,18 @@ func (pt *Path) replaceMappedLocations() (string, string) {
 		overflow := relative[len(keyRelative):]
 		if len(overflow) == 0 {
 			// exactly match the full path
-			return formatRoot(value), ""
+			return value, ""
 		}
 		if len(keyRelative) == 0 {
 			// only match the root
-			return formatRoot(value), strings.Trim(relative, pathSeparator)
+			return value, strings.Trim(relative, pathSeparator)
 		}
 		// match several prefix elements
 		if overflow[0:1] == pt.env.PathSeparator() {
-			return formatRoot(value), strings.Trim(overflow, pathSeparator)
+			return value, strings.Trim(overflow, pathSeparator)
 		}
 	}
-	return formatRoot(root), strings.Trim(relative, pathSeparator)
+	return root, strings.Trim(relative, pathSeparator)
 }
 
 func (pt *Path) normalizePath(path string) string {
@@ -484,16 +475,15 @@ func (pt *Path) parsePath(inputPath string) (root, path string) {
 		// 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"] + `\`
+			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 pt.env.GOOS() == environment.WINDOWS {
+		root = strings.TrimSuffix(root, separator)
 	}
 	if len(s) == 2 {
 		path = clean(s[1])


Test patch:
diff --git a/src/segments/path_test.go b/src/segments/path_test.go
index 370cd2d2..f2cdd122 100644
--- a/src/segments/path_test.go
+++ b/src/segments/path_test.go
@@ -280,7 +280,7 @@ func TestAgnosterPathStyles(t *testing.T) {
 			Style:               Letter,
 			Expected:            "➼ > .w > man",
 			HomePath:            homeDir,
-			Pwd:                 "➼/.whatever/man",
+			Pwd:                 "/➼/.whatever/man",
 			PathSeparator:       "/",
 			FolderSeparatorIcon: " > ",
 		},
@@ -288,13 +288,13 @@ func TestAgnosterPathStyles(t *testing.T) {
 			Style:               Letter,
 			Expected:            "➼ s > .w > man",
 			HomePath:            homeDir,
-			Pwd:                 "➼ something/.whatever/man",
+			Pwd:                 "/➼ something/.whatever/man",
 			PathSeparator:       "/",
 			FolderSeparatorIcon: " > ",
 		},
 		{
 			Style:               Letter,
-			Expected:            "C:\\",
+			Expected:            "C:",
 			HomePath:            homeDirWindows,
 			Pwd:                 "C:\\",
 			GOOS:                environment.WINDOWS,
@@ -354,7 +354,7 @@ func TestAgnosterPathStyles(t *testing.T) {
 		},
 		{
 			Style:               Mixed,
-			Expected:            "C:\\ > .. > foo > .. > man",
+			Expected:            "C: > .. > foo > .. > man",
 			HomePath:            homeDirWindows,
 			Pwd:                 "C:\\Users\\foo\\foobar\\man",
 			GOOS:                environment.WINDOWS,
@@ -563,7 +563,7 @@ func TestAgnosterPathStyles(t *testing.T) {
 		},
 		{
 			Style:               AgnosterShort,
-			Expected:            "C:/",
+			Expected:            "C:",
 			HomePath:            homeDir,
 			Pwd:                 "/mnt/c",
 			Pswd:                "C:",
@@ -594,7 +594,7 @@ func TestAgnosterPathStyles(t *testing.T) {
 		},
 		{
 			Style:               AgnosterShort,
-			Expected:            "C:\\",
+			Expected:            "C:",
 			HomePath:            homeDirWindows,
 			Pwd:                 "C:",
 			GOOS:                environment.WINDOWS,
@@ -603,7 +603,7 @@ func TestAgnosterPathStyles(t *testing.T) {
 		},
 		{
 			Style:               AgnosterShort,
-			Expected:            "C:\\ > .. > bar > man",
+			Expected:            "C: > .. > bar > man",
 			HomePath:            homeDirWindows,
 			Pwd:                 "C:\\usr\\foo\\bar\\man",
 			GOOS:                environment.WINDOWS,
@@ -613,7 +613,7 @@ func TestAgnosterPathStyles(t *testing.T) {
 		},
 		{
 			Style:               AgnosterShort,
-			Expected:            "C:\\ > .. > foo > bar > man",
+			Expected:            "C: > .. > foo > bar > man",
 			HomePath:            homeDirWindows,
 			Pwd:                 "C:\\usr\\foo\\bar\\man",
 			GOOS:                environment.WINDOWS,
@@ -743,10 +743,11 @@ func TestFullAndFolderPath(t *testing.T) {
 		{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: Folder, FolderSeparatorIcon: "\\", Pwd: "C:\\", Expected: "C:", 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},
+		{Style: Full, FolderSeparatorIcon: "\\", Pwd: "C:\\Users\\posh", Expected: "C:\\Users\\posh", PathSeparator: "\\", GOOS: environment.WINDOWS},
 
 		// StackCountEnabled=true and StackCount=2
 		{Style: Full, FolderSeparatorIcon: "|", Pwd: "/", StackCount: 2, Expected: "2 /"},
@@ -918,9 +919,17 @@ func TestAgnosterPath(t *testing.T) {
 		GOOS          string
 		PathSeparator string
 	}{
+		{
+			Case:          "Windows registry drive case sensitive",
+			Expected:      "\uf013 > f > magnetic:TOAST",
+			Home:          homeDirWindows,
+			PWD:           "HKLM:\\SOFTWARE\\magnetic:TOAST\\",
+			GOOS:          environment.WINDOWS,
+			PathSeparator: "\\",
+		},
 		{
 			Case:          "Windows outside home",
-			Expected:      "C:\\ > f > f > location",
+			Expected:      "C: > f > f > location",
 			Home:          homeDirWindows,
 			PWD:           "C:\\Program Files\\Go\\location",
 			GOOS:          environment.WINDOWS,
@@ -936,7 +945,7 @@ func TestAgnosterPath(t *testing.T) {
 		},
 		{
 			Case:          "Windows inside home zero levels",
-			Expected:      "C:\\ > location",
+			Expected:      "C: > location",
 			Home:          homeDirWindows,
 			PWD:           "C:\\location",
 			GOOS:          environment.WINDOWS,
@@ -944,7 +953,7 @@ func TestAgnosterPath(t *testing.T) {
 		},
 		{
 			Case:          "Windows inside home one level",
-			Expected:      "C:\\ > f > location",
+			Expected:      "C: > f > location",
 			Home:          homeDirWindows,
 			PWD:           "C:\\Program Files\\location",
 			GOOS:          environment.WINDOWS,
@@ -952,7 +961,7 @@ func TestAgnosterPath(t *testing.T) {
 		},
 		{
 			Case:          "Windows lower case drive letter",
-			Expected:      "C:\\ > Windows",
+			Expected:      "C: > Windows",
 			Home:          homeDirWindows,
 			PWD:           "C:\\Windows\\",
 			GOOS:          environment.WINDOWS,
@@ -960,7 +969,7 @@ func TestAgnosterPath(t *testing.T) {
 		},
 		{
 			Case:          "Windows lower case drive letter (other)",
-			Expected:      "P:\\ > Other",
+			Expected:      "P: > Other",
 			Home:          homeDirWindows,
 			PWD:           "P:\\Other\\",
 			GOOS:          environment.WINDOWS,
@@ -968,7 +977,7 @@ func TestAgnosterPath(t *testing.T) {
 		},
 		{
 			Case:          "Windows lower word drive",
-			Expected:      "some:\\ > some",
+			Expected:      "some: > some",
 			Home:          homeDirWindows,
 			PWD:           "some:\\some\\",
 			GOOS:          environment.WINDOWS,
@@ -976,7 +985,7 @@ func TestAgnosterPath(t *testing.T) {
 		},
 		{
 			Case:          "Windows lower word drive (ending with c)",
-			Expected:      "src:\\ > source",
+			Expected:      "src: > source",
 			Home:          homeDirWindows,
 			PWD:           "src:\\source\\",
 			GOOS:          environment.WINDOWS,
@@ -984,7 +993,7 @@ func TestAgnosterPath(t *testing.T) {
 		},
 		{
 			Case:          "Windows lower word drive (arbitrary cases)",
-			Expected:      "sRc:\\ > source",
+			Expected:      "sRc: > source",
 			Home:          homeDirWindows,
 			PWD:           "sRc:\\source\\",
 			GOOS:          environment.WINDOWS,
@@ -998,14 +1007,6 @@ func TestAgnosterPath(t *testing.T) {
 			GOOS:          environment.WINDOWS,
 			PathSeparator: "\\",
 		},
-		{
-			Case:          "Windows registry drive case sensitive",
-			Expected:      "\uf013 > f > magnetic:TOAST",
-			Home:          homeDirWindows,
-			PWD:           "HKLM:\\SOFTWARE\\magnetic:TOAST\\",
-			GOOS:          environment.WINDOWS,
-			PathSeparator: "\\",
-		},
 		{
 			Case:          "Unix outside home",
 			Expected:      "mnt > f > f > location",
@@ -1082,7 +1083,7 @@ func TestAgnosterLeftPath(t *testing.T) {
 		},
 		{
 			Case:          "Windows outside home",
-			Expected:      "C:\\ > Program Files > f > f",
+			Expected:      "C: > Program Files > f > f",
 			Home:          homeDirWindows,
 			PWD:           "C:\\Program Files\\Go\\location",
 			GOOS:          environment.WINDOWS,
@@ -1090,7 +1091,7 @@ func TestAgnosterLeftPath(t *testing.T) {
 		},
 		{
 			Case:          "Windows inside home zero levels",
-			Expected:      "C:\\ > location",
+			Expected:      "C: > location",
 			Home:          homeDirWindows,
 			PWD:           "C:\\location",
 			GOOS:          environment.WINDOWS,
@@ -1098,7 +1099,7 @@ func TestAgnosterLeftPath(t *testing.T) {
 		},
 		{
 			Case:          "Windows inside home one level",
-			Expected:      "C:\\ > Program Files > f",
+			Expected:      "C: > Program Files > f",
 			Home:          homeDirWindows,
 			PWD:           "C:\\Program Files\\location",
 			GOOS:          environment.WINDOWS,
@@ -1106,7 +1107,7 @@ func TestAgnosterLeftPath(t *testing.T) {
 		},
 		{
 			Case:          "Windows lower case drive letter",
-			Expected:      "C:\\ > Windows",
+			Expected:      "C: > Windows",
 			Home:          homeDirWindows,
 			PWD:           "C:\\Windows\\",
 			GOOS:          environment.WINDOWS,
@@ -1114,7 +1115,7 @@ func TestAgnosterLeftPath(t *testing.T) {
 		},
 		{
 			Case:          "Windows lower case drive letter (other)",
-			Expected:      "P:\\ > Other",
+			Expected:      "P: > Other",
 			Home:          homeDirWindows,
 			PWD:           "P:\\Other\\",
 			GOOS:          environment.WINDOWS,
@@ -1122,7 +1123,7 @@ func TestAgnosterLeftPath(t *testing.T) {
 		},
 		{
 			Case:          "Windows lower word drive",
-			Expected:      "some:\\ > some",
+			Expected:      "some: > some",
 			Home:          homeDirWindows,
 			PWD:           "some:\\some\\",
 			GOOS:          environment.WINDOWS,
@@ -1130,7 +1131,7 @@ func TestAgnosterLeftPath(t *testing.T) {
 		},
 		{
 			Case:          "Windows lower word drive (ending with c)",
-			Expected:      "src:\\ > source",
+			Expected:      "src: > source",
 			Home:          homeDirWindows,
 			PWD:           "src:\\source\\",
 			GOOS:          environment.WINDOWS,
@@ -1138,7 +1139,7 @@ func TestAgnosterLeftPath(t *testing.T) {
 		},
 		{
 			Case:          "Windows lower word drive (arbitrary cases)",
-			Expected:      "sRc:\\ > source",
+			Expected:      "sRc: > source",
 			Home:          homeDirWindows,
 			PWD:           "sRc:\\source\\",
 			GOOS:          environment.WINDOWS,