Repository: JanDeDobbeleer/oh-my-posh
Pull request #5716 (2024-10-06 08:31:57)

feat(python): make folder fallback env names customizable
### 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

Add the possibilty to customize python virtualenvs name replaced by the parent folder name


Patch:
diff --git a/.all-contributorsrc b/.all-contributorsrc
index ccb4971f..fe5596ab 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -2796,6 +2796,15 @@
       "contributions": [
         "doc"
       ]
+    },
+    {
+      "login": "devxpain",
+      "name": "devxpain",
+      "avatar_url": "https://avatars.githubusercontent.com/u/170700110?v=4",
+      "profile": "https://github.com/devxpain",
+      "contributions": [
+        "doc"
+      ]
     }
   ],
   "contributorsPerLine": 7,
diff --git a/.github/workflows/build_code.yml b/.github/workflows/build_code.yml
index 5d5eb5a3..31a38568 100644
--- a/.github/workflows/build_code.yml
+++ b/.github/workflows/build_code.yml
@@ -28,7 +28,7 @@ jobs:
         args: build --clean --snapshot --skip=post-hooks --skip=before
         workdir: src
     - name: Archive production artifacts
-      uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874
+      uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882
       with:
         name: builds
         retention-days: 1
diff --git a/src/cli/enable.go b/src/cli/enable.go
index cdcf8e30..bf634883 100644
--- a/src/cli/enable.go
+++ b/src/cli/enable.go
@@ -3,6 +3,8 @@ package cli
 import (
 	"fmt"
 
+	"github.com/jandedobbeleer/oh-my-posh/src/cache"
+	"github.com/jandedobbeleer/oh-my-posh/src/config"
 	"github.com/jandedobbeleer/oh-my-posh/src/runtime"
 	"github.com/jandedobbeleer/oh-my-posh/src/upgrade"
 
@@ -18,6 +20,7 @@ This command is used to %s one of the following features:
 - notice`
 	toggleArgs = []string{
 		"notice",
+		"autoupgrade",
 	}
 )
 
@@ -59,7 +62,14 @@ func toggleFeature(cmd *cobra.Command, feature string, enable bool) {
 			return
 		}
 
-		env.Cache().Set(upgrade.CACHEKEY, "disabled", -1)
+		env.Cache().Set(upgrade.CACHEKEY, "disabled", cache.INFINITE)
+	case "autoupgrade":
+		if enable {
+			env.Cache().Set(config.AUTOUPGRADE, "true", cache.INFINITE)
+			return
+		}
+
+		env.Cache().Delete(config.AUTOUPGRADE)
 	default:
 		_ = cmd.Help()
 	}
diff --git a/src/config/config.go b/src/config/config.go
index 3f77b8e9..ab97edad 100644
--- a/src/config/config.go
+++ b/src/config/config.go
@@ -14,6 +14,8 @@ const (
 	YAML string = "yaml"
 	TOML string = "toml"
 
+	AUTOUPGRADE = "auto_upgrade"
+
 	Version = 2
 )
 
@@ -103,11 +105,16 @@ func (cfg *Config) Features() shell.Features {
 		feats = append(feats, shell.FTCSMarks)
 	}
 
-	if !cfg.AutoUpgrade && !cfg.DisableNotice {
+	autoUpgrade := cfg.AutoUpgrade
+	if _, OK := cfg.env.Cache().Get(AUTOUPGRADE); OK {
+		autoUpgrade = true
+	}
+
+	if !autoUpgrade && !cfg.DisableNotice {
 		feats = append(feats, shell.Notice)
 	}
 
-	if cfg.AutoUpgrade {
+	if autoUpgrade {
 		feats = append(feats, shell.Upgrade)
 	}
 
diff --git a/src/segments/python.go b/src/segments/python.go
index 1d9c8ffa..25b96dfd 100644
--- a/src/segments/python.go
+++ b/src/segments/python.go
@@ -22,6 +22,7 @@ const (
 	FetchVirtualEnv      properties.Property = "fetch_virtual_env"
 	UsePythonVersionFile properties.Property = "use_python_version_file"
 	FolderNameFallback   properties.Property = "folder_name_fallback"
+	DefaultVenvNames     properties.Property = "default_venv_names"
 )
 
 func (p *Python) Template() string {
@@ -81,10 +82,10 @@ func (p *Python) loadContext() {
 	}
 
 	folderNameFallback := p.language.props.GetBool(FolderNameFallback, true)
-	defaultVenvNames := []string{
+	defaultVenvNames := p.language.props.GetStringArray(DefaultVenvNames, []string{
 		".venv",
 		"venv",
-	}
+	})
 
 	var venv string
 	for _, venvVar := range venvVars {
diff --git a/src/upgrade/notice.go b/src/upgrade/notice.go
index a95a3a22..d4661106 100644
--- a/src/upgrade/notice.go
+++ b/src/upgrade/notice.go
@@ -38,7 +38,7 @@ const (
 A new release of Oh My Posh is available: %s → %s
 To upgrade, run: 'oh-my-posh upgrade'
 
-To enable automated upgrades, set 'auto_upgrade' to 'true' in your configuration.
+To enable automated upgrades, run: 'oh-my-posh enable autoupgrade'.
 `
 )
 
