feat: nx segment

This commit is contained in:
evanfuture 2022-05-26 14:51:26 +02:00 committed by Jan De Dobbeleer
parent 2db0e67804
commit a4e8bc1b60
11 changed files with 237 additions and 132 deletions

View file

@ -129,6 +129,8 @@ const (
NODE SegmentType = "node"
// npm version
NPM SegmentType = "npm"
// NX writes which Nx version us currently active
NX SegmentType = "nx"
// OS write os specific icon
OS SegmentType = "os"
// OWM writes the weather coming from openweatherdata
@ -277,6 +279,7 @@ func (segment *Segment) mapSegmentWithWriter(env environment.Environment) error
NIGHTSCOUT: &segments.Nightscout{},
NODE: &segments.Node{},
NPM: &segments.Npm{},
NX: &segments.Nx{},
OS: &segments.Os{},
OWM: &segments.Owm{},
PATH: &segments.Path{},

View file

@ -1,10 +1,9 @@
package segments
import (
"encoding/json"
"fmt"
"oh-my-posh/environment"
"oh-my-posh/properties"
"path/filepath"
)
type Angular struct {
@ -22,28 +21,8 @@ func (a *Angular) Init(props properties.Properties, env environment.Environment)
extensions: []string{"angular.json"},
commands: []*cmd{
{
regex: `(?:(?P<version>((?P<major>[0-9]+).(?P<minor>[0-9]+).(?P<patch>[0-9]+))))`,
getVersion: func() (string, error) {
const fileName string = "package.json"
const fileFolder string = "/node_modules/@angular/core"
angularFilePath := a.language.env.Pwd() + fileFolder
if !a.language.env.HasFilesInDir(angularFilePath, fileName) {
return "", fmt.Errorf("%s not found in %s", fileName, angularFilePath)
}
// parse file
objmap := map[string]json.RawMessage{}
content := a.language.env.FileContent(a.language.env.Pwd() + fileFolder + "/" + fileName)
err := json.Unmarshal([]byte(content), &objmap)
if err != nil {
return "", err
}
var str string
err = json.Unmarshal(objmap["version"], &str)
if err != nil {
return "", err
}
return str, nil
},
regex: `(?:(?P<version>((?P<major>[0-9]+).(?P<minor>[0-9]+).(?P<patch>[0-9]+))))`,
getVersion: a.getVersion,
},
},
versionURLTemplate: "https://github.com/angular/angular/releases/tag/{{.Full}}",
@ -53,3 +32,7 @@ func (a *Angular) Init(props properties.Properties, env environment.Environment)
func (a *Angular) Enabled() bool {
return a.language.Enabled()
}
func (a *Angular) getVersion() (string, error) {
return getNodePackageVersion(a.language.env, filepath.Join("@angular", "core"))
}

View file

@ -1,44 +0,0 @@
package segments
import (
"fmt"
"oh-my-posh/environment"
"oh-my-posh/mock"
"oh-my-posh/properties"
"testing"
"github.com/stretchr/testify/assert"
)
func TestAngularCliVersionDisplayed(t *testing.T) {
cases := []struct {
Case string
FullVersion string
Version string
}{
{Case: "Angular 13.0.3", FullVersion: "13.0.3", Version: "{ \"name\": \"@angular/core\",\"version\": \"13.0.3\"}"},
{Case: "Angular 11.0.1", FullVersion: "11.0.1", Version: "{ \"name\": \"@angular/core\",\"version\": \"11.0.1\"}"},
}
for _, ta := range cases {
params := &mockedLanguageParams{
extension: "angular.json",
}
var env = new(mock.MockedEnvironment)
// mock getVersion methods
env.On("Pwd").Return("/usr/home/dev/my-app")
env.On("Home").Return("/usr/home")
env.On("HasFiles", params.extension).Return(true)
env.On("HasFilesInDir", "/usr/home/dev/my-app/node_modules/@angular/core", "package.json").Return(true)
env.On("FileContent", "/usr/home/dev/my-app/node_modules/@angular/core/package.json").Return(ta.Version)
env.On("TemplateCache").Return(&environment.TemplateCache{
Env: make(map[string]string),
})
props := properties.Map{}
angular := &Angular{}
angular.Init(props, env)
assert.True(t, angular.Enabled(), fmt.Sprintf("Failed in case: %s", ta.Case))
assert.Equal(t, ta.FullVersion, renderTemplate(env, angular.Template(), angular), fmt.Sprintf("Failed in case: %s", ta.Case))
}
}

55
src/segments/nx.go Normal file
View file

@ -0,0 +1,55 @@
package segments
import (
"encoding/json"
"fmt"
"oh-my-posh/environment"
"oh-my-posh/properties"
"path/filepath"
)
type Nx struct {
language
}
func (a *Nx) Template() string {
return languageTemplate
}
func (a *Nx) Init(props properties.Properties, env environment.Environment) {
a.language = language{
env: env,
props: props,
extensions: []string{"workspace.json"},
commands: []*cmd{
{
regex: `(?:(?P<version>((?P<major>[0-9]+).(?P<minor>[0-9]+).(?P<patch>[0-9]+))))`,
getVersion: a.getVersion,
},
},
versionURLTemplate: "https://github.com/nrwl/nx/releases/tag/{{.Full}}",
}
}
func (a *Nx) Enabled() bool {
return a.language.Enabled()
}
func (a *Nx) getVersion() (string, error) {
return getNodePackageVersion(a.language.env, "nx")
}
func getNodePackageVersion(env environment.Environment, nodePackage string) (string, error) {
const fileName string = "package.json"
folder := filepath.Join(env.Pwd(), "node_modules", nodePackage)
if !env.HasFilesInDir(folder, fileName) {
return "", fmt.Errorf("%s not found in %s", fileName, folder)
}
content := env.FileContent(filepath.Join(folder, fileName))
var data ProjectData
err := json.Unmarshal([]byte(content), &data)
if err != nil {
return "", err
}
return data.Version, nil
}

44
src/segments/nx_test.go Normal file
View file

@ -0,0 +1,44 @@
package segments
import (
"oh-my-posh/environment"
"oh-my-posh/mock"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
)
func TestGetNodePackageVersion(t *testing.T) {
cases := []struct {
Case string
PackageJSON string
Version string
ShouldFail bool
NoFiles bool
}{
{Case: "14.1.5", Version: "14.1.5", PackageJSON: "{ \"name\": \"nx\",\"version\": \"14.1.5\"}"},
{Case: "14.0.0", Version: "14.0.0", PackageJSON: "{ \"name\": \"nx\",\"version\": \"14.0.0\"}"},
{Case: "no files", NoFiles: true, ShouldFail: true},
{Case: "bad data", ShouldFail: true, PackageJSON: "bad data"},
}
for _, tc := range cases {
var env = new(mock.MockedEnvironment)
// mock getVersion methods
env.On("Pwd").Return("posh")
path := filepath.Join("posh", "node_modules", "nx")
env.On("HasFilesInDir", path, "package.json").Return(!tc.NoFiles)
env.On("FileContent", filepath.Join(path, "package.json")).Return(tc.PackageJSON)
env.On("TemplateCache").Return(&environment.TemplateCache{
Env: make(map[string]string),
})
got, err := getNodePackageVersion(env, "nx")
if tc.ShouldFail {
assert.Error(t, err, tc.Case)
return
}
assert.Nil(t, err, tc.Case)
assert.Equal(t, tc.Version, got, tc.Case)
}
}

View file

@ -146,6 +146,15 @@
"trailing_diamond": "\ue0b4 ",
"type": "angular"
},
{
"background": "#1e293b",
"foreground": "#ffffff",
"leading_diamond": " \ue0b6",
"style": "diamond",
"template": "{{ if .Error }}{{ .Error }}{{ else }}Nx {{ .Full }}{{ end }}",
"trailing_diamond": "\ue0b4 ",
"type": "nx"
},
{
"background": "#945bb3",
"foreground": "#359a25",
@ -251,9 +260,7 @@
},
{
"foreground": "#e0f8ff",
"foreground_templates": [
"{{ if gt .Code 0 }}#ef5350{{ end }}"
],
"foreground_templates": ["{{ if gt .Code 0 }}#ef5350{{ end }}"],
"properties": {
"always_enabled": true
},

View file

@ -80,6 +80,12 @@
"template": "<#ffffff>(</>{{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }}<#ffffff>)</>",
"type": "angular"
},
{
"foreground": "#ffffff",
"style": "plain",
"template": "<#1e293b>(</>{{ if .Error }}{{ .Error }}{{ else }}Nx {{ .Full }}{{ end }}<#1e293b>)</>",
"type": "nx"
},
{
"foreground": "#359a25",
"style": "plain",
@ -171,9 +177,7 @@
},
{
"foreground": "#ecf7fa",
"foreground_templates": [
"{{ if gt .Code 0 }}#ef5350{{ end }}"
],
"foreground_templates": ["{{ if gt .Code 0 }}#ef5350{{ end }}"],
"properties": {
"always_enabled": true
},

View file

@ -184,6 +184,15 @@
"trailing_diamond": "<transparent,#ffffff>\ue0b2</>",
"type": "angular"
},
{
"background": "#1e293b",
"foreground": "#ffffff",
"leading_diamond": "\ue0b2",
"style": "diamond",
"template": "\ue753 {{ if .Error }}{{ .Error }}{{ else }}Nx {{ .Full }}{{ end }} ",
"trailing_diamond": "<transparent,#1e293b>\ue0b2</>",
"type": "nx"
},
{
"background": "#945bb3",
"foreground": "#359a25",
@ -269,9 +278,7 @@
},
{
"foreground": "#22da6e",
"foreground_templates": [
"{{ if gt .Code 0 }}#ef5350{{ end }}"
],
"foreground_templates": ["{{ if gt .Code 0 }}#ef5350{{ end }}"],
"properties": {
"always_enabled": true
},

View file

@ -59,12 +59,7 @@
"type": "string",
"title": "Display Mode",
"description": "Determines whether the segment is displayed always or only if a file matching the extensions are present in the current folder",
"enum": [
"always",
"files",
"environment",
"context"
],
"enum": ["always", "files", "environment", "context"],
"default": "context"
},
"missing_command_text": {
@ -114,11 +109,7 @@
}
},
"then": {
"required": [
"type",
"alignment",
"segments"
],
"required": ["type", "alignment", "segments"],
"title": "Prompt definition, contains 1 or more segments to render"
}
},
@ -131,10 +122,7 @@
}
},
"then": {
"required": [
"type",
"segments"
],
"required": ["type", "segments"],
"title": "RPrompt definition, contains 1 or more segments to render to the right of the cursor"
}
}
@ -144,20 +132,14 @@
"type": "string",
"title": "Block type",
"description": "https://ohmyposh.dev/docs/configuration/block#type",
"enum": [
"prompt",
"rprompt"
],
"enum": ["prompt", "rprompt"],
"default": "prompt"
},
"alignment": {
"type": "string",
"title": "Block alignment",
"description": "https://ohmyposh.dev/docs/configuration/block#alignment",
"enum": [
"left",
"right"
],
"enum": ["left", "right"],
"default": "left"
},
"newline": {
@ -192,10 +174,7 @@
"title": "A segment",
"description": "https://ohmyposh.dev/docs/configuration/segment",
"default": {},
"required": [
"type",
"style"
],
"required": ["type", "style"],
"properties": {
"type": {
"type": "string",
@ -227,6 +206,7 @@
"kotlin",
"node",
"npm",
"nx",
"os",
"owm",
"path",
@ -259,12 +239,7 @@
"type": "string",
"title": "Segment Style",
"description": "https://ohmyposh.dev/docs/configuration/segment#style",
"enum": [
"plain",
"powerline",
"diamond",
"accordion"
]
"enum": ["plain", "powerline", "diamond", "accordion"]
},
"foreground": {
"$ref": "#/definitions/color"
@ -444,11 +419,7 @@
"title": "Source",
"description": "https://ohmyposh.dev/docs/az#properties",
"default": "first_match",
"enum": [
"first_match",
"cli",
"pwsh"
]
"enum": ["first_match", "cli", "pwsh"]
}
}
}
@ -1705,11 +1676,7 @@
"title": "units",
"description": "Units of measurement. Available values are standard (kelvin), metric (celsius), and imperial (fahrenheit). Default is standard",
"default": "standard",
"enum": [
"standard",
"metric",
"imperial"
]
"enum": ["standard", "metric", "imperial"]
},
"http_timeout": {
"$ref": "#/definitions/http_timeout"
@ -1904,6 +1871,37 @@
}
}
},
{
"if": {
"properties": {
"type": {
"const": "nx"
}
}
},
"then": {
"title": "Nx Segment",
"description": "https://ohmyposh.dev/docs/segments/nx",
"properties": {
"properties": {
"properties": {
"home_enabled": {
"$ref": "#/definitions/home_enabled"
},
"fetch_version": {
"$ref": "#/definitions/fetch_version"
},
"display_mode": {
"$ref": "#/definitions/display_mode"
},
"version_url_template": {
"$ref": "#/definitions/version_url_template"
}
}
}
}
}
},
{
"if": {
"properties": {
@ -2234,11 +2232,7 @@
"type": "string",
"title": "Use Stack GHC",
"description": "Get the GHC version used by Stack. Will decrease performance. Boolean indicating whether stack ghc was used available in template as .StackGhc",
"enum": [
"always",
"package",
"never"
],
"enum": ["always", "package", "never"],
"default": "never"
}
}
@ -2463,9 +2457,7 @@
]
}
},
"required": [
"blocks"
],
"required": ["blocks"],
"properties": {
"final_space": {
"type": "boolean",
@ -2517,9 +2509,7 @@
}
}
},
"required": [
"tips"
]
"required": ["tips"]
}
},
"transient_prompt": {

View file

@ -0,0 +1,55 @@
---
id: nx
title: Nx
sidebar_label: Nx
---
## What
Display the currently active [Nx][nx-docs] version.
## Sample Configuration
```json
{
"type": "nx",
"style": "powerline",
"powerline_symbol": "\uE0B0",
"foreground": "#000000",
"background": "#1976d2",
"template": " \uE753 {{ .Full }} "
}
```
## Properties
- home_enabled: `boolean` - display the segment in the HOME folder or not - defaults to `false`
- fetch_version: `boolean` - fetch the active version or not; useful if all you need is an icon indicating `ng`
- display_mode: `string` - determines when the segment is displayed
- `always`: the segment is always displayed
- `files`: the segment is only displayed when `workspace.json` file is present (default)
- version_url_template: `string` - a go [text/template][go-text-template] [template][templates] that creates
the URL of the version info / release notes
## Template ([info][templates])
:::note default template
```template
{{ if .Error }}{{ .Error }}{{ else }}{{ .Full }}{{ end }}
```
:::
### Properties
- `.Full`: `string` - the full version
- `.Major`: `string` - major number
- `.Minor`: `string` - minor number
- `.Patch`: `string` - patch number
- `.URL`: `string` - URL of the version info / release notes
- `.Error`: `string` - error encountered when fetching the version string
[go-text-template]: https://golang.org/pkg/text/template/
[templates]: /docs/configuration/templates
[nx-docs]: https://nx.dev

View file

@ -22,7 +22,7 @@ module.exports = {
],
},
"installation/prompt",
"installation/customize"
"installation/customize",
],
},
],
@ -81,6 +81,7 @@ module.exports = {
"segments/nightscout",
"segments/npm",
"segments/node",
"segments/nx",
"segments/os",
"segments/owm",
"segments/path",