feat: add quasar segment

This commit is contained in:
Jan De Dobbeleer 2023-07-20 07:57:11 +02:00 committed by Jan De Dobbeleer
parent 8cd77ae1c2
commit aacef4b186
7 changed files with 304 additions and 3 deletions

View file

@ -197,6 +197,8 @@ const (
PROJECT SegmentType = "project"
// PYTHON writes the virtual env name
PYTHON SegmentType = "python"
// QUASAR writes the QUASAR version and context
QUASAR SegmentType = "quasar"
// R version
R SegmentType = "r"
// ROOT writes root symbol
@ -302,6 +304,7 @@ var Segments = map[SegmentType]func() SegmentWriter{
PLASTIC: func() SegmentWriter { return &segments.Plastic{} },
PROJECT: func() SegmentWriter { return &segments.Project{} },
PYTHON: func() SegmentWriter { return &segments.Python{} },
QUASAR: func() SegmentWriter { return &segments.Quasar{} },
R: func() SegmentWriter { return &segments.R{} },
ROOT: func() SegmentWriter { return &segments.Root{} },
RUBY: func() SegmentWriter { return &segments.Ruby{} },

View file

@ -72,6 +72,9 @@ type language struct {
matchesVersionFile matchesVersionFile
homeEnabled bool
displayMode string
// root is the root folder of the project
projectFiles []string
projectRoot *platform.FileInfo
version
Error string
@ -106,11 +109,19 @@ func (l *language) Enabled() bool {
inHomeDir := func() bool {
return l.env.Pwd() == l.env.Home()
}
var enabled bool
homeEnabled := l.props.GetBool(HomeEnabled, l.homeEnabled)
if inHomeDir() && !homeEnabled {
enabled = false
} else {
return false
}
if len(l.projectFiles) != 0 && l.hasProjectFiles() {
enabled = true
}
if !enabled {
// set default mode when not set
if len(l.displayMode) == 0 {
l.displayMode = l.props.GetString(DisplayMode, DisplayModeFiles)
@ -126,7 +137,7 @@ func (l *language) Enabled() bool {
case DisplayModeContext:
fallthrough
default:
enabled = l.hasLanguageFiles() || l.hasLanguageFolders() || l.inLanguageContext()
enabled = l.hasLanguageFiles() || l.hasLanguageFolders() || l.inLanguageContext() || l.hasProjectFiles()
}
}
@ -159,6 +170,16 @@ func (l *language) hasLanguageFiles() bool {
return false
}
func (l *language) hasProjectFiles() bool {
for _, extension := range l.projectFiles {
if configPath, err := l.env.HasParentFilePath(extension); err == nil {
l.projectRoot = configPath
return true
}
}
return false
}
func (l *language) hasLanguageFolders() bool {
for _, folder := range l.folders {
if l.env.HasFolder(folder) {

86
src/segments/quasar.go Normal file
View file

@ -0,0 +1,86 @@
package segments
import (
"encoding/json"
"path/filepath"
"github.com/jandedobbeleer/oh-my-posh/src/platform"
"github.com/jandedobbeleer/oh-my-posh/src/properties"
)
const (
FetchDependencies properties.Property = "fetch_dependencies"
)
type Package struct {
Version string `json:"version"`
Dev bool `json:"dev"`
}
type Quasar struct {
language
HasVite bool
Vite *Package
AppVite *Package
}
func (q *Quasar) Enabled() bool {
if !q.language.Enabled() {
return false
}
if q.language.props.GetBool(FetchDependencies, false) {
q.fetchDependencies()
}
return true
}
func (q *Quasar) Template() string {
return " \uea6a {{.Full}}{{ if .HasVite }} \ueb29 {{ .Vite.Version }}{{ end }} "
}
func (q *Quasar) Init(props properties.Properties, env platform.Environment) {
q.language = language{
env: env,
props: props,
projectFiles: []string{"quasar.config", "quasar.config.js"},
commands: []*cmd{
{
executable: "quasar",
args: []string{"--version"},
regex: `(?P<version>((?P<major>[0-9]+).(?P<minor>[0-9]+).(?P<patch>[0-9]+)))`,
},
},
versionURLTemplate: "https://github.com/quasarframework/quasar/releases/tag/quasar-v{{ .Full }}",
}
}
func (q *Quasar) fetchDependencies() {
if !q.language.env.HasFilesInDir(q.projectRoot.ParentFolder, "package-lock.json") {
return
}
packageFilePath := filepath.Join(q.projectRoot.ParentFolder, "package-lock.json")
content := q.language.env.FileContent(packageFilePath)
var objmap map[string]json.RawMessage
if err := json.Unmarshal([]byte(content), &objmap); err != nil {
return
}
var dependencies map[string]*Package
if err := json.Unmarshal(objmap["dependencies"], &dependencies); err != nil {
return
}
if p, ok := dependencies["vite"]; ok {
q.HasVite = true
q.Vite = p
}
if p, ok := dependencies["@quasar/app-vite"]; ok {
q.AppVite = p
}
}

View file

@ -0,0 +1,84 @@
package segments
import (
"fmt"
"path/filepath"
"testing"
"github.com/alecthomas/assert"
"github.com/jandedobbeleer/oh-my-posh/src/mock"
"github.com/jandedobbeleer/oh-my-posh/src/platform"
"github.com/jandedobbeleer/oh-my-posh/src/properties"
)
func TestQuasar(t *testing.T) {
packageLockFile := `{
"name": "quasar-project",
"version": "0.0.1",
"lockfileVersion": 2,
"requires": true,
"dependencies": {
"@quasar/app-vite": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/@quasar/app-vite/-/app-vite-1.4.3.tgz",
"integrity": "sha512-5iMs1sk6fyYTFoRVySwFXWL/PS23UEsdk+YSFejhXnSs5fVDmb2GQMguCHwDl3jPIHjZ7A+XKkb2iWx9pjiPXw==",
"dev": true
},
"vite": {
"version": "2.9.16",
"resolved": "https://registry.npmjs.org/vite/-/vite-2.9.16.tgz",
"integrity": "sha512-X+6q8KPyeuBvTQV8AVSnKDvXoBMnTx8zxh54sOwmmuOdxkjMmEJXH2UEchA+vTMps1xw9vL64uwJOWryULg7nA==",
"dev": true,
"requires": {
"esbuild": "^0.14.27",
"fsevents": "~2.3.2",
"postcss": "^8.4.13",
"resolve": "^1.22.0",
"rollup": ">=2.59.0 <2.78.0"
}
}
}
}`
cases := []struct {
Case string
ExpectedString string
Version string
HasPackageLockFile bool
FetchDependencies bool
}{
{Case: "@quasar/cli v2.2.1", ExpectedString: "\uea6a 2.2.1", Version: "@quasar/cli v2.2.1"},
{
Case: "@quasar/cli v2.2.1 with vite",
Version: "@quasar/cli v2.2.1",
HasPackageLockFile: true,
FetchDependencies: true,
ExpectedString: "\uea6a 2.2.1 \ueb29 2.9.16",
},
}
for _, tc := range cases {
env := new(mock.MockedEnvironment)
env.On("HasCommand", "quasar").Return(true)
env.On("RunCommand", "quasar", []string{"--version"}).Return(tc.Version, nil)
env.On("Pwd").Return("/usr/home/project")
env.On("Home").Return("/usr/home")
env.On("TemplateCache").Return(&platform.TemplateCache{
Env: make(map[string]string),
})
env.On("HasFilesInDir", "/usr/home/project", "package-lock.json").Return(tc.HasPackageLockFile)
fileInfo := &platform.FileInfo{ParentFolder: "/usr/home/project", IsDir: true}
env.On("HasParentFilePath", "quasar.config").Return(fileInfo, nil)
env.On("FileContent", filepath.Join(fileInfo.ParentFolder, "package-lock.json")).Return(packageLockFile)
props := properties.Map{
properties.FetchVersion: true,
FetchDependencies: tc.FetchDependencies,
}
quasar := &Quasar{}
quasar.Init(props, env)
assert.True(t, quasar.Enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
assert.Equal(t, tc.ExpectedString, renderTemplate(env, quasar.Template(), quasar), fmt.Sprintf("Failed in case: %s", tc.Case))
}
}

View file

@ -1880,6 +1880,43 @@
}
}
},
{
"if": {
"properties": {
"type": {
"const": "quasar"
}
}
},
"then": {
"title": "Quasar Segment",
"description": "https://ohmyposh.dev/docs/segments/quasar",
"properties": {
"properties": {
"properties": {
"home_enabled": {
"$ref": "#/definitions/home_enabled"
},
"fetch_version": {
"$ref": "#/definitions/fetch_version"
},
"missing_command_text": {
"$ref": "#/definitions/missing_command_text"
},
"version_url_template": {
"$ref": "#/definitions/version_url_template"
},
"fetch_dependencies": {
"type": "boolean",
"title": "Fetch Dependencies",
"description": "Fetch the vite and @quasar/app-vite dependency information or not",
"default": true
}
}
}
}
}
},
{
"if": {
"properties": {

View file

@ -0,0 +1,69 @@
---
id: quasar
title: Quasar
sidebar_label: Quasar
---
## What
Display the currently active [Quasar CLI][quasar-cli] version. Only rendered when the current or
parent folder contains a `quasar.config` or `quasar.config.js` file.
## Sample Configuration
import Config from "@site/src/components/Config.js";
<Config
data={{
type: "quasar",
style: "powerline",
powerline_symbol: "\uE0B0",
foreground: "#00B4FF",
template:
" \uea6a {{.Full}}{{ if .HasVite }} \ueb29 {{ .Vite.Version }}{{ end }} ",
}}
/>
## Properties
| Name | Type | Description |
| ---------------------- | --------- | --------------------------------------------------------------------------------------------------------------------- |
| `home_enabled` | `boolean` | display the segment in the HOME folder or not - defaults to `false` |
| `missing_command_text` | `string` | text to display when the command is missing - defaults to empty |
| `fetch_version` | `boolean` | fetch the NPM version - defaults to `true` |
| `version_url_template` | `string` | a go [text/template][go-text-template] [template][templates] that creates the URL of the version info / release notes |
| `fetch_dependencies` | `boolean` | fetch the version number of the `vite` and `@quasar/app-vite` dependencies if present - defaults to `false` |
## Template ([info][templates])
:::note default template
```template
\uea6a {{.Full}}{{ if .HasVite }} \ueb29 {{ .Vite.Version }}{{ end }}
```
:::
### Properties
| Name | Type | Description |
| ---------- | ------------ | -------------------------------------------------- |
| `.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 |
| `.Vite` | `Dependency` | the `vite` dependency, if found |
| `.AppVite` | `Dependency` | the `@quasar/app-vite` dependency, if found |
#### Dependency
| Name | Type | Description |
| ---------- | --------- | ----------------------------- |
| `.Version` | `string` | the full version |
| `.Dev` | `boolean` | development dependency or not |
[go-text-template]: https://golang.org/pkg/text/template/
[templates]: /docs/configuration/templates
[quasar-cli]: https://quasar.dev/start/quasar-cli

View file

@ -101,6 +101,7 @@ module.exports = {
"segments/plastic",
"segments/project",
"segments/python",
"segments/quasar",
"segments/r",
"segments/root",
"segments/ruby",