feat: add Unity segment

This commit is contained in:
Colt 2023-02-26 23:37:37 +09:00 committed by GitHub
parent 6991a96cd6
commit 1ceba7d603
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 384 additions and 0 deletions

View file

@ -224,6 +224,8 @@ const (
TIME SegmentType = "time"
// UI5 Tooling segment
UI5TOOLING SegmentType = "ui5tooling"
// UNITY writes which Unity version is currently active
UNITY SegmentType = "unity"
// VALA writes the active vala version
VALA SegmentType = "vala"
// WAKATIME writes tracked time spend in dev editors
@ -305,6 +307,7 @@ var Segments = map[SegmentType]func() SegmentWriter{
TEXT: func() SegmentWriter { return &segments.Text{} },
TIME: func() SegmentWriter { return &segments.Time{} },
UI5TOOLING: func() SegmentWriter { return &segments.UI5Tooling{} },
UNITY: func() SegmentWriter { return &segments.Unity{} },
VALA: func() SegmentWriter { return &segments.Vala{} },
WAKATIME: func() SegmentWriter { return &segments.Wakatime{} },
WINREG: func() SegmentWriter { return &segments.WindowsRegistry{} },

112
src/segments/unity.go Normal file
View 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
View 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)
}
}
}

View file

@ -301,6 +301,7 @@
"text",
"terraform",
"ui5tooling",
"unity",
"wakatime",
"winreg",
"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": {
"properties": {

View 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

View file

@ -115,6 +115,7 @@ module.exports = {
"segments/text",
"segments/time",
"segments/ui5tooling",
"segments/unity",
"segments/vala",
"segments/wakatime",
"segments/withings",