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"
|
||||
// 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
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",
|
||||
"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": {
|
||||
|
|
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/time",
|
||||
"segments/ui5tooling",
|
||||
"segments/unity",
|
||||
"segments/vala",
|
||||
"segments/wakatime",
|
||||
"segments/withings",
|
||||
|
|
Loading…
Reference in a new issue