Repository: JanDeDobbeleer/oh-my-posh
Pull request #1894 (2022-03-10 19:58:05)

feat: npm segment
### Prerequisites

- [x] I have read and understood the `CONTRIBUTING` guide
- [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

New npm segment to show the version when a project with `package.json` and `package-lock.json` is used.

<img width="1112" alt="Screenshot 2022-03-10 at 19 48 35" src="https://user-images.githubusercontent.com/2900833/157744583-5c86e2c7-5dd7-4d33-b6be-ce5de78445a5.png">




Patch:
diff --git a/docs/docs/segment-npm.md b/docs/docs/segment-npm.md
new file mode 100644
index 00000000..a1cb4c73
--- /dev/null
+++ b/docs/docs/segment-npm.md
@@ -0,0 +1,44 @@
+---
+id: npm
+title: npm
+sidebar_label: NPM
+---
+
+## What
+
+Display the currently active npm version.
+
+## Sample Configuration
+
+```json
+{
+  "type": "npm",
+  "style": "powerline",
+  "powerline_symbol": "\uE0B0",
+  "foreground": "#193549",
+  "background": "#ffeb3b",
+  "properties": {
+    "template": "\ue71e {{ .Full }} "
+  }
+}
+```
+
+## Template ([info][templates])
+
+:::note default template
+
+``` template
+\ue71e {{.Full}}
+```
+
+:::
+
+### Properties
+
+- `.Full`: `string` - the full version
+- `.Major`: `string` - major number
+- `.Minor`: `string` - minor number
+- `.Patch`: `string` - patch number
+- `.Error`: `string` - when fetching the version string errors
+
+[templates]: /docs/config-templates
diff --git a/src/engine/segment.go b/src/engine/segment.go
index 2903cf88..9c2049ea 100644
--- a/src/engine/segment.go
+++ b/src/engine/segment.go
@@ -164,6 +164,8 @@ const (
 	SWIFT SegmentType = "swift"
 	// cds (SAP CAP) version
 	CDS SegmentType = "cds"
+	// npm version
+	NPM SegmentType = "npm"
 )
 
 func (segment *Segment) shouldIncludeFolder() bool {
@@ -243,6 +245,7 @@ func (segment *Segment) background() string {
 func (segment *Segment) mapSegmentWithWriter(env environment.Environment) error {
 	segment.env = env
 	functions := map[SegmentType]SegmentWriter{
+		NPM:           &segments.Npm{},
 		OWM:           &segments.Owm{},
 		SESSION:       &segments.Session{},
 		PATH:          &segments.Path{},
diff --git a/src/segments/npm.go b/src/segments/npm.go
new file mode 100644
index 00000000..ab55f84e
--- /dev/null
+++ b/src/segments/npm.go
@@ -0,0 +1,34 @@
+package segments
+
+import (
+	"oh-my-posh/environment"
+	"oh-my-posh/properties"
+)
+
+type Npm struct {
+	language
+}
+
+func (n *Npm) Enabled() bool {
+	return n.language.Enabled()
+}
+
+func (n *Npm) Template() string {
+	return " \ue71e {{.Full}} "
+}
+
+func (n *Npm) Init(props properties.Properties, env environment.Environment) {
+	n.language = language{
+		env:        env,
+		props:      props,
+		extensions: []string{"package.json", "package-lock.json"},
+		commands: []*cmd{
+			{
+				executable: "npm",
+				args:       []string{"--version"},
+				regex:      `(?P<version>((?P<major>[0-9]+).(?P<minor>[0-9]+).(?P<patch>[0-9]+)))`,
+			},
+		},
+		versionURLTemplate: "https://github.com/npm/npm/releases/tag/v{{ .Full }}",
+	}
+}
diff --git a/themes/schema.json b/themes/schema.json
index 548b91e1..863fbc88 100644
--- a/themes/schema.json
+++ b/themes/schema.json
@@ -198,7 +198,8 @@
             "haskell",
             "ui5tooling",
             "kotlin",
-            "swift"
+            "swift",
+            "npm"
           ]
         },
         "style": {
@@ -264,6 +265,17 @@
         }
       },
       "allOf": [
+        {
+          "if": {
+            "properties": {
+              "type": { "const": "npm" }
+            }
+          },
+          "then": {
+            "title": "NPM Segment",
+            "description": "https://ohmyposh.dev/docs/npm"
+          }
+        },
         {
           "if": {
             "properties": {


Test patch:
diff --git a/src/segments/npm_test.go b/src/segments/npm_test.go
new file mode 100644
index 00000000..158167c6
--- /dev/null
+++ b/src/segments/npm_test.go
@@ -0,0 +1,31 @@
+package segments
+
+import (
+	"fmt"
+	"testing"
+
+	"github.com/alecthomas/assert"
+)
+
+func TestNpm(t *testing.T) {
+	cases := []struct {
+		Case           string
+		ExpectedString string
+		Version        string
+	}{
+		{Case: "1.0.0", ExpectedString: "\ue71e 1.0.0", Version: "1.0.0"},
+	}
+	for _, tc := range cases {
+		params := &mockedLanguageParams{
+			cmd:           "npm",
+			versionParam:  "--version",
+			versionOutput: tc.Version,
+			extension:     "package.json",
+		}
+		env, props := getMockedLanguageEnv(params)
+		npm := &Npm{}
+		npm.Init(props, env)
+		assert.True(t, npm.Enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
+		assert.Equal(t, tc.ExpectedString, renderTemplate(env, npm.Template(), npm), fmt.Sprintf("Failed in case: %s", tc.Case))
+	}
+}