mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2025-02-21 02:55:37 -08:00
feat: add Unity segment
This commit is contained in:
parent
6991a96cd6
commit
1ceba7d603
|
@ -224,6 +224,8 @@ const (
|
||||||
TIME SegmentType = "time"
|
TIME SegmentType = "time"
|
||||||
// UI5 Tooling segment
|
// UI5 Tooling segment
|
||||||
UI5TOOLING SegmentType = "ui5tooling"
|
UI5TOOLING SegmentType = "ui5tooling"
|
||||||
|
// UNITY writes which Unity version is currently active
|
||||||
|
UNITY SegmentType = "unity"
|
||||||
// VALA writes the active vala version
|
// VALA writes the active vala version
|
||||||
VALA SegmentType = "vala"
|
VALA SegmentType = "vala"
|
||||||
// WAKATIME writes tracked time spend in dev editors
|
// WAKATIME writes tracked time spend in dev editors
|
||||||
|
@ -305,6 +307,7 @@ var Segments = map[SegmentType]func() SegmentWriter{
|
||||||
TEXT: func() SegmentWriter { return &segments.Text{} },
|
TEXT: func() SegmentWriter { return &segments.Text{} },
|
||||||
TIME: func() SegmentWriter { return &segments.Time{} },
|
TIME: func() SegmentWriter { return &segments.Time{} },
|
||||||
UI5TOOLING: func() SegmentWriter { return &segments.UI5Tooling{} },
|
UI5TOOLING: func() SegmentWriter { return &segments.UI5Tooling{} },
|
||||||
|
UNITY: func() SegmentWriter { return &segments.Unity{} },
|
||||||
VALA: func() SegmentWriter { return &segments.Vala{} },
|
VALA: func() SegmentWriter { return &segments.Vala{} },
|
||||||
WAKATIME: func() SegmentWriter { return &segments.Wakatime{} },
|
WAKATIME: func() SegmentWriter { return &segments.Wakatime{} },
|
||||||
WINREG: func() SegmentWriter { return &segments.WindowsRegistry{} },
|
WINREG: func() SegmentWriter { return &segments.WindowsRegistry{} },
|
||||||
|
|
112
src/segments/unity.go
Normal file
112
src/segments/unity.go
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
package segments
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/jandedobbeleer/oh-my-posh/src/platform"
|
||||||
|
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
||||||
|
"github.com/jandedobbeleer/oh-my-posh/src/regex"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Unity struct {
|
||||||
|
props properties.Properties
|
||||||
|
env platform.Environment
|
||||||
|
|
||||||
|
UnityVersion string
|
||||||
|
CSharpVersion string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *Unity) Enabled() bool {
|
||||||
|
unityVersion, err := u.GetUnityVersion()
|
||||||
|
if err != nil {
|
||||||
|
u.env.Error(err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(unityVersion) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
u.UnityVersion = unityVersion
|
||||||
|
|
||||||
|
csharpVersion, err := u.GetCSharpVersion()
|
||||||
|
if err != nil {
|
||||||
|
u.env.Error(err)
|
||||||
|
}
|
||||||
|
u.CSharpVersion = csharpVersion
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *Unity) GetUnityVersion() (version string, err error) {
|
||||||
|
projectDir, err := u.env.HasParentFilePath("ProjectSettings")
|
||||||
|
if err != nil {
|
||||||
|
u.env.Debug("No ProjectSettings parent folder found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !u.env.HasFilesInDir(projectDir.Path, "ProjectVersion.txt") {
|
||||||
|
u.env.Debug("No ProjectVersion.txt file found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
versionFilePath := filepath.Join(projectDir.Path, "ProjectVersion.txt")
|
||||||
|
versionFileText := u.env.FileContent(versionFilePath)
|
||||||
|
|
||||||
|
firstLine := strings.Split(versionFileText, "\n")[0]
|
||||||
|
versionPrefix := "m_EditorVersion: "
|
||||||
|
versionPrefixIndex := strings.Index(firstLine, versionPrefix)
|
||||||
|
if versionPrefixIndex == -1 {
|
||||||
|
err := errors.New("ProjectSettings/ProjectVersion.txt is missing 'm_EditorVersion: ' prefix")
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
versionStartIndex := versionPrefixIndex + len(versionPrefix)
|
||||||
|
unityVersion := firstLine[versionStartIndex:]
|
||||||
|
|
||||||
|
return strings.TrimSuffix(unityVersion, "f1"), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *Unity) GetCSharpVersion() (version string, err error) {
|
||||||
|
lastDotIndex := strings.LastIndex(u.UnityVersion, ".")
|
||||||
|
if lastDotIndex == -1 {
|
||||||
|
return "", errors.New("lastDotIndex")
|
||||||
|
}
|
||||||
|
shortUnityVersion := u.UnityVersion[0:lastDotIndex]
|
||||||
|
|
||||||
|
if val, found := u.env.Cache().Get(shortUnityVersion); found {
|
||||||
|
csharpVersion := strings.TrimSuffix(val, ".0")
|
||||||
|
return csharpVersion, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
url := fmt.Sprintf("https://docs.unity3d.com/%s/Documentation/Manual/CSharpCompiler.html", shortUnityVersion)
|
||||||
|
httpTimeout := u.props.GetInt(properties.HTTPTimeout, 2000)
|
||||||
|
|
||||||
|
body, err := u.env.HTTPRequest(url, nil, httpTimeout)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
pageContent := string(body)
|
||||||
|
|
||||||
|
pattern := `<a href="https://(?:docs|learn)\.microsoft\.com/en-us/dotnet/csharp/whats-new/csharp-[0-9]+-?[0-9]*">(?P<csharpVersion>.*)</a>`
|
||||||
|
matches := regex.FindNamedRegexMatch(pattern, pageContent)
|
||||||
|
if matches != nil && matches["csharpVersion"] != "" {
|
||||||
|
csharpVersion := strings.TrimSuffix(matches["csharpVersion"], ".0")
|
||||||
|
u.env.Cache().Set(shortUnityVersion, csharpVersion, -1)
|
||||||
|
return csharpVersion, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
u.env.Cache().Set(shortUnityVersion, "", -1)
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *Unity) Template() string {
|
||||||
|
return " \ue721 {{ .UnityVersion }}{{ if .CSharpVersion }} {{ .CSharpVersion }}{{ end }} "
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *Unity) Init(props properties.Properties, env platform.Environment) {
|
||||||
|
u.props = props
|
||||||
|
u.env = env
|
||||||
|
}
|
188
src/segments/unity_test.go
Normal file
188
src/segments/unity_test.go
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
package segments
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
mock2 "github.com/stretchr/testify/mock"
|
||||||
|
|
||||||
|
"github.com/jandedobbeleer/oh-my-posh/src/mock"
|
||||||
|
"github.com/jandedobbeleer/oh-my-posh/src/platform"
|
||||||
|
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CacheGet struct {
|
||||||
|
key string
|
||||||
|
val string
|
||||||
|
found bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type CacheSet struct {
|
||||||
|
key string
|
||||||
|
val string
|
||||||
|
}
|
||||||
|
|
||||||
|
type HTTPResponse struct {
|
||||||
|
body string
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnitySegment(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
Case string
|
||||||
|
ExpectedOutput string
|
||||||
|
VersionFileText string
|
||||||
|
CacheGet CacheGet
|
||||||
|
CacheSet CacheSet
|
||||||
|
ExpectedToBeEnabled bool
|
||||||
|
VersionFileExists bool
|
||||||
|
HTTPResponse HTTPResponse
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Case: "C# version cached",
|
||||||
|
ExpectedOutput: "\ue721 2021.3.16 C# 9",
|
||||||
|
ExpectedToBeEnabled: true,
|
||||||
|
VersionFileExists: true,
|
||||||
|
VersionFileText: "m_EditorVersion: 2021.3.16f1\nm_EditorVersionWithRevision: 2021.3.16f1 (4016570cf34f)",
|
||||||
|
CacheGet: CacheGet{
|
||||||
|
key: "2021.3",
|
||||||
|
val: "C# 9",
|
||||||
|
found: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Case: "C# version not cached",
|
||||||
|
ExpectedOutput: "\ue721 2021.3.16 C# 9",
|
||||||
|
ExpectedToBeEnabled: true,
|
||||||
|
VersionFileExists: true,
|
||||||
|
VersionFileText: "m_EditorVersion: 2021.3.16f1\nm_EditorVersionWithRevision: 2021.3.16f1 (4016570cf34f)",
|
||||||
|
CacheGet: CacheGet{
|
||||||
|
key: "2021.3",
|
||||||
|
val: "",
|
||||||
|
found: false,
|
||||||
|
},
|
||||||
|
CacheSet: CacheSet{
|
||||||
|
key: "2021.3",
|
||||||
|
val: "C# 9",
|
||||||
|
},
|
||||||
|
HTTPResponse: HTTPResponse{
|
||||||
|
body: `<a href="https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-9">C# 9.0</a>`,
|
||||||
|
err: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Case: "C# version has a minor version",
|
||||||
|
ExpectedOutput: "\ue721 2021.3.16 C# 7.3",
|
||||||
|
ExpectedToBeEnabled: true,
|
||||||
|
VersionFileExists: true,
|
||||||
|
VersionFileText: "m_EditorVersion: 2021.3.16f1\nm_EditorVersionWithRevision: 2021.3.16f1 (4016570cf34f)",
|
||||||
|
CacheGet: CacheGet{
|
||||||
|
key: "2021.3",
|
||||||
|
val: "",
|
||||||
|
found: false,
|
||||||
|
},
|
||||||
|
CacheSet: CacheSet{
|
||||||
|
key: "2021.3",
|
||||||
|
val: "C# 7.3",
|
||||||
|
},
|
||||||
|
HTTPResponse: HTTPResponse{
|
||||||
|
body: `<a href="https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-7-3">C# 7.3</a>`,
|
||||||
|
err: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Case: "C# version not found in webpage",
|
||||||
|
ExpectedOutput: "\ue721 2021.3.16",
|
||||||
|
ExpectedToBeEnabled: true,
|
||||||
|
VersionFileExists: true,
|
||||||
|
VersionFileText: "m_EditorVersion: 2021.3.16f1\nm_EditorVersionWithRevision: 2021.3.16f1 (4016570cf34f)",
|
||||||
|
CacheGet: CacheGet{
|
||||||
|
key: "2021.3",
|
||||||
|
val: "",
|
||||||
|
found: false,
|
||||||
|
},
|
||||||
|
CacheSet: CacheSet{
|
||||||
|
key: "2021.3",
|
||||||
|
val: "",
|
||||||
|
},
|
||||||
|
HTTPResponse: HTTPResponse{
|
||||||
|
body: `<h1>Sorry... that page seems to be missing!</h1>`,
|
||||||
|
err: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Case: "http request fails",
|
||||||
|
ExpectedOutput: "\ue721 2021.3.16",
|
||||||
|
ExpectedToBeEnabled: true,
|
||||||
|
VersionFileExists: true,
|
||||||
|
VersionFileText: "m_EditorVersion: 2021.3.16f1\nm_EditorVersionWithRevision: 2021.3.16f1 (4016570cf34f)",
|
||||||
|
CacheGet: CacheGet{
|
||||||
|
key: "2021.3",
|
||||||
|
val: "",
|
||||||
|
found: false,
|
||||||
|
},
|
||||||
|
HTTPResponse: HTTPResponse{
|
||||||
|
body: "",
|
||||||
|
err: errors.New("FAIL"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Case: "ProjectSettings/ProjectVersion.txt doesn't exist",
|
||||||
|
ExpectedToBeEnabled: false,
|
||||||
|
VersionFileExists: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Case: "ProjectSettings/ProjectVersion.txt is empty",
|
||||||
|
ExpectedToBeEnabled: false,
|
||||||
|
VersionFileExists: true,
|
||||||
|
VersionFileText: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Case: "ProjectSettings/ProjectVersion.txt does not have expected format",
|
||||||
|
ExpectedToBeEnabled: false,
|
||||||
|
VersionFileExists: true,
|
||||||
|
VersionFileText: "2021.3.16f1",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range cases {
|
||||||
|
env := new(mock.MockedEnvironment)
|
||||||
|
env.On("Error", mock2.Anything).Return()
|
||||||
|
env.On("Debug", mock2.Anything)
|
||||||
|
|
||||||
|
err := errors.New("no match at root level")
|
||||||
|
var projectDir *platform.FileInfo
|
||||||
|
if tc.VersionFileExists {
|
||||||
|
err = nil
|
||||||
|
projectDir = &platform.FileInfo{
|
||||||
|
ParentFolder: "UnityProjectRoot",
|
||||||
|
Path: "UnityProjectRoot/ProjectSettings",
|
||||||
|
IsDir: true,
|
||||||
|
}
|
||||||
|
env.On("HasFilesInDir", projectDir.Path, "ProjectVersion.txt").Return(tc.VersionFileExists)
|
||||||
|
versionFilePath := filepath.Join(projectDir.Path, "ProjectVersion.txt")
|
||||||
|
env.On("FileContent", versionFilePath).Return(tc.VersionFileText)
|
||||||
|
}
|
||||||
|
env.On("HasParentFilePath", "ProjectSettings").Return(projectDir, err)
|
||||||
|
|
||||||
|
cache := &mock.MockedCache{}
|
||||||
|
cache.On("Get", tc.CacheGet.key).Return(tc.CacheGet.val, tc.CacheGet.found)
|
||||||
|
cache.On("Set", tc.CacheSet.key, tc.CacheSet.val, -1).Return()
|
||||||
|
env.On("Cache").Return(cache)
|
||||||
|
|
||||||
|
url := fmt.Sprintf("https://docs.unity3d.com/%s/Documentation/Manual/CSharpCompiler.html", tc.CacheGet.key)
|
||||||
|
env.On("HTTPRequest", url).Return([]byte(tc.HTTPResponse.body), tc.HTTPResponse.err)
|
||||||
|
|
||||||
|
props := properties.Map{}
|
||||||
|
unity := &Unity{}
|
||||||
|
unity.Init(props, env)
|
||||||
|
assert.Equal(t, tc.ExpectedToBeEnabled, unity.Enabled())
|
||||||
|
if tc.ExpectedToBeEnabled {
|
||||||
|
assert.Equal(t, tc.ExpectedOutput, renderTemplate(env, unity.Template(), unity), tc.Case)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -301,6 +301,7 @@
|
||||||
"text",
|
"text",
|
||||||
"terraform",
|
"terraform",
|
||||||
"ui5tooling",
|
"ui5tooling",
|
||||||
|
"unity",
|
||||||
"wakatime",
|
"wakatime",
|
||||||
"winreg",
|
"winreg",
|
||||||
"withings",
|
"withings",
|
||||||
|
@ -2752,6 +2753,26 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"type": { "const": "unity" }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"title": "Unity Segment",
|
||||||
|
"description": "https://ohmyposh.dev/docs/unity",
|
||||||
|
"properties": {
|
||||||
|
"properties": {
|
||||||
|
"properties": {
|
||||||
|
"http_timeout": {
|
||||||
|
"$ref": "#/definitions/http_timeout"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"if": {
|
"if": {
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
59
website/docs/segments/unity.mdx
Normal file
59
website/docs/segments/unity.mdx
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
---
|
||||||
|
id: unity
|
||||||
|
title: Unity
|
||||||
|
sidebar_label: Unity
|
||||||
|
---
|
||||||
|
|
||||||
|
## What
|
||||||
|
|
||||||
|
Display the currently active [Unity][unity] and C# versions.
|
||||||
|
|
||||||
|
The Unity version is displayed regardless of whether or not the C# version fetching succeeds.
|
||||||
|
|
||||||
|
The C# version is fetched from [the docs][unity-csharp-page], but the page only exists as far back as Unity 2018.3.
|
||||||
|
Earlier versions will not display a C# version.
|
||||||
|
|
||||||
|
A web request only occurs the first time a given `major.minor` Unity version is encountered.
|
||||||
|
Subsequent invocations return the cached C# version.
|
||||||
|
|
||||||
|
## Sample Configuration
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "unity",
|
||||||
|
"style": "powerline",
|
||||||
|
"powerline_symbol": "\ue0b0",
|
||||||
|
"foreground": "#111111",
|
||||||
|
"background": "#ffffff",
|
||||||
|
"properties": {
|
||||||
|
"http_timeout": 2000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| --------------- | -------- | ----------------------------------------------- |
|
||||||
|
| `http_timeout` | `int` | The default timeout for http request is 2000ms. |
|
||||||
|
|
||||||
|
## Template ([info][templates])
|
||||||
|
|
||||||
|
:::note default template
|
||||||
|
|
||||||
|
```template
|
||||||
|
\ue721 {{ .UnityVersion }}{{ if .CSharpVersion }} {{ .CSharpVersion }}{{ end }}
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Properties
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---------------- | -------- | ---------------------------------------- |
|
||||||
|
| `.UnityVersion` | `string` | the Unity version |
|
||||||
|
| `.CSharpVersion` | `string` | the C# version |
|
||||||
|
|
||||||
|
[unity]: https://unity.com/
|
||||||
|
[templates]: /docs/configuration/templates
|
||||||
|
[unity-csharp-page]: https://docs.unity3d.com/Manual/CSharpCompiler.html
|
|
@ -115,6 +115,7 @@ module.exports = {
|
||||||
"segments/text",
|
"segments/text",
|
||||||
"segments/time",
|
"segments/time",
|
||||||
"segments/ui5tooling",
|
"segments/ui5tooling",
|
||||||
|
"segments/unity",
|
||||||
"segments/vala",
|
"segments/vala",
|
||||||
"segments/wakatime",
|
"segments/wakatime",
|
||||||
"segments/withings",
|
"segments/withings",
|
||||||
|
|
Loading…
Reference in a new issue