mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2024-11-10 13:04:04 -08:00
feat: flexible matching for include/exclude folders
This commit is contained in:
parent
b2515650c1
commit
7e4865779a
|
@ -293,8 +293,9 @@ will not be rendered when in one of the excluded locations.
|
|||
]
|
||||
```
|
||||
|
||||
You can also specify a [regular expression][regex] to create folder wildcards.
|
||||
In the sample below, any folders inside the `/Users/posh/Projects` path will be matched.
|
||||
The strings specified in these properties are evaluated as [regular expressions][regex]. You
|
||||
can use any valid regular expression construct, but the regular expression must match the entire directory
|
||||
name. The following will match `/Users/posh/Projects/Foo` but not `/home/Users/posh/Projects/Foo`.
|
||||
|
||||
```json
|
||||
"include_folders": [
|
||||
|
@ -313,16 +314,17 @@ You can also combine these properties:
|
|||
]
|
||||
```
|
||||
|
||||
Note for Windows users: Windows directory separators should be specified as 4 backslashes.
|
||||
##### Notes
|
||||
|
||||
```json
|
||||
"include_folders": [
|
||||
"C:\\\\Projects.*"
|
||||
],
|
||||
"exclude_folders": [
|
||||
"C:\\\\Projects\\\\secret-project.*"
|
||||
]
|
||||
```
|
||||
- Oh My Posh will accept both `/` and `\` as path separators for a folder and will match regardless of which
|
||||
is used by the current operating system.
|
||||
- Because the strings are evaluated as regular expressions, if you want to use a `\` in a Windows
|
||||
directory name, you need to specify it as `\\\\`.
|
||||
- The character `~` at the start of a specified folder will match the user's home directory.
|
||||
- The comparison 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.
|
||||
|
||||
### Colors
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package main
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -176,9 +177,20 @@ func (segment *Segment) cwdExcluded(cwd string) bool {
|
|||
}
|
||||
|
||||
func (segment *Segment) cwdMatchesOneOf(cwd string, regexes []string) bool {
|
||||
normalizedCwd := strings.ReplaceAll(cwd, "\\", "/")
|
||||
normalizedHomeDir := strings.ReplaceAll(segment.env.homeDir(), "\\", "/")
|
||||
|
||||
for _, element := range regexes {
|
||||
pattern := fmt.Sprintf("^%s$", element)
|
||||
matched := matchString(pattern, cwd)
|
||||
normalizedElement := strings.ReplaceAll(element, "\\\\", "/")
|
||||
if strings.HasPrefix(normalizedElement, "~") {
|
||||
normalizedElement = normalizedHomeDir + normalizedElement[1:]
|
||||
}
|
||||
pattern := fmt.Sprintf("^%s$", normalizedElement)
|
||||
goos := segment.env.getRuntimeGOOS()
|
||||
if goos == windowsPlatform || goos == darwinPlatform {
|
||||
pattern = "(?i)" + pattern
|
||||
}
|
||||
matched := matchString(pattern, normalizedCwd)
|
||||
if matched {
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -81,11 +81,15 @@ func TestShouldIncludeFolder(t *testing.T) {
|
|||
{Case: "Include Mismatch / Exclude Mismatch", IncludeFolders: []string{"zProjects.*"}, ExcludeFolders: []string{"Projects/nope"}, Expected: false},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
env := new(MockedEnvironment)
|
||||
env.On("getRuntimeGOOS", nil).Return(linuxPlatform)
|
||||
env.On("homeDir", nil).Return("")
|
||||
segment := &Segment{
|
||||
Properties: map[Property]interface{}{
|
||||
IncludeFolders: tc.IncludeFolders,
|
||||
ExcludeFolders: tc.ExcludeFolders,
|
||||
},
|
||||
env: env,
|
||||
}
|
||||
got := segment.shouldIncludeFolder(cwd)
|
||||
assert.Equal(t, tc.Expected, got, tc.Case)
|
||||
|
@ -93,10 +97,14 @@ func TestShouldIncludeFolder(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestShouldIncludeFolderRegexInverted(t *testing.T) {
|
||||
env := new(MockedEnvironment)
|
||||
env.On("getRuntimeGOOS", nil).Return(linuxPlatform)
|
||||
env.On("homeDir", nil).Return("")
|
||||
segment := &Segment{
|
||||
Properties: map[Property]interface{}{
|
||||
ExcludeFolders: []string{"(?!Projects[\\/]).*"},
|
||||
},
|
||||
env: env,
|
||||
}
|
||||
// detect panic(thrown by MustCompile)
|
||||
defer func() {
|
||||
|
@ -109,10 +117,14 @@ func TestShouldIncludeFolderRegexInverted(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestShouldIncludeFolderRegexInvertedNonEscaped(t *testing.T) {
|
||||
env := new(MockedEnvironment)
|
||||
env.On("getRuntimeGOOS", nil).Return(linuxPlatform)
|
||||
env.On("homeDir", nil).Return("")
|
||||
segment := &Segment{
|
||||
Properties: map[Property]interface{}{
|
||||
ExcludeFolders: []string{"(?!Projects/).*"},
|
||||
},
|
||||
env: env,
|
||||
}
|
||||
// detect panic(thrown by MustCompile)
|
||||
defer func() {
|
||||
|
@ -196,3 +208,39 @@ func TestGetColors(t *testing.T) {
|
|||
assert.Equal(t, tc.ExpectedColor, color, tc.Case)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCwdMatchesOneOf(t *testing.T) {
|
||||
cases := []struct {
|
||||
GOOS string
|
||||
HomeDir string
|
||||
Cwd string
|
||||
Pattern string
|
||||
Expected bool
|
||||
}{
|
||||
{GOOS: linuxPlatform, HomeDir: "/home/bill", Cwd: "/home/bill", Pattern: "/home/bill", Expected: true},
|
||||
{GOOS: linuxPlatform, HomeDir: "/home/bill", Cwd: "/home/bill/foo", Pattern: "~/foo", Expected: true},
|
||||
{GOOS: linuxPlatform, HomeDir: "/home/bill", Cwd: "/home/bill/foo", Pattern: "~/Foo", Expected: false},
|
||||
{GOOS: linuxPlatform, HomeDir: "/home/bill", Cwd: "/home/bill/foo", Pattern: "~\\\\foo", Expected: true},
|
||||
{GOOS: linuxPlatform, HomeDir: "/home/bill", Cwd: "/home/bill/foo/bar", Pattern: "~/fo.*", Expected: true},
|
||||
{GOOS: linuxPlatform, HomeDir: "/home/bill", Cwd: "/home/bill/foo", Pattern: "~/fo\\w", Expected: true},
|
||||
{GOOS: windowsPlatform, HomeDir: "C:\\Users\\Bill", Cwd: "C:\\Users\\Bill", Pattern: "C:\\\\Users\\\\Bill", Expected: true},
|
||||
{GOOS: windowsPlatform, HomeDir: "C:\\Users\\Bill", Cwd: "C:\\Users\\Bill", Pattern: "C:/Users/Bill", Expected: true},
|
||||
{GOOS: windowsPlatform, HomeDir: "C:\\Users\\Bill", Cwd: "C:\\Users\\Bill", Pattern: "c:/users/bill", Expected: true},
|
||||
{GOOS: windowsPlatform, HomeDir: "C:\\Users\\Bill", Cwd: "C:\\Users\\Bill", Pattern: "~", Expected: true},
|
||||
{GOOS: windowsPlatform, HomeDir: "C:\\Users\\Bill", Cwd: "C:\\Users\\Bill\\Foo", Pattern: "~/Foo", Expected: true},
|
||||
{GOOS: windowsPlatform, HomeDir: "C:\\Users\\Bill", Cwd: "C:\\Users\\Bill\\Foo", Pattern: "~/foo", Expected: true},
|
||||
{GOOS: windowsPlatform, HomeDir: "C:\\Users\\Bill", Cwd: "C:\\Users\\Bill\\Foo\\Bar", Pattern: "~/fo.*", Expected: true},
|
||||
{GOOS: windowsPlatform, HomeDir: "C:\\Users\\Bill", Cwd: "C:\\Users\\Bill\\Foo", Pattern: "~/fo\\w", Expected: true},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
env := new(MockedEnvironment)
|
||||
env.On("getRuntimeGOOS", nil).Return(tc.GOOS)
|
||||
env.On("homeDir", nil).Return(tc.HomeDir)
|
||||
segment := &Segment{
|
||||
env: env,
|
||||
}
|
||||
got := segment.cwdMatchesOneOf(tc.Cwd, []string{tc.Pattern})
|
||||
assert.Equal(t, tc.Expected, got)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue