diff --git a/docs/docs/segment-project.md b/docs/docs/segment-project.md new file mode 100644 index 00000000..395bf337 --- /dev/null +++ b/docs/docs/segment-project.md @@ -0,0 +1,44 @@ +--- +id: project +title: Project +sidebar_label: Project +--- + +## What + +Display the current version of your project defined in the package file. + +Supports: + +- Node.js project (`package.json`) + +## Sample Configuration + +```json +{ + "type": "project", + "style": "powerline", + "powerline_symbol": "\uE0B0", + "foreground": "#193549", + "background": "#ffeb3b", + "properties": { + "template": " {{ if .Error }}{{ .Error }}{{ else }}{{ if .Version }}\uf487 {{.Version}}{{ end }}{{ end }} " + } +} +``` + +## Template ([info][templates]) + +:::note default template + +``` template +{{ if .Error }}{{ .Error }}{{ else }}{{ if .Version }}\uf487 {{.Version}}{{ end }}{{ end }} +``` + +::: + +### Properties + +- `.Version`: `string` - The version of your project + +[templates]: /docs/config-templates diff --git a/docs/sidebars.js b/docs/sidebars.js index 4ceff3c7..cc44a85e 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -84,6 +84,7 @@ module.exports = { "path", "php", "plastic", + "project", "python", "root", "ruby", diff --git a/src/engine/segment.go b/src/engine/segment.go index 9c2049ea..715ed2f9 100644 --- a/src/engine/segment.go +++ b/src/engine/segment.go @@ -166,6 +166,8 @@ const ( CDS SegmentType = "cds" // npm version NPM SegmentType = "npm" + // Project version + PROJECT SegmentType = "project" ) func (segment *Segment) shouldIncludeFolder() bool { @@ -245,6 +247,7 @@ func (segment *Segment) background() string { func (segment *Segment) mapSegmentWithWriter(env environment.Environment) error { segment.env = env functions := map[SegmentType]SegmentWriter{ + PROJECT: &segments.Project{}, NPM: &segments.Npm{}, OWM: &segments.Owm{}, SESSION: &segments.Session{}, diff --git a/src/segments/project.go b/src/segments/project.go new file mode 100644 index 00000000..58a0f25a --- /dev/null +++ b/src/segments/project.go @@ -0,0 +1,81 @@ +package segments + +import ( + "encoding/json" + "oh-my-posh/environment" + "oh-my-posh/properties" +) + +type ProjectItem struct { + Name string + File string + Fetcher func(item ProjectItem) string +} + +type NodePackageJSON struct { + Name string `json:"name"` + Description string `json:"description"` + Version string `json:"version"` +} + +type Project struct { + props properties.Properties + env environment.Environment + + projects []*ProjectItem + Version string + Error string +} + +func (n *Project) Enabled() bool { + var enabled = false + for _, item := range n.projects { + if !enabled { + enabled = n.hasProjectFile(item) + } + } + + return enabled +} + +func (n *Project) Template() string { + return " {{ if .Error }}{{ .Error }}{{ else }}{{ if .Version }}\uf487 {{.Version}}{{ end }}{{ end }} " +} + +func (n *Project) Init(props properties.Properties, env environment.Environment) { + n.props = props + n.env = env + + n.projects = []*ProjectItem{ + { + Name: "node", + File: "package.json", + Fetcher: n.getNodePackageVersion, + }, + } + + n.Version = "" + for _, item := range n.projects { + if n.hasProjectFile(item) { + n.Version = item.Fetcher(*item) + break + } + } +} + +func (n *Project) hasProjectFile(p *ProjectItem) bool { + return n.env.HasFiles(p.File) +} + +func (n *Project) getNodePackageVersion(item ProjectItem) string { + content := n.env.FileContent(item.File) + + var data NodePackageJSON + err := json.Unmarshal([]byte(content), &data) + if err != nil { + n.Error = err.Error() + return "" + } + + return data.Version +} diff --git a/src/segments/project_test.go b/src/segments/project_test.go new file mode 100644 index 00000000..4e096eba --- /dev/null +++ b/src/segments/project_test.go @@ -0,0 +1,43 @@ +package segments + +import ( + "fmt" + "oh-my-posh/mock" + "oh-my-posh/properties" + "testing" + + "github.com/alecthomas/assert" +) + +type MockData struct { + Name string + Case string + ExpectedString string + PackageContents string + File string +} + +func getMockedPackageEnv(tc *MockData) (*mock.MockedEnvironment, properties.Map) { + env := new(mock.MockedEnvironment) + props := properties.Map{} + env.On("HasFiles", tc.File).Return(true) + env.On("FileContent", tc.File).Return(tc.PackageContents) + return env, props +} + +func TestPackage(t *testing.T) { + cases := []*MockData{ + {Case: "1.0.0", ExpectedString: "\uf487 1.0.0", Name: "node", File: "package.json", PackageContents: "{\"version\":\"1.0.0\"}"}, + {Case: "3.2.1", ExpectedString: "\uf487 3.2.1", Name: "node", File: "package.json", PackageContents: "{\"version\":\"3.2.1\"}"}, + {Case: "No version present", ExpectedString: "", Name: "node", File: "package.json", PackageContents: "{}"}, + {Case: "Invalid json", ExpectedString: "invalid character '}' looking for beginning of value", Name: "node", File: "package.json", PackageContents: "}"}, + } + + for _, tc := range cases { + env, props := getMockedPackageEnv(tc) + pkg := &Project{} + pkg.Init(props, env) + assert.True(t, pkg.Enabled(), fmt.Sprintf("Failed in case: %s", tc.Case)) + assert.Equal(t, tc.ExpectedString, renderTemplate(env, pkg.Template(), pkg), fmt.Sprintf("Failed in case: %s", tc.Case)) + } +} diff --git a/themes/schema.json b/themes/schema.json index 863fbc88..c87a3aac 100644 --- a/themes/schema.json +++ b/themes/schema.json @@ -199,7 +199,8 @@ "ui5tooling", "kotlin", "swift", - "npm" + "npm", + "project" ] }, "style": { @@ -265,6 +266,17 @@ } }, "allOf": [ + { + "if": { + "properties": { + "type": { "const": "project" } + } + }, + "then": { + "title": "Project Segment", + "description": "https://ohmyposh.dev/docs/project" + } + }, { "if": { "properties": {