diff --git a/themes/schema.json b/themes/schema.json
index 95c05480..5d409438 100644
--- a/themes/schema.json
+++ b/themes/schema.json
@@ -2653,6 +2653,24 @@
                     "items": {
                       "type": "string"
                     }
+                  },
+                  "folder_name_fallback": {
+                    "type": "boolean",
+                    "title": "Folder Name Fallback",
+                    "description": "Replace virtual environment names in default_venv_names list with parent folder name",
+                    "default": "true"
+                  },
+                  "default_venv_names": {
+                    "type": "array",
+                    "title": "Default Venv Names",
+                    "description": "Names to replace when folder_name_fallback is true",
+                    "default": [
+                      ".venv",
+                      "venv"
+                    ],
+                    "items": {
+                      "type": "string"
+                    }
                   }
                 }
               }
diff --git a/website/docs/contributors.md b/website/docs/contributors.md
index a5833d4f..c05be708 100644
--- a/website/docs/contributors.md
+++ b/website/docs/contributors.md
@@ -168,7 +168,7 @@ Thanks goes to these wonderful people ([emoji key][acek]):
       <td align="center" valign="top" width="14.28%"><a href="https://takiya.eu"><img src="https://avatars.githubusercontent.com/u/6952402?v=4?s=100" width="100px;" alt="Alex 'Avunia' Takiya"/><br /><sub><b>Alex 'Avunia' Takiya</b></sub></a><br /><a href="https://github.com/JanDeDobbeleer/oh-my-posh/commits?author=atakiya" title="Code">💻</a></td>
       <td align="center" valign="top" width="14.28%"><a href="https://github.com/kenmorse"><img src="https://avatars.githubusercontent.com/u/63734484?v=4?s=100" width="100px;" alt="kenmorse"/><br /><sub><b>kenmorse</b></sub></a><br /><a href="https://github.com/JanDeDobbeleer/oh-my-posh/commits?author=kenmorse" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="14.28%"><a href="https://github.com/xadozuk"><img src="https://avatars.githubusercontent.com/u/780423?v=4?s=100" width="100px;" alt="xadozuk"/><br /><sub><b>xadozuk</b></sub></a><br /><a href="https://github.com/JanDeDobbeleer/oh-my-posh/commits?author=xadozuk" title="Code">💻</a></td>
-      <td align="center" valign="top" width="14.28%"><a href="https://bittu.eu.org"><img src="https://avatars.githubusercontent.com/u/83997633?v=4?s=100" width="100px;" alt="Begula"/><br /><sub><b>Begula</b></sub></a><br /><a href="#design-vedantmgoyal2009" title="Design">🎨</a> <a href="https://github.com/JanDeDobbeleer/oh-my-posh/commits?author=vedantmgoyal2009" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://bittu.eu.org"><img src="https://avatars.githubusercontent.com/u/83997633?v=4?s=100" width="100px;" alt="Vedant"/><br /><sub><b>Vedant</b></sub></a><br /><a href="#design-vedantmgoyal9" title="Design">🎨</a> <a href="https://github.com/JanDeDobbeleer/oh-my-posh/commits?author=vedantmgoyal9" title="Code">💻</a></td>
       <td align="center" valign="top" width="14.28%"><a href="https://github.com/lewis-yeung"><img src="https://avatars.githubusercontent.com/u/83903009?v=4?s=100" width="100px;" alt="L. Yeung"/><br /><sub><b>L. Yeung</b></sub></a><br /><a href="https://github.com/JanDeDobbeleer/oh-my-posh/commits?author=lewis-yeung" title="Code">💻</a> <a href="https://github.com/JanDeDobbeleer/oh-my-posh/commits?author=lewis-yeung" title="Documentation">📖</a> <a href="#design-lewis-yeung" title="Design">🎨</a></td>
       <td align="center" valign="top" width="14.28%"><a href="https://github.com/antoson"><img src="https://avatars.githubusercontent.com/u/36371990?v=4?s=100" width="100px;" alt="Ondrej Antos"/><br /><sub><b>Ondrej Antos</b></sub></a><br /><a href="https://github.com/JanDeDobbeleer/oh-my-posh/commits?author=antoson" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="14.28%"><a href="https://github.com/Bahnschrift"><img src="https://avatars.githubusercontent.com/u/31170809?v=4?s=100" width="100px;" alt="Bahnschrift"/><br /><sub><b>Bahnschrift</b></sub></a><br /><a href="https://github.com/JanDeDobbeleer/oh-my-posh/commits?author=Bahnschrift" title="Documentation">📖</a></td>
@@ -394,6 +394,7 @@ Thanks goes to these wonderful people ([emoji key][acek]):
       <td align="center" valign="top" width="14.28%"><a href="https://github.com/garysassano"><img src="https://avatars.githubusercontent.com/u/10464497?v=4?s=100" width="100px;" alt="Gary Sassano"/><br /><sub><b>Gary Sassano</b></sub></a><br /><a href="#design-garysassano" title="Design">🎨</a></td>
       <td align="center" valign="top" width="14.28%"><a href="https://github.com/ilaumjd"><img src="https://avatars.githubusercontent.com/u/16514431?v=4?s=100" width="100px;" alt="Ilham AM"/><br /><sub><b>Ilham AM</b></sub></a><br /><a href="https://github.com/JanDeDobbeleer/oh-my-posh/commits?author=ilaumjd" title="Code">💻</a> <a href="https://github.com/JanDeDobbeleer/oh-my-posh/commits?author=ilaumjd" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="14.28%"><a href="https://trajano.net/"><img src="https://avatars.githubusercontent.com/u/110627?v=4?s=100" width="100px;" alt="Archimedes Trajano"/><br /><sub><b>Archimedes Trajano</b></sub></a><br /><a href="https://github.com/JanDeDobbeleer/oh-my-posh/commits?author=trajano" title="Documentation">📖</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/devxpain"><img src="https://avatars.githubusercontent.com/u/170700110?v=4?s=100" width="100px;" alt="devxpain"/><br /><sub><b>devxpain</b></sub></a><br /><a href="https://github.com/JanDeDobbeleer/oh-my-posh/commits?author=devxpain" title="Documentation">📖</a></td>
     </tr>
   </tbody>
 </table>
diff --git a/website/docs/faq.mdx b/website/docs/faq.mdx
index e4b32b32..45d980a5 100644
--- a/website/docs/faq.mdx
+++ b/website/docs/faq.mdx
@@ -278,22 +278,23 @@ This is most likely caused by two Oh My Posh init lines in your `.zshrc`, remove
 ### Fish: Display current bind (Vim) mode
 
 By default, Oh My Posh will not re-render the prompt (i.e., generate a new prompt) until a new command is run, so you should
-call the `omp_repaint_prompt` function to do prompt re-rendering whenever `$fish_bind_mode` changes:
+export `$fish_bind_mode` to `FISH__BIND_MODE` and call the `omp_repaint_prompt` function to do prompt re-rendering when
+`$fish_bind_mode` changes:
 
 ```fish
 function rerender_on_bind_mode_change --on-variable fish_bind_mode
-    if test "$fish_bind_mode" != paste
+    if test "$fish_bind_mode" != paste -a "$fish_bind_mode" != "$FISH__BIND_MODE"
+        set -gx FISH__BIND_MODE $fish_bind_mode
         omp_repaint_prompt
     end
 end
 ```
 
-Then export the current bind mode in the `set_poshcontext` function. Note that scope shadowing must be disabled in order to
-access the `$fish_bind_mode` variable.
+Next, mask the `fish_default_mode_prompt` function to prevent it from echoing the current mode:
 
 ```fish
-function set_poshcontext --no-scope-shadowing
-  set --export FISH__BIND_MODE $fish_bind_mode
+function fish_default_mode_prompt --description "Display vi prompt mode"
+    # This function is masked and does nothing
 end
 ```
 
diff --git a/website/docs/segments/languages/python.mdx b/website/docs/segments/languages/python.mdx
index 59302983..ee6143cb 100644
--- a/website/docs/segments/languages/python.mdx
+++ b/website/docs/segments/languages/python.mdx
@@ -38,7 +38,8 @@ import Config from "@site/src/components/Config.js";
 | `extensions`           | `[]string` | `*.py, *.ipynb, pyproject.toml, venv.bak` | allows to override the default list of file extensions to validate                                                                                                                                                                   |
 | `folders`              | `[]string` |                                           | allows to override the list of folder names to validate                                                                                                                                                                              |
 | `cache_version`        | `boolean`  | `false`                                   | cache the executable's version or not                                                                                                                                                                                                |
-| `folder_name_fallback` | `boolean`  | `true`                                    | instead of `venv` or `.venv` (case sensitive), use the parent folder name as the virtual environment's name or not                                                                                                                   |
+| `folder_name_fallback` | `boolean`  | `true`                                    | instead of `default_venv_names` (case sensitive), use the parent folder name as the virtual environment's name or not                                                                                                                   |
+| `default_venv_names`       | `[]string` | `.venv, venv` | allows to override the list of environment's name replaced when `folder_name_fallback` is `true` |
 
 ## Template ([info][templates])
 


Test patch:
diff --git a/src/segments/python_test.go b/src/segments/python_test.go
index 48ef25fe..16066def 100644
--- a/src/segments/python_test.go
+++ b/src/segments/python_test.go
@@ -198,3 +198,48 @@ func TestPythonVirtualEnvIgnoreDefaultVenvNames(t *testing.T) {
 		assert.Equal(t, tc.Expected, python.Venv)
 	}
 }
+
+func TestPythonVirtualEnvIgnoreCustomVenvNames(t *testing.T) {
+	cases := []struct {
+		Expected           string
+		FolderNameFallback bool
+		DefaultVenvNames   []string
+		VirtualEnvName     string
+	}{
+		{
+			Expected:           "folder",
+			FolderNameFallback: true,
+			DefaultVenvNames:   []string{"env"},
+			VirtualEnvName:     "/path/to/folder/env",
+		},
+		{
+			Expected:           "venv",
+			FolderNameFallback: true,
+			DefaultVenvNames:   []string{"env"},
+			VirtualEnvName:     "/path/to/folder/venv",
+		},
+	}
+
+	for _, tc := range cases {
+		params := &mockedLanguageParams{}
+		env, props := getMockedLanguageEnv(params)
+
+		env.On("GOOS").Return("")
+		env.On("PathSeparator").Return("/")
+		env.On("CommandPath", testify_.Anything).Return("")
+		env.On("HasFilesInDir", testify_.Anything, "pyvenv.cfg").Return(false)
+		env.On("Getenv", "VIRTUAL_ENV").Return(tc.VirtualEnvName)
+		env.On("Getenv", "CONDA_ENV_PATH").Return("")
+		env.On("Getenv", "CONDA_DEFAULT_ENV").Return("")
+		env.On("Getenv", "PYENV_VERSION").Return("")
+		env.On("HasParentFilePath", ".python-version", false).Return(&runtime.FileInfo{}, errors.New("no match at root level"))
+
+		props[FolderNameFallback] = tc.FolderNameFallback
+		props[DefaultVenvNames] = tc.DefaultVenvNames
+
+		python := &Python{}
+		python.Init(props, env)
+		python.loadContext()
+		assert.Equal(t, tc.Expected, python.Venv)
+	}
+}