From e92061428bfc7c945ce4cb47c7b293e839f8f65f Mon Sep 17 00:00:00 2001 From: Jan De Dobbeleer Date: Sun, 6 Dec 2020 19:34:42 +0100 Subject: [PATCH] feat: use regex for ignore folders resolves #187 --- docs/docs/configuration.md | 33 ++++++++++++++++++++----- properties.go | 46 ++++++++++++++++++++--------------- segment.go | 12 ++++++--- segment_test.go | 50 +++++++++++++++++++++++++++++++++++--- 4 files changed, 108 insertions(+), 33 deletions(-) diff --git a/docs/docs/configuration.md b/docs/docs/configuration.md index a4834336..8fe9a4ab 100644 --- a/docs/docs/configuration.md +++ b/docs/docs/configuration.md @@ -198,10 +198,30 @@ segment's configuration will not render it when in that location. The engine wil ] ``` +You can also specify a [regular expression][regex] to create wildcards to exclude certain folders. +In the sample below, folders inside the `/Users/posh/Projects` path will not show the segment. + +```json +"ignore_folders": [ + "/Users/posh/Projects/.*" +] +``` + +Want to only show the segment inside certain folders? Use the [negative lookahead][regex-nl] to only match folders +in a certain path. Everything else will be ignored. In the sample below, only folders inside the +`/Users/posh/Projects/` path will show the segment. + +```json +"ignore_folders": [ + "(?!/Users/posh/Projects/).*" +] +``` + #### Colors -You have the ability to override the foreground and/or background color for text in any property that accepts it. The syntax is custom but -should be rather straighforward: `<#ffffff,#000000>this is white with black background <#FF479C>but this is pink`. Anything between the color start +You have the ability to override the foreground and/or background color for text in any property that accepts it. +The syntax is custom but should be rather straighforward: +`<#ffffff,#000000>this is white with black background <#FF479C>but this is pink`. Anything between the color start `<#FF479C>` and end `` will be colored accordingly. For example, if you want `prefix` to print a colored bracket which isn't the same as the segment's `foreground`, you can @@ -224,12 +244,11 @@ To change *only* the background color, just omit the first color from the above ``` Oh my Posh mainly supports three different color types being -* Typical [hex colors][hexcolors] (for example `#CB4B16`). -* The `transparent` keyword which can be used to create either a transparent foreground override +- Typical [hex colors][hexcolors] (for example `#CB4B16`). +- The `transparent` keyword which can be used to create either a transparent foreground override or transparent background color using the segement's foreground property. - -* 16 [ANSI color names][ansicolors]. +- 16 [ANSI color names][ansicolors]. These include 8 basic ANSI colors and `default`: @@ -329,3 +348,5 @@ Oh my Posh mainly supports three different color types being [hexcolors]: https://htmlcolorcodes.com/color-chart/material-design-color-chart/ [ansicolors]: https://htmlcolorcodes.com/color-chart/material-design-color-chart/ [fg]: /docs/configure#foreground +[regex]: https://www.regular-expressions.info/tutorial.html +[regex-nl]: https://www.regular-expressions.info/lookaround.html diff --git a/properties.go b/properties.go index 021b7652..5f0ab41d 100644 --- a/properties.go +++ b/properties.go @@ -97,31 +97,37 @@ func (p *properties) getKeyValueMap(property Property, defaultValue map[string]s return keyValues } -func parseStringArray(value interface{}) []string { - expectedValue, ok := value.([]interface{}) - if !ok { +func parseStringArray(param interface{}) []string { + switch v := param.(type) { + default: return []string{} + case []interface{}: + list := make([]string, len(v)) + for i, v := range v { + list[i] = fmt.Sprint(v) + } + return list + case []string: + return v } - list := make([]string, len(expectedValue)) - for i, v := range expectedValue { - list[i] = fmt.Sprint(v) - } - return list } -func parseKeyValueArray(value interface{}) map[string]string { - locations, ok := value.([]interface{}) - if !ok { +func parseKeyValueArray(param interface{}) map[string]string { + switch v := param.(type) { + default: return map[string]string{} - } - keyValueArray := make(map[string]string) - for _, s := range locations { - l := parseStringArray(s) - if len(l) == 2 { - key := l[0] - val := l[1] - keyValueArray[key] = val + case []interface{}: + keyValueArray := make(map[string]string) + for _, s := range v { + l := parseStringArray(s) + if len(l) == 2 { + key := l[0] + val := l[1] + keyValueArray[key] = val + } } + return keyValueArray + case map[string]string: + return v } - return keyValueArray } diff --git a/segment.go b/segment.go index 0d11fe28..8114ffdc 100644 --- a/segment.go +++ b/segment.go @@ -2,6 +2,8 @@ package main import ( "errors" + "fmt" + "regexp" "time" ) @@ -105,11 +107,13 @@ func (segment *Segment) getValue(property Property, defaultValue string) string return defaultValue } -func (segment *Segment) hasValue(property Property, match string) bool { - if value, ok := segment.Properties[property]; ok { +func (segment *Segment) shouldIgnoreFolder(cwd string) bool { + if value, ok := segment.Properties[IgnoreFolders]; ok { list := parseStringArray(value) for _, element := range list { - if element == match { + pattern := fmt.Sprintf("^%s$", element) + matched, err := regexp.MatchString(pattern, cwd) + if err == nil && matched { return true } } @@ -159,7 +163,7 @@ func (segment *Segment) mapSegmentWithWriter(env environmentInfo) error { func (segment *Segment) setStringValue(env environmentInfo, cwd string, debug bool) { err := segment.mapSegmentWithWriter(env) - if err != nil || segment.hasValue(IgnoreFolders, cwd) { + if err != nil || segment.shouldIgnoreFolder(cwd) { return } // add timing only in debug diff --git a/segment_test.go b/segment_test.go index c7d43671..da3cf752 100644 --- a/segment_test.go +++ b/segment_test.go @@ -7,6 +7,10 @@ import ( "github.com/stretchr/testify/assert" ) +const ( + cwd = "Projects/oh-my-posh3" +) + func TestMapSegmentWriterCanMap(t *testing.T) { sc := &Segment{ Type: Session, @@ -41,7 +45,7 @@ func TestParseTestSettings(t *testing.T) { "prefix": " \uE5FF ", "style": "folder", "ignore_folders": [ - "go-my-psh" + "/super/secret/project" ] } } @@ -49,7 +53,47 @@ func TestParseTestSettings(t *testing.T) { segment := &Segment{} err := json.Unmarshal([]byte(segmentJSON), segment) assert.NoError(t, err) - expected := "go-my-psh" - got := segment.hasValue(IgnoreFolders, expected) + cwd := "/super/secret/project" + got := segment.shouldIgnoreFolder(cwd) assert.True(t, got) } + +func TestShouldIgnoreFolderRegex(t *testing.T) { + segment := &Segment{ + Properties: map[Property]interface{}{ + IgnoreFolders: []string{"Projects[\\/].*"}, + }, + } + got := segment.shouldIgnoreFolder(cwd) + assert.True(t, got) +} + +func TestShouldIgnoreFolderRegexNonEscaped(t *testing.T) { + segment := &Segment{ + Properties: map[Property]interface{}{ + IgnoreFolders: []string{"Projects/.*"}, + }, + } + got := segment.shouldIgnoreFolder(cwd) + assert.True(t, got) +} + +func TestShouldIgnoreFolderRegexInverted(t *testing.T) { + segment := &Segment{ + Properties: map[Property]interface{}{ + IgnoreFolders: []string{"(?!Projects[\\/]).*"}, + }, + } + got := segment.shouldIgnoreFolder(cwd) + assert.False(t, got) +} + +func TestShouldIgnoreFolderRegexInvertedNonEscaped(t *testing.T) { + segment := &Segment{ + Properties: map[Property]interface{}{ + IgnoreFolders: []string{"(?!Projects/).*"}, + }, + } + got := segment.shouldIgnoreFolder(cwd) + assert.False(t, got) +}