mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2024-12-27 11:59:40 -08:00
feat(path): flexible matching for mapped-locations
This commit is contained in:
parent
e1be81e658
commit
5db251ce53
|
@ -43,12 +43,12 @@ 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
|
||||
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.
|
||||
|
||||
- mapped_locations_enabled: `boolean` - replace known locations in the path with the replacements before applying the
|
||||
style. defaults to `true`
|
||||
- mapped_locations: `map[string]string` - custom glyph/text for specific paths. Works regardless of the `mapped_locations_enabled`
|
||||
style - defaults to `true`
|
||||
- mapped_locations: `object` - custom glyph/text for specific paths. Works regardless of the `mapped_locations_enabled`
|
||||
setting.
|
||||
|
||||
For example, to swap out `C:\Users\Leet\GitHub` with a GitHub icon, you can do the following:
|
||||
|
@ -59,6 +59,16 @@ 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.
|
||||
- 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.
|
||||
|
||||
This means that for user Bill, who has a user account `Bill` on Windows and `bill` on Linux, `~/Foo` might match
|
||||
`C:\Users\Bill\Foo` or `C:\Users\Bill\foo` on Windows but only `/home/bill/Foo` on Linux.
|
||||
|
||||
## Style
|
||||
|
||||
Style sets the way the path is displayed. Based on previous experience and popular themes, there are 5 flavors.
|
||||
|
|
|
@ -220,6 +220,19 @@ func (pt *path) getPwd() string {
|
|||
return pwd
|
||||
}
|
||||
|
||||
func (pt *path) normalize(inputPath string) string {
|
||||
normalized := inputPath
|
||||
if strings.HasPrefix(inputPath, "~") {
|
||||
normalized = pt.env.homeDir() + normalized[1:]
|
||||
}
|
||||
normalized = strings.ReplaceAll(normalized, "\\", "/")
|
||||
goos := pt.env.getRuntimeGOOS()
|
||||
if goos == windowsPlatform || goos == darwinPlatform {
|
||||
normalized = strings.ToLower(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)
|
||||
|
@ -229,14 +242,14 @@ func (pt *path) replaceMappedLocations(pwd string) string {
|
|||
if pt.props.getBool(MappedLocationsEnabled, true) {
|
||||
mappedLocations["HKCU:"] = pt.props.getString(WindowsRegistryIcon, "\uF013")
|
||||
mappedLocations["HKLM:"] = pt.props.getString(WindowsRegistryIcon, "\uF013")
|
||||
mappedLocations[pt.env.homeDir()] = pt.props.getString(HomeIcon, "~")
|
||||
mappedLocations[pt.normalize(pt.env.homeDir())] = pt.props.getString(HomeIcon, "~")
|
||||
}
|
||||
|
||||
// merge custom locations with mapped locations
|
||||
// mapped locations can override predefined locations
|
||||
keyValues := pt.props.getKeyValueMap(MappedLocations, make(map[string]string))
|
||||
for key, val := range keyValues {
|
||||
mappedLocations[key] = val
|
||||
mappedLocations[pt.normalize(key)] = val
|
||||
}
|
||||
|
||||
// sort map keys in reverse order
|
||||
|
@ -250,9 +263,11 @@ func (pt *path) replaceMappedLocations(pwd string) string {
|
|||
}
|
||||
sort.Sort(sort.Reverse(sort.StringSlice(keys)))
|
||||
|
||||
for _, value := range keys {
|
||||
if strings.HasPrefix(pwd, value) {
|
||||
return strings.Replace(pwd, value, mappedLocations[value], 1)
|
||||
normalizedPwd := pt.normalize(pwd)
|
||||
for _, key := range keys {
|
||||
if strings.HasPrefix(normalizedPwd, key) {
|
||||
value := mappedLocations[key]
|
||||
return value + pwd[len(key):]
|
||||
}
|
||||
}
|
||||
return pwd
|
||||
|
|
|
@ -220,6 +220,7 @@ func TestRootLocationHome(t *testing.T) {
|
|||
}
|
||||
env.On("getArgs", nil).Return(args)
|
||||
env.On("getPathSeperator", nil).Return(tc.PathSeperator)
|
||||
env.On("getRuntimeGOOS", nil).Return("")
|
||||
path := &path{
|
||||
env: env,
|
||||
props: props,
|
||||
|
@ -247,6 +248,7 @@ func TestPathDepthMultipleLevelsDeep(t *testing.T) {
|
|||
}
|
||||
env := new(MockedEnvironment)
|
||||
env.On("getPathSeperator", nil).Return("/")
|
||||
env.On("getRunteGOOS", nil).Return("")
|
||||
path := &path{
|
||||
env: env,
|
||||
}
|
||||
|
@ -500,12 +502,82 @@ func TestGetFullPath(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestGetFullPathCustomMappedLocations(t *testing.T) {
|
||||
cases := []struct {
|
||||
Pwd string
|
||||
MappedLocations map[string]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": "#"}, 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"},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
env := new(MockedEnvironment)
|
||||
env.On("getPathSeperator", nil).Return("/")
|
||||
env.On("homeDir", nil).Return("/usr/home")
|
||||
env.On("getcwd", nil).Return(tc.Pwd)
|
||||
env.On("getRuntimeGOOS", nil).Return("")
|
||||
args := &args{
|
||||
PSWD: &tc.Pwd,
|
||||
}
|
||||
env.On("getArgs", nil).Return(args)
|
||||
path := &path{
|
||||
env: env,
|
||||
props: &properties{
|
||||
values: map[Property]interface{}{
|
||||
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: linuxPlatform, Expected: "C:/Users/Bob/Foo"},
|
||||
{Input: "C:\\Users\\Bob\\Foo", GOOS: windowsPlatform, Expected: "c:/users/bob/foo"},
|
||||
{Input: "~\\Bob\\Foo", GOOS: linuxPlatform, Expected: "/usr/home/Bob/Foo"},
|
||||
{Input: "~\\Bob\\Foo", GOOS: windowsPlatform, Expected: "/usr/home/bob/foo"},
|
||||
{Input: "/foo/~/bar", GOOS: linuxPlatform, Expected: "/foo/~/bar"},
|
||||
{Input: "/foo/~/bar", GOOS: windowsPlatform, Expected: "/foo/~/bar"},
|
||||
{Input: "~/baz", GOOS: linuxPlatform, Expected: "/usr/home/baz"},
|
||||
{Input: "~/baz", GOOS: windowsPlatform, Expected: "/usr/home/baz"},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
env := new(MockedEnvironment)
|
||||
env.On("homeDir", nil).Return("/usr/home")
|
||||
env.On("getRuntimeGOOS", nil).Return(tc.GOOS)
|
||||
pt := &path{
|
||||
env: env,
|
||||
}
|
||||
got := pt.normalize(tc.Input)
|
||||
assert.Equal(t, tc.Expected, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetFolderPathCustomMappedLocations(t *testing.T) {
|
||||
pwd := "/a/b/c/d"
|
||||
env := new(MockedEnvironment)
|
||||
env.On("getPathSeperator", nil).Return("/")
|
||||
env.On("homeDir", nil).Return("/usr/home")
|
||||
env.On("getcwd", nil).Return(pwd)
|
||||
env.On("getRuntimeGOOS", nil).Return("")
|
||||
args := &args{
|
||||
PSWD: &pwd,
|
||||
}
|
||||
|
@ -536,6 +608,7 @@ func testWritePathInfo(home, pwd, pathSeparator string) string {
|
|||
env.On("homeDir", nil).Return(home)
|
||||
env.On("getPathSeperator", nil).Return(pathSeparator)
|
||||
env.On("getcwd", nil).Return(pwd)
|
||||
env.On("getRuntimeGOOS", nil).Return("")
|
||||
args := &args{
|
||||
PSWD: &pwd,
|
||||
}
|
||||
|
@ -635,6 +708,7 @@ func TestGetPwd(t *testing.T) {
|
|||
env.On("getPathSeperator", nil).Return("/")
|
||||
env.On("homeDir", nil).Return("/usr/home")
|
||||
env.On("getcwd", nil).Return(tc.Pwd)
|
||||
env.On("getRuntimeGOOS", nil).Return("")
|
||||
args := &args{
|
||||
PSWD: &tc.Pswd,
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue