Repository: JanDeDobbeleer/oh-my-posh
Pull request #6209 (2025-03-01 16:13:02)

feat: next release
### 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).

<!---

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/.configurations/configuration.dsc.yaml b/.config/configuration.winget
similarity index 100%
rename from .configurations/configuration.dsc.yaml
rename to .config/configuration.winget
diff --git a/src/cli/init.go b/src/cli/init.go
index cc62d0db..d52b0461 100644
--- a/src/cli/init.go
+++ b/src/cli/init.go
@@ -83,6 +83,7 @@ func runInit(sh string) {
 		Strict:    strict,
 		Debug:     debug,
 		SaveCache: true,
+		Init:      true,
 	}
 
 	env := &runtime.Terminal{}
diff --git a/src/config/segment_types.go b/src/config/segment_types.go
index 63df09bd..6b4dfedb 100644
--- a/src/config/segment_types.go
+++ b/src/config/segment_types.go
@@ -129,6 +129,8 @@ const (
 	NBGV SegmentType = "nbgv"
 	// NIGHTSCOUT is an open source diabetes system
 	NIGHTSCOUT SegmentType = "nightscout"
+	// NIM writes the active nim version
+	NIM SegmentType = "nim"
 	// NIXSHELL writes the active nix shell details
 	NIXSHELL SegmentType = "nix-shell"
 	// NODE writes which node version is currently active
@@ -211,6 +213,8 @@ const (
 	UNITY SegmentType = "unity"
 	// UPGRADE lets you know if you can upgrade Oh My Posh
 	UPGRADE SegmentType = "upgrade"
+	// V writes the active vlang version
+	V SegmentType = "v"
 	// VALA writes the active vala version
 	VALA SegmentType = "vala"
 	// WAKATIME writes tracked time spend in dev editors
@@ -283,6 +287,7 @@ var Segments = map[SegmentType]func() SegmentWriter{
 	NBGV:            func() SegmentWriter { return &segments.Nbgv{} },
 	NIGHTSCOUT:      func() SegmentWriter { return &segments.Nightscout{} },
 	NIXSHELL:        func() SegmentWriter { return &segments.NixShell{} },
+	NIM:             func() SegmentWriter { return &segments.Nim{} },
 	NODE:            func() SegmentWriter { return &segments.Node{} },
 	NPM:             func() SegmentWriter { return &segments.Npm{} },
 	NX:              func() SegmentWriter { return &segments.Nx{} },
@@ -323,6 +328,7 @@ var Segments = map[SegmentType]func() SegmentWriter{
 	UMBRACO:         func() SegmentWriter { return &segments.Umbraco{} },
 	UNITY:           func() SegmentWriter { return &segments.Unity{} },
 	UPGRADE:         func() SegmentWriter { return &segments.Upgrade{} },
+	V:               func() SegmentWriter { return &segments.V{} },
 	VALA:            func() SegmentWriter { return &segments.Vala{} },
 	WAKATIME:        func() SegmentWriter { return &segments.Wakatime{} },
 	WINREG:          func() SegmentWriter { return &segments.WindowsRegistry{} },
diff --git a/src/segments/golang.go b/src/segments/golang.go
index 88ad935c..2cc6d944 100644
--- a/src/segments/golang.go
+++ b/src/segments/golang.go
@@ -2,7 +2,7 @@ package segments
 
 import (
 	"github.com/jandedobbeleer/oh-my-posh/src/properties"
-
+	"github.com/jandedobbeleer/oh-my-posh/src/regex"
 	"golang.org/x/mod/modfile"
 )
 
@@ -11,7 +11,8 @@ type Golang struct {
 }
 
 const (
-	ParseModFile properties.Property = "parse_mod_file"
+	ParseModFile  properties.Property = "parse_mod_file"
+	ParseWorkFile properties.Property = "parse_work_file"
 )
 
 func (g *Golang) Template() string {
@@ -19,7 +20,7 @@ func (g *Golang) Template() string {
 }
 
 func (g *Golang) Enabled() bool {
-	g.extensions = []string{"*.go", "go.mod"}
+	g.extensions = []string{"*.go", "go.mod", "go.sum", "go.work", "go.work.sum"}
 	g.commands = []*cmd{
 		{
 			regex:      `(?P<version>((?P<major>[0-9]+).(?P<minor>[0-9]+)(.(?P<patch>[0-9]+))?))`,
@@ -36,14 +37,26 @@ func (g *Golang) Enabled() bool {
 	return g.language.Enabled()
 }
 
+// getVersion returns the version of the Go language
+// It first checks if the go.mod file is present and if it is, it parses the file to get the version
+// If the go.mod file is not present, it checks if the go.work file is present and if it is, it parses the file to get the version
+// If neither file is present, it returns an empty string
 func (g *Golang) getVersion() (string, error) {
-	if !g.props.GetBool(ParseModFile, false) {
-		return "", nil
+	if g.props.GetBool(ParseModFile, false) {
+		return g.parseModFile()
+	}
+
+	if g.props.GetBool(ParseWorkFile, false) {
+		return g.parseWorkFile()
 	}
 
+	return "", nil
+}
+
+func (g *Golang) parseModFile() (string, error) {
 	gomod, err := g.language.env.HasParentFilePath("go.mod", false)
 	if err != nil {
-		return "", nil
+		return "", err
 	}
 
 	contents := g.language.env.FileContent(gomod.Path)
@@ -52,5 +65,26 @@ func (g *Golang) getVersion() (string, error) {
 		return "", err
 	}
 
-	return file.Go.Version, nil
+	if file.Go.Version != "" {
+		return file.Go.Version, nil
+	}
+
+	// ignore when no version is found in go.mod file
+	return "", nil
+}
+
+func (g *Golang) parseWorkFile() (string, error) {
+	goWork, err := g.language.env.HasParentFilePath("go.work", false)
+	if err != nil {
+		return "", err
+	}
+
+	contents := g.language.env.FileContent(goWork.Path)
+	version := regex.FindStringMatch(`go (\d(\.\d{1,2})?(\.\d{1,2})?)`, contents, 1)
+	if len(version) > 0 {
+		return version, nil
+	}
+
+	// ignore when no version is found in go.work file
+	return "", nil
 }
diff --git a/src/segments/nim.go b/src/segments/nim.go
new file mode 100644
index 00000000..abaf2a65
--- /dev/null
+++ b/src/segments/nim.go
@@ -0,0 +1,22 @@
+package segments
+
+type Nim struct {
+	language
+}
+
+func (n *Nim) Template() string {
+	return languageTemplate
+}
+
+func (n *Nim) Enabled() bool {
+	n.extensions = []string{"*.nim", "*.nims"}
+
+	n.commands = []*cmd{
+		{
+			executable: "nim",
+			args:       []string{"--version"},
+			regex:      `Nim Compiler Version (?P<version>(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+))`,
+		},
+	}
+	return n.language.Enabled()
+}
diff --git a/src/segments/owm.go b/src/segments/owm.go
index a5ab3a55..692bdb78 100644
--- a/src/segments/owm.go
+++ b/src/segments/owm.go
@@ -32,8 +32,10 @@ const (
 	CacheKeyResponse string = "owm_response"
 	// CacheKeyURL key used when caching the url responsible for the response
 	CacheKeyURL string = "owm_url"
-
-	PoshOWMAPIKey = "POSH_OWM_API_KEY"
+	// Environmental variable to dynamically set the Open Map API key
+	OWMAPIKey string = "POSH_OWM_API_KEY"
+	// Environmental variable to dynamically set the location string
+	OWMLocationKey string = "POSH_OWM_LOCATION"
 )
 
 type weather struct {
@@ -68,18 +70,22 @@ func (d *Owm) Template() string {
 func (d *Owm) getResult() (*owmDataResponse, error) {
 	response := new(owmDataResponse)
 
-	apikey := properties.OneOf(d.props, ".", APIKey, "apiKey")
+	apikey := properties.OneOf(d.props, d.env.Getenv(OWMAPIKey), APIKey, "apiKey")
 	if len(apikey) == 0 {
-		apikey = d.env.Getenv(PoshOWMAPIKey)
+		apikey = "."
 	}
 
-	location := d.props.GetString(Location, "De Bilt,NL")
-	location = url.QueryEscape(location)
+	if len(apikey) == 0 {
+		return nil, errors.New("no api key found")
+	}
 
-	if len(apikey) == 0 || len(location) == 0 {
-		return nil, errors.New("no api key or location found")
+	location := d.props.GetString(Location, d.env.Getenv(OWMLocationKey))
+	if len(location) == 0 {
+		return nil, errors.New("no location found")
 	}
 
+	location = url.QueryEscape(location)
+
 	units := d.props.GetString(Units, "standard")
 	httpTimeout := d.props.GetInt(properties.HTTPTimeout, properties.DefaultHTTPTimeout)
 
diff --git a/src/segments/v.go b/src/segments/v.go
new file mode 100644
index 00000000..8e6b828f
--- /dev/null
+++ b/src/segments/v.go
@@ -0,0 +1,22 @@
+package segments
+
+type V struct {
+	language
+}
+
+func (v *V) Template() string {
+	return languageTemplate
+}
+
+func (v *V) Enabled() bool {
+	v.extensions = []string{"*.v"}
+
+	v.commands = []*cmd{
+		{
+			executable: "v",
+			args:       []string{"--version"},
+			regex:      `V (?P<version>(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)) [a-f0-9]+`,
+		},
+	}
+	return v.language.Enabled()
+}
diff --git a/themes/1_shell.omp.json b/themes/1_shell.omp.json
index dabeaa0f..f1a60307 100644
--- a/themes/1_shell.omp.json
+++ b/themes/1_shell.omp.json
@@ -69,7 +69,7 @@
         {
           "foreground": "#94ffa2",
           "style": "diamond",
-          "template": " <#ffffff>MEM:</> {{ round .PhysicalPercentUsed .Precision }}% ({{ (div ((sub .PhysicalTotalMemory .PhysicalFreeMemory)|float64) 1073741824.0) }}/{{ (div .PhysicalTotalMemory 1073741824.0) }}GB)",
+          "template": " <#ffffff>MEM:</> {{ round .PhysicalPercentUsed .Precision }}% ({{ (div ((sub .PhysicalTotalMemory .PhysicalAvailableMemory)|float64) 1073741824.0) }}/{{ (div .PhysicalTotalMemory 1073741824.0) }}GB)",
           "type": "sysinfo"
         }
       ],
diff --git a/themes/chips.omp.json b/themes/chips.omp.json
index 4f9e00e9..49942555 100644
--- a/themes/chips.omp.json
+++ b/themes/chips.omp.json
@@ -66,7 +66,7 @@
             "threshold": 1
           },
           "style": "diamond",
-          "template": "{{ if eq \"False\" (title (default \"False\" .Env.DISABLE_SEGMENT_PRIMARY_EXEC_TIME)) }}\uFA1E {{ .FormattedMs }}.{{ end }}",
+          "template": "{{ if eq \"False\" (title (default \"False\" .Env.DISABLE_SEGMENT_PRIMARY_EXEC_TIME)) }}\udb81\udd1f {{ .FormattedMs }}.{{ end }}",
           "trailing_diamond": "\uE0B4 ",
           "type": "executiontime"
         },
@@ -125,7 +125,7 @@
           "foreground": "p:c-badge-text",
           "leading_diamond": "\uE0B6",
           "style": "diamond",
-          "template": "{{ if eq \"True\" (title (default \"False\" .Env.DISABLE_SEGMENT_BATTERY)) }}{{ else }}{{ if not .Error }}{{ if eq \"Charging\" .State.String }}\uE315 {{ else if eq \"Discharging\" .State.String }}{{ else if eq \"Full\" .State.String }}~ {{ else }}? {{ end }}{{ if le .Percentage 15 }}\uF579{{ else if and (ge .Percentage 16) (le .Percentage 30) }}\uF57A{{ else if and (ge .Percentage 31) (le .Percentage 45) }}\uF57C{{ else if and (ge .Percentage 46) (le .Percentage 55)}}\uF57D{{ else if and (ge .Percentage 56) (le .Percentage 70) }}\uF57E{{ else if and (ge .Percentage 71) (le .Percentage 80) }}\uF580{{ else if and (ge .Percentage 81) (le .Percentage 95) }}\uF581{{ else }}\uF578{{ end }} {{ .Percentage }}%{{ else }}!{{ end }}{{ end }}",
+          "template": "{{ if eq \"True\" (title (default \"False\" .Env.DISABLE_SEGMENT_BATTERY)) }}{{ else }}{{ if not .Error }}{{ if eq \"Charging\" .State.String }}\uE315 {{ else if eq \"Discharging\" .State.String }}{{ else if eq \"Full\" .State.String }}~ {{ else }}? {{ end }}{{ if le .Percentage 15 }}\udb80\udc7a{{ else if and (ge .Percentage 16) (le .Percentage 30) }}\udb80\udc7b{{ else if and (ge .Percentage 31) (le .Percentage 45) }}\udb80\udc7d{{ else if and (ge .Percentage 46) (le .Percentage 55)}}\udb80\udc7e{{ else if and (ge .Percentage 56) (le .Percentage 70) }}\udb80\udc7f{{ else if and (ge .Percentage 71) (le .Percentage 80) }}\udb80\udc82{{ else if and (ge .Percentage 81) (le .Percentage 95) }}\udb80\udc82{{ else }}\udb80\udc79{{ end }} {{ .Percentage }}%{{ else }}!{{ end }}{{ end }}",
           "trailing_diamond": "\uE0B4",
           "type": "battery"
         }
@@ -287,7 +287,7 @@
     "c-wakatime-overtime": "#FF8A80"
   },
   "transient_prompt": {
-    "template": "{{ if eq \"False\" (title (default \"False\" .Env.DISABLE_SEGMENT_TRANSIENT)) }}<{{ if eq .Code 0 }}p:c-badge-return-success{{ else if or (eq .Code 1) (eq .Code 130) }}p:c-badge-return-fail-term{{ else }}p:c-badge-return-custom{{ end }}>\uE0B6</><p:c-badge-text,{{ if eq .Code 0 }}p:c-badge-return-success{{ else if or (eq .Code 1) (eq .Code 130) }}p:c-badge-return-fail-term{{ else }}p:c-badge-return-custom{{ end }}>\uF55D \uE0B1 {{ if .Segments.Executiontime.Ms }}{{ if eq \"False\" (title (default \"False\" .Env.DISABLE_SEGMENT_TRANSIENT_EXEC_TIME)) }}\uFA1E {{ .Segments.Executiontime.FormattedMs }} \uE621 {{ end }}{{ end }}<b>{{ if eq .Code 0 }}OK{{ else if eq .Code 1 }}FAIL{{ else if eq .Code 130 }}TERM{{ else }}Code{{ end }} ({{ .Code }})</b></><{{ if eq .Code 0 }}p:c-badge-return-success{{ else if or (eq .Code 1) (eq .Code 130) }}p:c-badge-return-fail-term{{ else }}p:c-badge-return-custom{{ end }}>\uE0B4</> {{ end }}\u276F "
+    "template": "{{ if eq \"False\" (title (default \"False\" .Env.DISABLE_SEGMENT_TRANSIENT)) }}<{{ if eq .Code 0 }}p:c-badge-return-success{{ else if or (eq .Code 1) (eq .Code 130) }}p:c-badge-return-fail-term{{ else }}p:c-badge-return-custom{{ end }}>\uE0B6</><p:c-badge-text,{{ if eq .Code 0 }}p:c-badge-return-success{{ else if or (eq .Code 1) (eq .Code 130) }}p:c-badge-return-fail-term{{ else }}p:c-badge-return-custom{{ end }}>\udb80\udc5e \uE0B1 {{ if .Segments.Executiontime.Ms }}{{ if eq \"False\" (title (default \"False\" .Env.DISABLE_SEGMENT_TRANSIENT_EXEC_TIME)) }}\udb81\udd1f {{ .Segments.Executiontime.FormattedMs }} \uE621 {{ end }}{{ end }}<b>{{ if eq .Code 0 }}OK{{ else if eq .Code 1 }}FAIL{{ else if eq .Code 130 }}TERM{{ else }}Code{{ end }} ({{ .Code }})</b></><{{ if eq .Code 0 }}p:c-badge-return-success{{ else if or (eq .Code 1) (eq .Code 130) }}p:c-badge-return-fail-term{{ else }}p:c-badge-return-custom{{ end }}>\uE0B4</> {{ end }}\u276F "
   },
   "secondary_prompt": {
     "background": "transparent",
diff --git a/themes/di4am0nd.omp.json b/themes/di4am0nd.omp.json
index a168d2cc..4d2a75d4 100644
--- a/themes/di4am0nd.omp.json
+++ b/themes/di4am0nd.omp.json
@@ -46,7 +46,7 @@
         {
           "foreground": "#85C980",
           "style": "diamond",
-          "template": "RAM:{{ (div ((sub .PhysicalTotalMemory .PhysicalFreeMemory)|float64) 1073741824.0) }}/{{ (div .PhysicalTotalMemory 1073741824.0) }}GB ",
+          "template": "RAM:{{ (div ((sub .PhysicalTotalMemory .PhysicalAvailableMemory)|float64) 1073741824.0) }}/{{ (div .PhysicalTotalMemory 1073741824.0) }}GB ",
           "trailing_diamond": " ",
           "type": "sysinfo"
         },
diff --git a/themes/easy-term.omp.json b/themes/easy-term.omp.json
index f3701f2c..f40bcebc 100644
--- a/themes/easy-term.omp.json
+++ b/themes/easy-term.omp.json
@@ -79,7 +79,7 @@
         {
           "foreground": "#81ff91",
           "style": "diamond",
-          "template": "<#cc7eda> \u007C </><#7eb8da>RAM:</> {{ (div ((sub .PhysicalTotalMemory .PhysicalFreeMemory)|float64) 1073741824.0) }}/{{ (div .PhysicalTotalMemory 1073741824.0) }}GB",
+          "template": "<#cc7eda> \u007C </><#7eb8da>RAM:</> {{ (div ((sub .PhysicalTotalMemory .PhysicalAvailableMemory)|float64) 1073741824.0) }}/{{ (div .PhysicalTotalMemory 1073741824.0) }}GB",
           "type": "sysinfo"
         },
         {
diff --git a/themes/if_tea.omp.json b/themes/if_tea.omp.json
index ce6c7e98..8240803b 100644
--- a/themes/if_tea.omp.json
+++ b/themes/if_tea.omp.json
@@ -44,7 +44,7 @@
           "background": "#00c7fc",
           "foreground": "#000000",
           "style": "diamond",
-          "template": "RAM: {{ (div ((sub .PhysicalTotalMemory .PhysicalFreeMemory)|float64) 1073741824.0) }}/{{ (div .PhysicalTotalMemory 1073741824.0) }}GB \ue266 ",
+          "template": "RAM: {{ (div ((sub .PhysicalTotalMemory .PhysicalAvailableMemory)|float64) 1073741824.0) }}/{{ (div .PhysicalTotalMemory 1073741824.0) }}GB \ue266 ",
           "trailing_diamond": "<transparent,#00c7fc>\ue0b2</>",
           "type": "sysinfo"
         },
diff --git a/themes/illusi0n.omp.json b/themes/illusi0n.omp.json
index eaefa161..e13d8371 100644
--- a/themes/illusi0n.omp.json
+++ b/themes/illusi0n.omp.json
@@ -12,7 +12,7 @@
         {
           "foreground": "#ff8800",
           "style": "diamond",
-          "template": "{{ (div ((sub .PhysicalTotalMemory .PhysicalFreeMemory)|float64) 1073741824.0) }}/{{ (div .PhysicalTotalMemory 1073741824.0) }}GB ",
+          "template": "{{ (div ((sub .PhysicalTotalMemory .PhysicalAvailableMemory)|float64) 1073741824.0) }}/{{ (div .PhysicalTotalMemory 1073741824.0) }}GB ",
           "type": "sysinfo"
         }
       ],
diff --git a/themes/schema.json b/themes/schema.json
index fe8e0881..3f43f5f4 100644
--- a/themes/schema.json
+++ b/themes/schema.json
@@ -345,6 +345,7 @@
             "mvn",
             "nbgv",
             "nightscout",
+            "nim",
             "nix-shell",
             "node",
             "npm",
@@ -386,6 +387,7 @@
             "umbraco",
             "unity",
             "upgrade",
+            "v",
             "vala",
             "wakatime",
             "winreg",
@@ -1568,6 +1570,12 @@
                     "description": "Parse go.mod file instead of calling out to go to improve performance.",
                     "default": false
                   },
+                  "parse_go_work_file": {
+                    "type": "boolean",
+                    "title": "Parse go.work file",
+                    "description": "Parse go.work file instead of calling out to go to improve performance.",
+                    "default": false
+                  },
                   "extensions": {
                     "type": "array",
                     "title": "Extensions",
@@ -4141,6 +4149,58 @@
             }
           }
         },
+        {
+          "if": {
+            "properties": {
+              "type": {
+                "const": "v"
+              }
+            }
+          },
+          "then": {
+            "title": "V Segment",
+            "description": "https://ohmyposh.dev/docs/segments/languages/v",
+            "properties": {
+              "properties": {
+                "properties": {
+                  "home_enabled": {
+                    "$ref": "#/definitions/home_enabled"
+                  },
+                  "fetch_version": {
+                    "$ref": "#/definitions/fetch_version"
+                  },
+                  "cache_duration": {
+                    "$ref": "#/definitions/cache_duration",
+                    "default": "none"
+                  },
+                  "display_mode": {
+                    "$ref": "#/definitions/display_mode"
+                  },
+                  "missing_command_text": {
+                    "$ref": "#/definitions/missing_command_text"
+                  },
+                  "version_url_template": {
+                    "$ref": "#/definitions/version_url_template"
+                  },
+                  "extensions": {
+                    "type": "array",
+                    "title": "Extensions",
+                    "description": "The extensions to look for when determining if the current directory is a V project",
+                    "default": [
+                      "*.v"
+                    ],
+                    "items": {
+                      "type": "string"
+                    }
+                  },
+                  "folders": {
+                    "$ref": "#/definitions/folders"
+                  }
+                }
+              }
+            }
+          }
+        },
         {
           "if": {
             "properties": {
@@ -4716,6 +4776,56 @@
             }
           }
         },
+        {
+          "if": {
+            "properties": {
+              "type": {
+                "const": "nim"
+              }
+            }
+          },
+          "then": {
+            "title": "Nim Segment",
+            "description": "https://ohmyposh.dev/docs/segments/languages/nim",
+            "properties": {
+              "properties": {
+                "properties": {
+                  "home_enabled": {
+                    "$ref": "#/definitions/home_enabled"
+                  },
+                  "fetch_version": {
+                    "$ref": "#/definitions/fetch_version"
+                  },
+                  "cache_duration": {
+                    "$ref": "#/definitions/cache_duration",
+                    "default": "none"
+                  },
+                  "display_mode": {
+                    "$ref": "#/definitions/display_mode"
+                  },
+                  "missing_command_text": {
+                    "$ref": "#/definitions/missing_command_text"
+                  },
+                  "version_url_template": {
+                    "$ref": "#/definitions/version_url_template"
+                  },
+                  "extensions": {
+                    "type": "array",
+                    "title": "Extensions",
+                    "description": "The extensions to look for when determining if a folder is a Nim workspace",
+                    "default": [
+                      "*.nim",
+                      "*.nims"
+                    ]
+                  },
+                  "folders": {
+                    "$ref": "#/definitions/folders"
+                  }
+                }
+              }
+            }
+          }
+        },
         {
           "if": {
             "properties": {
diff --git a/themes/tokyo.omp.json b/themes/tokyo.omp.json
index e7fc64b3..dbc0e110 100644
--- a/themes/tokyo.omp.json
+++ b/themes/tokyo.omp.json
@@ -31,7 +31,7 @@
         {
           "foreground": "#be9ddf",
           "style": "diamond",
-          "template": "[<#ffffff>\ue266</> RAM: {{ (div ((sub .PhysicalTotalMemory .PhysicalFreeMemory)|float64) 1073741824.0) }}/{{ (div .PhysicalTotalMemory 1073741824.0) }}GB]",
+          "template": "[<#ffffff>\ue266</> RAM: {{ (div ((sub .PhysicalTotalMemory .PhysicalAvailableMemory)|float64) 1073741824.0) }}/{{ (div .PhysicalTotalMemory 1073741824.0) }}GB]",
           "type": "sysinfo"
         },
         {
diff --git a/themes/wholespace.omp.json b/themes/wholespace.omp.json
index 11ef4ad5..1f00aee3 100644
--- a/themes/wholespace.omp.json
+++ b/themes/wholespace.omp.json
@@ -42,7 +42,7 @@
           "background": "#516BEB",
           "foreground": "#ffffff",
           "style": "diamond",
-          "template": "RAM: {{ (div ((sub .PhysicalTotalMemory .PhysicalFreeMemory)|float64) 1073741824.0) }}/{{ (div .PhysicalTotalMemory 1073741824.0) }}GB \ue266 ",
+          "template": "RAM: {{ (div ((sub .PhysicalTotalMemory .PhysicalAvailableMemory)|float64) 1073741824.0) }}/{{ (div .PhysicalTotalMemory 1073741824.0) }}GB \ue266 ",
           "trailing_diamond": "<transparent,#516BEB>\ue0b2</>",
           "type": "sysinfo"
         },
diff --git a/website/docs/contributing/started.mdx b/website/docs/contributing/started.mdx
index 66d9d052..542249e2 100644
--- a/website/docs/contributing/started.mdx
+++ b/website/docs/contributing/started.mdx
@@ -60,7 +60,7 @@ The project has a [winget] [configuration][winget-configuration] file available
 Navigate to the cloned repository and use winget to install the dependencies:
 
 ```powershell
-winget configure configurations/configuration.dsc.yaml
+winget configure .config/configuration.winget
 ```
 
 Done! Restart the terminal and you're ready to continue below.
@@ -164,6 +164,6 @@ With everything set up, you're ready to start making changes and create your fir
 [code]: https://code.visualstudio.com
 [delve]: https://github.com/go-delve/delve
 [docusaurus]: https://docusaurus.io
-[winget-configuration]: https://github.com/JanDeDobbeleer/oh-my-posh/blob/main/configurations/configuration.dsc.yaml
+[winget-configuration]: https://github.com/JanDeDobbeleer/oh-my-posh/blob/main/.config/configuration.winget
 [winget]: https://learn.microsoft.com/en-us/windows/package-manager/winget/
 [nodejs]: https://nodejs.org/en/download/
diff --git a/website/docs/installation/upgrade.mdx b/website/docs/installation/upgrade.mdx
index e434728a..3e086dd5 100644
--- a/website/docs/installation/upgrade.mdx
+++ b/website/docs/installation/upgrade.mdx
@@ -24,6 +24,11 @@ enabled by adding the following to your configuration.
   }}
 />
 
+:::info
+Auto upgrade will never upgrade major versions. This is to avoid introducing breaking changes
+without explicit user acknowledgement.
+:::
+
 | Name       |   Type    | Default | Description                                                                                                                                                                                                                |
 | ---------- | :-------: | :-----: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
 | `notice`   | `boolean` | `false` | enable displaying the upgrade notice on shell start, only checks based on `interval`                                                                                                                                       |
diff --git a/website/docs/segments/languages/golang.mdx b/website/docs/segments/languages/golang.mdx
index 89d9c0de..d3d3a6de 100644
--- a/website/docs/segments/languages/golang.mdx
+++ b/website/docs/segments/languages/golang.mdx
@@ -25,17 +25,18 @@ import Config from "@site/src/components/Config.js";
 
 ## Properties
 
-| Name                   |    Type    |    Default     | Description                                                                                                                                                                                                                          |
-| ---------------------- | :--------: | :------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| `home_enabled`         | `boolean`  |    `false`     | display the segment in the HOME folder or not                                                                                                                                                                                        |
-| `fetch_version`        | `boolean`  |     `true`     | fetch the golang version                                                                                                                                                                                                             |
-| `cache_duration`       |  `string`  |     `none`     | the duration for which the version will be cached. The duration is a string in the format `1h2m3s` and is parsed using the [time.ParseDuration] function from the Go standard library. To disable the cache, use `none`              |
-| `missing_command_text` |  `string`  |                | text to display when the command is missing                                                                                                                                                                                          |
-| `display_mode`         |  `string`  |   `context`    | <ul><li>`always`: the segment is always displayed</li><li>`files`: the segment is only displayed when file `extensions` listed are present</li><li>`context`: displays the segment when the environment or files is active</li></ul> |
-| `version_url_template` |  `string`  |                | a go [text/template][go-text-template] [template][templates] that creates the URL of the version info / release notes                                                                                                                |
-| `parse_mod_file`       | `boolean`  |    `false`     | parse the go.mod file instead of calling `go version`                                                                                                                                                                                |
-| `extensions`           | `[]string` | `*.go, go.mod` | allows to override the default list of file extensions to validate                                                                                                                                                                   |
-| `folders`              | `[]string` |                | allows to override the list of folder names to validate                                                                                                                                                                              |
+| Name                   |    Type    |                   Default                    | Description                                                                                                                                                                                                                          |
+| ---------------------- | :--------: | :------------------------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `home_enabled`         | `boolean`  |                   `false`                    | display the segment in the HOME folder or not                                                                                                                                                                                        |
+| `fetch_version`        | `boolean`  |                    `true`                    | fetch the golang version                                                                                                                                                                                                             |
+| `cache_duration`       |  `string`  |                    `none`                    | the duration for which the version will be cached. The duration is a string in the format `1h2m3s` and is parsed using the [time.ParseDuration] function from the Go standard library. To disable the cache, use `none`              |
+| `missing_command_text` |  `string`  |                                              | text to display when the command is missing                                                                                                                                                                                          |
+| `display_mode`         |  `string`  |                  `context`                   | <ul><li>`always`: the segment is always displayed</li><li>`files`: the segment is only displayed when file `extensions` listed are present</li><li>`context`: displays the segment when the environment or files is active</li></ul> |
+| `version_url_template` |  `string`  |                                              | a go [text/template][go-text-template] [template][templates] that creates the URL of the version info / release notes                                                                                                                |
+| `parse_mod_file`       | `boolean`  |                   `false`                    | parse the go.mod file instead of calling `go version`                                                                                                                                                                                |
+| `parse_go_work_file`   | `boolean`  |                   `false`                    | parse the go.work file instead of calling `go version`                                                                                                                                                                               |
+| `extensions`           | `[]string` | `*.go, go.mod, go.work, go.sum, go.work.sum` | allows to override the default list of file extensions to validate                                                                                                                                                                   |
+| `folders`              | `[]string` |                                              | allows to override the list of folder names to validate                                                                                                                                                                              |
 
 ## Template ([info][templates])
 
diff --git a/website/docs/segments/languages/nim.mdx b/website/docs/segments/languages/nim.mdx
new file mode 100644
index 00000000..7f986af2
--- /dev/null
+++ b/website/docs/segments/languages/nim.mdx
@@ -0,0 +1,61 @@
+---
+id: nim
+title: Nim 
+sidebar_label: Nim
+---
+
+## What
+
+Display the currently active Nim version.
+
+## Sample Configuration
+
+import Config from "@site/src/components/Config.js";
+
+<Config
+  data={{
+    type: "nim",
+    style: "powerline",
+    powerline_symbol: "\uE0B0",
+    foreground: "#193549",
+    background: "#f3d400",
+    template: " \ue841 {{ .Full }} ",
+  }}
+/>
+
+## Properties
+
+| Name                   |    Type    |               Default               | Description                                                                                                                                                                                                                          |
+| ---------------------- | :--------: | :---------------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `home_enabled`         | `boolean`  |               `false`               | display the segment in the HOME folder or not                                                                                                                                                                                        |
+| `fetch_version`        | `boolean`  |               `true`                | fetch the Nim version (`nim --version`)                                                                                                                                                                                              |
+| `cache_duration`       |  `string`  |               `none`                | the duration for which the version will be cached. The duration is a string in the format `1h2m3s` and is parsed using the [time.ParseDuration] function from the Go standard library. To disable the cache, use `none`              |
+| `missing_command_text` |  `string`  |                                     | text to display when the command is missing                                                                                                                                                                                          |
+| `display_mode`         |  `string`  |              `context`              | <ul><li>`always`: the segment is always displayed</li><li>`files`: the segment is only displayed when file `extensions` listed are present</li><li>`context`: displays the segment when the environment or files is active</li></ul> |
+| `version_url_template` |  `string`  |                                     | a go [text/template][go-text-template] [template][templates] that creates the URL of the version info / release notes                                                                                                                |
+| `extensions`           | `[]string` | `*.nim, *.nims`                     | allows to override the default list of file extensions to validate                                                                                                                                                                  |
+| `folders`              | `[]string` |                                     | allows to override the list of folder names to validate                                                                                                                                                                              |
+
+## Template ([info][templates])
+
+:::note default template
+
+```template
+{{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }}
+```
+
+:::
+
+### Properties
+
+| Name          | Type     | Description                                        |
+| ------------- | -------- | -------------------------------------------------- |
+| `.Full`       | `string` | the full version                                   |
+| `.Major`      | `string` | major number                                       |
+| `.Minor`      | `string` | minor number                                       |
+| `.Patch`      | `string` | patch number                                       |
+| `.Error`      | `string` | error encountered when fetching the version string |
+
+[go-text-template]: https://golang.org/pkg/text/template/
+[templates]: /docs/configuration/templates
+[time.ParseDuration]: https://golang.org/pkg/time/#ParseDuration
\ No newline at end of file
diff --git a/website/docs/segments/languages/v.mdx b/website/docs/segments/languages/v.mdx
new file mode 100644
index 00000000..da672897
--- /dev/null
+++ b/website/docs/segments/languages/v.mdx
@@ -0,0 +1,62 @@
+---
+id: v
+title: V
+sidebar_label: V
+---
+
+## What
+
+Display the currently active V version.
+
+## Sample Configuration
+
+import Config from "@site/src/components/Config.js";
+
+<Config
+  data={{
+    type: "vlang",
+    style: "powerline",
+    powerline_symbol: "\uE0B0",
+    foreground: "#193549",
+    background: "#4F87FF",
+    template: " \ue6ac {{ .Full }} ",
+  }}
+/>
+
+## Properties
+
+| Name                   |    Type    |               Default               | Description                                                                                                                                                                                                                          |
+| ---------------------- | :--------: | :---------------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `home_enabled`         | `boolean`  |               `false`               | display the segment in the HOME folder or not                                                                                                                                                                                        |
+| `fetch_version`        | `boolean`  |               `true`                | fetch the V version (`v --version`)                                                                                                                                                                                              |
+| `cache_duration`       |  `string`  |               `none`                | the duration for which the version will be cached. The duration is a string in the format `1h2m3s` and is parsed using the [time.ParseDuration] function from the Go standard library. To disable the cache, use `none`              |
+| `missing_command_text` |  `string`  |                                     | text to display when the command is missing                                                                                                                                                                                          |
+| `display_mode`         |  `string`  |              `context`              | <ul><li>`always`: the segment is always displayed</li><li>`files`: the segment is only displayed when file `extensions` listed are present</li><li>`context`: displays the segment when the environment or files is active</li></ul> |
+| `version_url_template` |  `string`  |                                     | a go [text/template][go-text-template] [template][templates] that creates the URL of the version info / release notes                                                                                                                |
+| `extensions`           | `[]string` | `*.v`                               | allows to override the default list of file extensions to validate                                                                                                                                                                  |
+| `folders`              | `[]string` |                                     | allows to override the list of folder names to validate                                                                                                                                                                              |
+
+## Template ([info][templates])
+
+:::note default template
+
+```template
+{{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }}
+```
+
+:::
+
+### Properties
+
+| Name          | Type     | Description                                        |
+| ------------- | -------- | -------------------------------------------------- |
+| `.Full`       | `string` | the full version (e.g., "0.4.9")                  |
+| `.Major`      | `string` | major number (e.g., "0")                          |
+| `.Minor`      | `string` | minor number (e.g., "4")                          |
+| `.Patch`      | `string` | patch number (e.g., "9")                          |
+| `.Commit`     | `string` | commit hash (e.g., "b487986")                     |
+| `.Error`      | `string` | error encountered when fetching the version string |
+
+[go-text-template]: https://golang.org/pkg/text/template/
+[templates]: /docs/configuration/templates
+[time.ParseDuration]: https://golang.org/pkg/time/#ParseDuration
\ No newline at end of file
diff --git a/website/docs/segments/web/owm.mdx b/website/docs/segments/web/owm.mdx
index 0bc52d26..871a664a 100644
--- a/website/docs/segments/web/owm.mdx
+++ b/website/docs/segments/web/owm.mdx
@@ -31,17 +31,17 @@ import Config from "@site/src/components/Config.js";
       units: "metric",
       http_timeout: 20,
     },
-  }}u
+  }}
 />
 
 ## Properties
 
-| Name           |   Type   |   Default    | Description                                                                                                                                                                                                                                  |
-| -------------- | :------: | :----------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `api_key`      | `string` |     `.`      | Your API key from [Open Weather Map][owm]. Can also be set using the `POSH_OWM_API_KEY` environment variable.                                                                                                                                |
-| `location`     | `string` | `De Bilt,NL` | The requested location interpreted only if valid coordinates aren't given. Formatted as \<City,STATE,COUNTRY_CODE\>. City name, state code and country code divided by comma. Please, refer to ISO 3166 for the state codes or country codes |
-| `units`        | `string` |  `standard`  | Units of measurement. Available values are standard (kelvin), metric (celsius), and imperial (fahrenheit)                                                                                                                                    |
-| `http_timeout` |  `int`   |     `20`     | in milliseconds, the timeout for http request                                                                                                                                                                                                |
+| Name           |   Type   |   Default    | Description                                                                                                                                                                                                                                                                                                       |
+| -------------- | :------: | :----------: | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `api_key`      | `string` |     `.`      | Your API key from [Open Weather Map][owm]. Can also be set using the `POSH_OWM_API_KEY` environment variable                                                                                                                                                                                                      |
+| `location`     | `string` | `De Bilt,NL` | The requested location interpreted only if valid coordinates aren't given. Formatted as \<City,STATE,COUNTRY_CODE\>. City name, state code and country code divided by comma. Please, refer to ISO 3166 for the state codes or country codes . Can also be set using the `POSH_OWM_LOCATION` environment variable |
+| `units`        | `string` |  `standard`  | Units of measurement. Available values are standard (kelvin), metric (celsius), and imperial (fahrenheit)                                                                                                                                                                                                         |
+| `http_timeout` |  `int`   |     `20`     | in milliseconds, the timeout for http request                                                                                                                                                                                                                                                                     |
 
 ## Template ([info][templates])
 
diff --git a/website/sidebars.js b/website/sidebars.js
index d3326e30..05b6878a 100644
--- a/website/sidebars.js
+++ b/website/sidebars.js
@@ -137,6 +137,7 @@ module.exports = {
             "segments/languages/kotlin",
             "segments/languages/lua",
             "segments/languages/mojo",
+            "segments/languages/nim",
             "segments/languages/node",
             "segments/languages/ocaml",
             "segments/languages/perl",
@@ -146,6 +147,7 @@ module.exports = {
             "segments/languages/ruby",
             "segments/languages/rust",
             "segments/languages/swift",
+            "segments/languages/v",
             "segments/languages/vala",
             "segments/languages/zig",
           ]


Test patch:
diff --git a/src/segments/golang_test.go b/src/segments/golang_test.go
index 5b068447..b955c2a6 100644
--- a/src/segments/golang_test.go
+++ b/src/segments/golang_test.go
@@ -12,12 +12,15 @@ import (
 
 func TestGolang(t *testing.T) {
 	cases := []struct {
-		Case                  string
-		ExpectedString        string
-		Version               string
-		ParseModFile          bool
-		HasModFileInParentDir bool
-		InvalidModfile        bool
+		Case                     string
+		ExpectedString           string
+		Version                  string
+		ParseModFile             bool
+		HasModFileInParentDir    bool
+		InvalidModfile           bool
+		ParseGoWorkFile          bool
+		HasGoWorkFileInParentDir bool
+		InvalidGoWorkFile        bool
 	}{
 		{Case: "Go 1.15", ExpectedString: "1.15.8", Version: "go version go1.15.8 darwin/amd64"},
 		{Case: "Go 1.16", ExpectedString: "1.16", Version: "go version go1.16 darwin/amd64"},
@@ -31,6 +34,30 @@ func TestGolang(t *testing.T) {
 			ExpectedString:        "1.16",
 			Version:               "go version go1.16 darwin/amd64",
 		},
+		{Case: "go.work file", ParseGoWorkFile: true, HasGoWorkFileInParentDir: true, ExpectedString: "1.21"},
+		{
+			Case:                     "invalid go.work file fallback",
+			ParseGoWorkFile:          true,
+			HasGoWorkFileInParentDir: true,
+			InvalidGoWorkFile:        true,
+			ExpectedString:           "1.16",
+			Version:                  "go version go1.16 darwin/amd64",
+		},
+		{
+			Case:                     "go.work file with go.mod file uses go.mod's version",
+			ParseModFile:             true,
+			HasModFileInParentDir:    true,
+			ParseGoWorkFile:          true,
+			HasGoWorkFileInParentDir: true,
+			ExpectedString:           "1.22.3",
+		},
+		{
+			Case:            "missing both go.mod and go.work file fallback",
+			ParseModFile:    true,
+			ParseGoWorkFile: true,
+			ExpectedString:  "1.16",
+			Version:         "go version go1.16 darwin/amd64",
+		},
 	}
 	for _, tc := range cases {
 		params := &mockedLanguageParams{
@@ -40,6 +67,7 @@ func TestGolang(t *testing.T) {
 			extension:     "*.go",
 		}
 		env, props := getMockedLanguageEnv(params)
+
 		if tc.ParseModFile {
 			props[ParseModFile] = tc.ParseModFile
 			fileInfo := &runtime.FileInfo{
@@ -47,11 +75,13 @@ func TestGolang(t *testing.T) {
 				ParentFolder: "./",
 				IsDir:        false,
 			}
+
 			var err error
 			if !tc.HasModFileInParentDir {
 				err = errors.New("no match")
 			}
 			env.On("HasParentFilePath", "go.mod", false).Return(fileInfo, err)
+
 			var content string
 			if tc.InvalidModfile {
 				content = "invalid go.mod file"
@@ -59,10 +89,38 @@ func TestGolang(t *testing.T) {
 				tmp, _ := os.ReadFile(fileInfo.Path)
 				content = string(tmp)
 			}
+
+			env.On("FileContent", fileInfo.Path).Return(content)
+		}
+
+		if tc.ParseGoWorkFile {
+			props[ParseWorkFile] = tc.ParseGoWorkFile
+			fileInfo := &runtime.FileInfo{
+				Path:         "../test/go.work",
+				ParentFolder: "./",
+				IsDir:        false,
+			}
+
+			var err error
+			if !tc.HasGoWorkFileInParentDir {
+				err = errors.New("no match")
+			}
+
+			env.On("HasParentFilePath", "go.work", false).Return(fileInfo, err)
+			var content string
+			if tc.InvalidGoWorkFile {
+				content = "invalid go.work file"
+			} else {
+				tmp, _ := os.ReadFile(fileInfo.Path)
+				content = string(tmp)
+			}
+
 			env.On("FileContent", fileInfo.Path).Return(content)
 		}
+
 		g := &Golang{}
 		g.Init(props, env)
+
 		assert.True(t, g.Enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
 		assert.Equal(t, tc.ExpectedString, renderTemplate(env, g.Template(), g), fmt.Sprintf("Failed in case: %s", tc.Case))
 	}
diff --git a/src/segments/nim_test.go b/src/segments/nim_test.go
new file mode 100644
index 00000000..0156daf8
--- /dev/null
+++ b/src/segments/nim_test.go
@@ -0,0 +1,46 @@
+package segments
+
+import (
+	"fmt"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestNim(t *testing.T) {
+	cases := []struct {
+		Case           string
+		ExpectedString string
+		Version        string
+	}{
+		{
+			Case:           "Nim 2.2.0",
+			ExpectedString: "2.2.0",
+			Version:        "Nim Compiler Version 2.2.0 [MacOSX: arm64]\nCompiled at 2024-11-30\nCopyright (c) 2006-2024 by Andreas Rumpf",
+		},
+		{
+			Case:           "Nim 1.6.12",
+			ExpectedString: "1.6.12",
+			Version:        "Nim Compiler Version 1.6.12 [Linux: amd64]\nCompiled at 2023-06-15\nCopyright (c) 2006-2023 by Andreas Rumpf",
+		},
+		{
+			Case:           "Nim 2.0.0",
+			ExpectedString: "2.0.0",
+			Version:        "Nim Compiler Version 2.0.0 [Windows: amd64]\nCompiled at 2023-12-25\nCopyright (c) 2006-2023 by Andreas Rumpf",
+		},
+	}
+
+	for _, tc := range cases {
+		params := &mockedLanguageParams{
+			cmd:           "nim",
+			versionParam:  "--version",
+			versionOutput: tc.Version,
+			extension:     "*.nim",
+		}
+		env, props := getMockedLanguageEnv(params)
+		n := &Nim{}
+		n.Init(props, env)
+		assert.True(t, n.Enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
+		assert.Equal(t, tc.ExpectedString, renderTemplate(env, n.Template(), n), fmt.Sprintf("Failed in case: %s", tc.Case))
+	}
+}
diff --git a/src/segments/owm_test.go b/src/segments/owm_test.go
index b9a73bd7..d067b189 100644
--- a/src/segments/owm_test.go
+++ b/src/segments/owm_test.go
@@ -81,6 +81,8 @@ func TestOWMSegmentSingle(t *testing.T) {
 		location := url.QueryEscape(tc.Location)
 		testURL := fmt.Sprintf(OWMWEATHERAPIURL, location)
 		env.On("HTTPRequest", testURL).Return([]byte(tc.WeatherJSONResponse), tc.Error)
+		env.On("Getenv", OWMLocationKey).Return("")
+		env.On("Getenv", OWMAPIKey).Return("")
 
 		o := &Owm{}
 		o.Init(props, env)
@@ -207,6 +209,8 @@ func TestOWMSegmentIcons(t *testing.T) {
 		expectedString := fmt.Sprintf("%s (20°C)", tc.ExpectedIconString)
 
 		env.On("HTTPRequest", testURL).Return([]byte(weatherResponse), nil)
+		env.On("Getenv", OWMLocationKey).Return("")
+		env.On("Getenv", OWMAPIKey).Return("")
 
 		props := properties.Map{
 			APIKey:   "key",
@@ -220,26 +224,4 @@ func TestOWMSegmentIcons(t *testing.T) {
 		assert.Nil(t, o.setStatus())
 		assert.Equal(t, expectedString, renderTemplate(env, o.Template(), o), tc.Case)
 	}
-
-	// test with hyperlink enabled
-	for _, tc := range cases {
-		env := &mock.Environment{}
-
-		weatherResponse := fmt.Sprintf(`{"weather":[{"icon":"%s"}],"main":{"temp":20.3}}`, tc.IconID)
-		expectedString := fmt.Sprintf("«%s (20°C)»(%s)", tc.ExpectedIconString, testURL)
-
-		env.On("HTTPRequest", testURL).Return([]byte(weatherResponse), nil)
-
-		props := properties.Map{
-			APIKey:   "key",
-			Location: "AMSTERDAM,NL",
-			Units:    "metric",
-		}
-
-		o := &Owm{}
-		o.Init(props, env)
-
-		assert.Nil(t, o.setStatus())
-		assert.Equal(t, expectedString, renderTemplate(env, "«{{.Weather}} ({{.Temperature}}{{.UnitIcon}})»({{.URL}})", o), tc.Case)
-	}
 }
diff --git a/src/segments/v_test.go b/src/segments/v_test.go
new file mode 100644
index 00000000..e5706c72
--- /dev/null
+++ b/src/segments/v_test.go
@@ -0,0 +1,46 @@
+package segments
+
+import (
+	"fmt"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestV(t *testing.T) {
+	cases := []struct {
+		Case           string
+		ExpectedString string
+		Version        string
+	}{
+		{
+			Case:           "V 0.4.9",
+			ExpectedString: "0.4.9",
+			Version:        "V 0.4.9 b487986",
+		},
+		{
+			Case:           "V 0.4.8",
+			ExpectedString: "0.4.8",
+			Version:        "V 0.4.8 a123456",
+		},
+		{
+			Case:           "V 0.4.7",
+			ExpectedString: "0.4.7",
+			Version:        "V 0.4.7 f789012",
+		},
+	}
+
+	for _, tc := range cases {
+		params := &mockedLanguageParams{
+			cmd:           "v",
+			versionParam:  "--version",
+			versionOutput: tc.Version,
+			extension:     "*.v",
+		}
+		env, props := getMockedLanguageEnv(params)
+		v := &V{}
+		v.Init(props, env)
+		assert.True(t, v.Enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
+		assert.Equal(t, tc.ExpectedString, renderTemplate(env, v.Template(), v), fmt.Sprintf("Failed in case: %s", tc.Case))
+	}
+}
diff --git a/src/test/go.work b/src/test/go.work
new file mode 100644
index 00000000..350b99cc
--- /dev/null
+++ b/src/test/go.work
@@ -0,0 +1,1 @@
+go 1.21
\ No newline at end of file