mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2026-08-24 10:14:12 -05:00
refactor(segments): migrate 19 languages to a generic engine
Most language segments were ~20-30 line Go files that only declared file extensions, an executable name, and a version regex before delegating to the shared Language base. Every new simple language (e.g. the recent GCC PR) meant another one-off struct, test file, and registration to review and maintain. Replace fortran, ruby, clojure, crystal, elixir, julia, kotlin, lua, nim, ocaml, perl, php, r, rust, swift, v, vala, zig, and dart with a single ConfiguredLanguage engine driven by a built-in preset table. Public config surface (segment type strings, all existing options) is unchanged; this is purely an internal consolidation. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Entire-Checkpoint: 6d449f3da816
This commit is contained in:
committed by
Jan De Dobbeleer
co-authored by
Claude Sonnet 5
parent
5c27aaadf0
commit
59969e90b5
+20
-38
@@ -47,22 +47,18 @@ func init() {
|
||||
gob.Register(&segments.CfTarget{})
|
||||
gob.Register(&segments.Claude{})
|
||||
gob.Register(&segments.ClaudeData{})
|
||||
gob.Register(&segments.Clojure{})
|
||||
gob.Register(&segments.Cmake{})
|
||||
gob.Register(&segments.ConfiguredLanguage{})
|
||||
gob.Register(&segments.Connection{})
|
||||
gob.Register(&segments.Crystal{})
|
||||
gob.Register(&segments.Dart{})
|
||||
gob.Register(&segments.Deno{})
|
||||
gob.Register(&segments.Docker{})
|
||||
gob.Register(&segments.Dotnet{})
|
||||
gob.Register(&segments.Dvc{})
|
||||
gob.Register(&segments.DvcStatus{})
|
||||
gob.Register(&segments.Elixir{})
|
||||
gob.Register(&segments.Executiontime{})
|
||||
gob.Register(&segments.Status{})
|
||||
gob.Register(&segments.Firebase{})
|
||||
gob.Register(&segments.Flutter{})
|
||||
gob.Register(&segments.Fortran{})
|
||||
gob.Register(&segments.Fossil{})
|
||||
gob.Register(&segments.FossilStatus{})
|
||||
gob.Register(&segments.Gcp{})
|
||||
@@ -81,11 +77,8 @@ func init() {
|
||||
gob.Register(&segments.HTTP{})
|
||||
gob.Register(&segments.Jujutsu{})
|
||||
gob.Register(&segments.JujutsuStatus{})
|
||||
gob.Register(&segments.Julia{})
|
||||
gob.Register(&segments.Kotlin{})
|
||||
gob.Register(&segments.Kubectl{})
|
||||
gob.Register(&segments.LastFM{})
|
||||
gob.Register(&segments.Lua{})
|
||||
gob.Register(&segments.Mercurial{})
|
||||
gob.Register(&segments.MercurialStatus{})
|
||||
gob.Register(&segments.Mojo{})
|
||||
@@ -94,18 +87,14 @@ func init() {
|
||||
gob.Register(&segments.Nbgv{})
|
||||
gob.Register(&segments.Nightscout{})
|
||||
gob.Register(&segments.NixShell{})
|
||||
gob.Register(&segments.Nim{})
|
||||
gob.Register(&segments.Node{})
|
||||
gob.Register(&segments.Npm{})
|
||||
gob.Register(&segments.Nx{})
|
||||
gob.Register(&segments.OCaml{})
|
||||
gob.Register(&segments.OrthodoxCal{})
|
||||
gob.Register(&segments.Os{})
|
||||
gob.Register(&segments.Owm{})
|
||||
gob.Register(&segments.Path{})
|
||||
gob.Register(&segments.Folders{})
|
||||
gob.Register(&segments.Perl{})
|
||||
gob.Register(&segments.Php{})
|
||||
gob.Register(&segments.Plastic{})
|
||||
gob.Register(&segments.PlasticStatus{})
|
||||
gob.Register(&segments.Pnpm{})
|
||||
@@ -114,12 +103,9 @@ func init() {
|
||||
gob.Register(&segments.Python{})
|
||||
gob.Register(&segments.Quasar{})
|
||||
gob.Register(&segments.Package{})
|
||||
gob.Register(&segments.R{})
|
||||
gob.Register(&segments.Ramadan{})
|
||||
gob.Register(&segments.React{})
|
||||
gob.Register(&segments.Root{})
|
||||
gob.Register(&segments.Ruby{})
|
||||
gob.Register(&segments.Rust{})
|
||||
gob.Register(&segments.Sapling{})
|
||||
gob.Register(&segments.SaplingStatus{})
|
||||
gob.Register(&segments.Session{})
|
||||
@@ -131,7 +117,6 @@ func init() {
|
||||
gob.Register(&segments.Svelte{})
|
||||
gob.Register(&segments.Svn{})
|
||||
gob.Register(&segments.SvnStatus{})
|
||||
gob.Register(&segments.Swift{})
|
||||
gob.Register(&segments.SystemInfo{})
|
||||
gob.Register(&segments.TalosCTL{})
|
||||
gob.Register(&segments.Taskwarrior{})
|
||||
@@ -146,8 +131,6 @@ func init() {
|
||||
gob.Register(&segments.Unity{})
|
||||
gob.Register(&segments.Upgrade{})
|
||||
gob.Register(&segments.UpgradeCache{})
|
||||
gob.Register(&segments.V{})
|
||||
gob.Register(&segments.Vala{})
|
||||
gob.Register(&segments.VIMode{})
|
||||
gob.Register(&segments.Wakatime{})
|
||||
gob.Register(&segments.WinGet{})
|
||||
@@ -157,7 +140,6 @@ func init() {
|
||||
gob.Register(&segments.XMake{})
|
||||
gob.Register(&segments.Yarn{})
|
||||
gob.Register(&segments.Ytm{})
|
||||
gob.Register(&segments.Zig{})
|
||||
gob.Register(&segments.Segment{})
|
||||
}
|
||||
|
||||
@@ -427,23 +409,23 @@ var Segments = map[SegmentType]func() SegmentWriter{
|
||||
CF: func() SegmentWriter { return &segments.Cf{} },
|
||||
CFTARGET: func() SegmentWriter { return &segments.CfTarget{} },
|
||||
CLAUDE: func() SegmentWriter { return &segments.Claude{} },
|
||||
CLOJURE: func() SegmentWriter { return &segments.Clojure{} },
|
||||
CLOJURE: func() SegmentWriter { return segments.NewLanguage(string(CLOJURE)) },
|
||||
CMAKE: func() SegmentWriter { return &segments.Cmake{} },
|
||||
CONNECTION: func() SegmentWriter { return &segments.Connection{} },
|
||||
COPILOT: func() SegmentWriter { return &segments.Copilot{} },
|
||||
COPILOTCLI: func() SegmentWriter { return &segments.CopilotCLI{} },
|
||||
CRYSTAL: func() SegmentWriter { return &segments.Crystal{} },
|
||||
DART: func() SegmentWriter { return &segments.Dart{} },
|
||||
CRYSTAL: func() SegmentWriter { return segments.NewLanguage(string(CRYSTAL)) },
|
||||
DART: func() SegmentWriter { return segments.NewLanguage(string(DART)) },
|
||||
DENO: func() SegmentWriter { return &segments.Deno{} },
|
||||
DOCKER: func() SegmentWriter { return &segments.Docker{} },
|
||||
DOTNET: func() SegmentWriter { return &segments.Dotnet{} },
|
||||
DVC: func() SegmentWriter { return &segments.Dvc{} },
|
||||
ELIXIR: func() SegmentWriter { return &segments.Elixir{} },
|
||||
ELIXIR: func() SegmentWriter { return segments.NewLanguage(string(ELIXIR)) },
|
||||
EXECUTIONTIME: func() SegmentWriter { return &segments.Executiontime{} },
|
||||
EXIT: func() SegmentWriter { return &segments.Status{} },
|
||||
FIREBASE: func() SegmentWriter { return &segments.Firebase{} },
|
||||
FLUTTER: func() SegmentWriter { return &segments.Flutter{} },
|
||||
FORTRAN: func() SegmentWriter { return &segments.Fortran{} },
|
||||
FORTRAN: func() SegmentWriter { return segments.NewLanguage(string(FORTRAN)) },
|
||||
FOSSIL: func() SegmentWriter { return &segments.Fossil{} },
|
||||
GCP: func() SegmentWriter { return &segments.Gcp{} },
|
||||
GIT: func() SegmentWriter { return &segments.Git{} },
|
||||
@@ -456,11 +438,11 @@ var Segments = map[SegmentType]func() SegmentWriter{
|
||||
JAVA: func() SegmentWriter { return &segments.Java{} },
|
||||
HTTP: func() SegmentWriter { return &segments.HTTP{} },
|
||||
JUJUTSU: func() SegmentWriter { return &segments.Jujutsu{} },
|
||||
JULIA: func() SegmentWriter { return &segments.Julia{} },
|
||||
KOTLIN: func() SegmentWriter { return &segments.Kotlin{} },
|
||||
JULIA: func() SegmentWriter { return segments.NewLanguage(string(JULIA)) },
|
||||
KOTLIN: func() SegmentWriter { return segments.NewLanguage(string(KOTLIN)) },
|
||||
KUBECTL: func() SegmentWriter { return &segments.Kubectl{} },
|
||||
LASTFM: func() SegmentWriter { return &segments.LastFM{} },
|
||||
LUA: func() SegmentWriter { return &segments.Lua{} },
|
||||
LUA: func() SegmentWriter { return segments.NewLanguage(string(LUA)) },
|
||||
MERCURIAL: func() SegmentWriter { return &segments.Mercurial{} },
|
||||
MOJO: func() SegmentWriter { return &segments.Mojo{} },
|
||||
MVN: func() SegmentWriter { return &segments.Mvn{} },
|
||||
@@ -468,29 +450,29 @@ var Segments = map[SegmentType]func() SegmentWriter{
|
||||
NBGV: func() SegmentWriter { return &segments.Nbgv{} },
|
||||
NIGHTSCOUT: func() SegmentWriter { return &segments.Nightscout{} },
|
||||
NIXSHELL: func() SegmentWriter { return &segments.NixShell{} },
|
||||
NIM: func() SegmentWriter { return &segments.Nim{} },
|
||||
NIM: func() SegmentWriter { return segments.NewLanguage(string(NIM)) },
|
||||
NODE: func() SegmentWriter { return &segments.Node{} },
|
||||
NPM: func() SegmentWriter { return &segments.Npm{} },
|
||||
NX: func() SegmentWriter { return &segments.Nx{} },
|
||||
OCAML: func() SegmentWriter { return &segments.OCaml{} },
|
||||
OCAML: func() SegmentWriter { return segments.NewLanguage(string(OCAML)) },
|
||||
ORTHODOXCAL: func() SegmentWriter { return &segments.OrthodoxCal{} },
|
||||
OS: func() SegmentWriter { return &segments.Os{} },
|
||||
OWM: func() SegmentWriter { return &segments.Owm{} },
|
||||
PATH: func() SegmentWriter { return &segments.Path{} },
|
||||
PERL: func() SegmentWriter { return &segments.Perl{} },
|
||||
PHP: func() SegmentWriter { return &segments.Php{} },
|
||||
PERL: func() SegmentWriter { return segments.NewLanguage(string(PERL)) },
|
||||
PHP: func() SegmentWriter { return segments.NewLanguage(string(PHP)) },
|
||||
PLASTIC: func() SegmentWriter { return &segments.Plastic{} },
|
||||
PNPM: func() SegmentWriter { return &segments.Pnpm{} },
|
||||
PROJECT: func() SegmentWriter { return &segments.Project{} },
|
||||
PULUMI: func() SegmentWriter { return &segments.Pulumi{} },
|
||||
PYTHON: func() SegmentWriter { return &segments.Python{} },
|
||||
QUASAR: func() SegmentWriter { return &segments.Quasar{} },
|
||||
R: func() SegmentWriter { return &segments.R{} },
|
||||
R: func() SegmentWriter { return segments.NewLanguage(string(R)) },
|
||||
RAMADAN: func() SegmentWriter { return &segments.Ramadan{} },
|
||||
REACT: func() SegmentWriter { return &segments.React{} },
|
||||
ROOT: func() SegmentWriter { return &segments.Root{} },
|
||||
RUBY: func() SegmentWriter { return &segments.Ruby{} },
|
||||
RUST: func() SegmentWriter { return &segments.Rust{} },
|
||||
RUBY: func() SegmentWriter { return segments.NewLanguage(string(RUBY)) },
|
||||
RUST: func() SegmentWriter { return segments.NewLanguage(string(RUST)) },
|
||||
SAPLING: func() SegmentWriter { return &segments.Sapling{} },
|
||||
SESSION: func() SegmentWriter { return &segments.Session{} },
|
||||
SHELL: func() SegmentWriter { return &segments.Shell{} },
|
||||
@@ -500,7 +482,7 @@ var Segments = map[SegmentType]func() SegmentWriter{
|
||||
STRAVA: func() SegmentWriter { return &segments.Strava{} },
|
||||
SVELTE: func() SegmentWriter { return &segments.Svelte{} },
|
||||
SVN: func() SegmentWriter { return &segments.Svn{} },
|
||||
SWIFT: func() SegmentWriter { return &segments.Swift{} },
|
||||
SWIFT: func() SegmentWriter { return segments.NewLanguage(string(SWIFT)) },
|
||||
SYSTEMINFO: func() SegmentWriter { return &segments.SystemInfo{} },
|
||||
TALOSCTL: func() SegmentWriter { return &segments.TalosCTL{} },
|
||||
TASKWARRIOR: func() SegmentWriter { return &segments.Taskwarrior{} },
|
||||
@@ -514,8 +496,8 @@ var Segments = map[SegmentType]func() SegmentWriter{
|
||||
UNO: func() SegmentWriter { return &segments.Uno{} },
|
||||
UNITY: func() SegmentWriter { return &segments.Unity{} },
|
||||
UPGRADE: func() SegmentWriter { return &segments.Upgrade{} },
|
||||
V: func() SegmentWriter { return &segments.V{} },
|
||||
VALA: func() SegmentWriter { return &segments.Vala{} },
|
||||
V: func() SegmentWriter { return segments.NewLanguage(string(V)) },
|
||||
VALA: func() SegmentWriter { return segments.NewLanguage(string(VALA)) },
|
||||
VIMODE: func() SegmentWriter { return &segments.VIMode{} },
|
||||
WAKATIME: func() SegmentWriter { return &segments.Wakatime{} },
|
||||
WINGET: func() SegmentWriter { return &segments.WinGet{} },
|
||||
@@ -524,7 +506,7 @@ var Segments = map[SegmentType]func() SegmentWriter{
|
||||
XMAKE: func() SegmentWriter { return &segments.XMake{} },
|
||||
YARN: func() SegmentWriter { return &segments.Yarn{} },
|
||||
YTM: func() SegmentWriter { return &segments.Ytm{} },
|
||||
ZIG: func() SegmentWriter { return &segments.Zig{} },
|
||||
ZIG: func() SegmentWriter { return segments.NewLanguage(string(ZIG)) },
|
||||
ZVM: func() SegmentWriter { return &segments.Zvm{} },
|
||||
}
|
||||
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
package segments
|
||||
|
||||
type Clojure struct {
|
||||
Language
|
||||
}
|
||||
|
||||
func (c *Clojure) Template() string {
|
||||
return languageTemplate
|
||||
}
|
||||
|
||||
func (c *Clojure) Enabled() bool {
|
||||
c.init()
|
||||
return c.Language.Enabled()
|
||||
}
|
||||
|
||||
const clojureToolName = "clojure"
|
||||
|
||||
const leinToolName = "lein"
|
||||
|
||||
func (c *Clojure) init() {
|
||||
options := c.options.StringArray(Tooling, []string{})
|
||||
if len(options) == 0 {
|
||||
c.defaultTooling = []string{clojureToolName, leinToolName}
|
||||
}
|
||||
|
||||
c.extensions = []string{
|
||||
"project.clj",
|
||||
"deps.edn",
|
||||
"build.boot",
|
||||
"bb.edn",
|
||||
"*.clj",
|
||||
"*.cljc",
|
||||
"*.cljs",
|
||||
}
|
||||
|
||||
c.tooling = map[string]*cmd{
|
||||
clojureToolName: {
|
||||
executable: clojureToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: `Clojure CLI version (?P<version>(?P<major>[0-9]+)\.(?P<minor>[0-9]+)\.(?P<patch>[0-9]+)(?:\.(?P<build>[0-9]+))?)`,
|
||||
},
|
||||
leinToolName: {
|
||||
executable: leinToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: `Leiningen (?P<version>(?P<major>[0-9]+)\.(?P<minor>[0-9]+)\.(?P<patch>[0-9]+))`,
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package segments
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestClojure(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
Cmd string
|
||||
}{
|
||||
{
|
||||
Case: "Clojure CLI 1.11.1.1113",
|
||||
ExpectedString: "1.11.1.1113",
|
||||
Version: "Clojure CLI version 1.11.1.1113",
|
||||
Cmd: "clojure",
|
||||
},
|
||||
{
|
||||
Case: "Leiningen 2.9.8",
|
||||
ExpectedString: "2.9.8",
|
||||
Version: "Leiningen 2.9.8 on Java 11.0.11 OpenJDK 64-Bit Server VM",
|
||||
Cmd: "lein",
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: tc.Cmd,
|
||||
versionParam: "--version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.clj",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
props[LanguageExtensions] = []string{params.extension}
|
||||
if tc.Cmd != "clojure" {
|
||||
env.On("HasCommand", "clojure").Return(false)
|
||||
}
|
||||
c := &Clojure{}
|
||||
c.Init(props, env)
|
||||
assert.True(t, c.Enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, c.Template(), c), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package segments
|
||||
|
||||
type Crystal struct {
|
||||
Language
|
||||
}
|
||||
|
||||
func (c *Crystal) Template() string {
|
||||
return languageTemplate
|
||||
}
|
||||
|
||||
const crystalToolName = "crystal"
|
||||
|
||||
func (c *Crystal) Enabled() bool {
|
||||
c.extensions = []string{"*.cr", "shard.yml"}
|
||||
c.tooling = map[string]*cmd{
|
||||
crystalToolName: {
|
||||
executable: crystalToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: `Crystal ` + versionRegex,
|
||||
},
|
||||
}
|
||||
c.defaultTooling = []string{crystalToolName}
|
||||
c.versionURLTemplate = "https://github.com/crystal-lang/crystal/releases/tag/{{ .Full }}"
|
||||
|
||||
return c.Language.Enabled()
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package segments
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCrystal(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
}{
|
||||
{Case: "Crystal 1.0.0", ExpectedString: "1.0.0", Version: "Crystal 1.0.0 (2021-03-22)"},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "crystal",
|
||||
versionParam: "--version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.cr",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
c := &Crystal{}
|
||||
c.Init(props, env)
|
||||
assert.True(t, c.Enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, c.Template(), c), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package segments
|
||||
|
||||
var (
|
||||
dartExtensions = []string{"*.dart", "pubspec.yaml", "pubspec.yml", "pubspec.lock"}
|
||||
dartFolders = []string{".dart_tool"}
|
||||
)
|
||||
|
||||
type Dart struct {
|
||||
Language
|
||||
}
|
||||
|
||||
func (d *Dart) Template() string {
|
||||
return languageTemplate
|
||||
}
|
||||
|
||||
func (d *Dart) Enabled() bool {
|
||||
d.extensions = dartExtensions
|
||||
d.folders = dartFolders
|
||||
d.tooling = map[string]*cmd{
|
||||
fvmToolName: {
|
||||
executable: fvmToolName,
|
||||
args: []string{dartToolName, versionFlagArg},
|
||||
regex: `Dart SDK version: ` + versionRegex,
|
||||
},
|
||||
dartToolName: {
|
||||
executable: dartToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: `Dart SDK version: ` + versionRegex,
|
||||
},
|
||||
}
|
||||
d.defaultTooling = []string{fvmToolName, dartToolName}
|
||||
d.versionURLTemplate = "https://dart.dev/guides/language/evolution#dart-{{ .Major }}{{ .Minor }}"
|
||||
|
||||
return d.Language.Enabled()
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package segments
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestDart(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
}{
|
||||
{Case: "Dart 2.12.4", ExpectedString: "2.12.4", Version: "Dart SDK version: 2.12.4 (stable) (Thu Apr 15 12:26:53 2021 +0200) on \"macos_x64\""},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "dart",
|
||||
versionParam: "--version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.dart",
|
||||
}
|
||||
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
env.On("HasCommand", "fvm").Return(false)
|
||||
|
||||
d := &Dart{}
|
||||
d.Init(props, env)
|
||||
|
||||
assert.True(t, d.Enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, d.Template(), d), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package segments
|
||||
|
||||
type Elixir struct {
|
||||
Language
|
||||
}
|
||||
|
||||
func (e *Elixir) Template() string {
|
||||
return languageTemplate
|
||||
}
|
||||
|
||||
const elixirToolName = "elixir"
|
||||
|
||||
func (e *Elixir) Enabled() bool {
|
||||
e.extensions = []string{"*.ex", "*.exs"}
|
||||
e.tooling = map[string]*cmd{
|
||||
asdfToolName: {
|
||||
executable: asdfToolName,
|
||||
args: []string{"current", elixirToolName},
|
||||
regex: `elixir\s+` + versionRegex + `[^\s]*\s+`,
|
||||
},
|
||||
elixirToolName: {
|
||||
executable: elixirToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: `Elixir ` + versionRegex,
|
||||
},
|
||||
}
|
||||
e.defaultTooling = []string{asdfToolName, elixirToolName}
|
||||
e.versionURLTemplate = "https://github.com/elixir-lang/elixir/releases/tag/v{{ .Full }}"
|
||||
|
||||
return e.Language.Enabled()
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package segments
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestElixir(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
ElixirVersionOutput string
|
||||
AsdfVersionOutput string
|
||||
HasAsdf bool
|
||||
AsdfExitCode int
|
||||
}{
|
||||
{
|
||||
Case: "Version without asdf",
|
||||
ExpectedString: "1.14.2",
|
||||
ElixirVersionOutput: "Erlang/OTP 25 [erts-13.1.3] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit] [dtrace]\n\nElixir 1.14.2 (compiled with Erlang/OTP 25)",
|
||||
},
|
||||
{
|
||||
Case: "Version with asdf",
|
||||
ExpectedString: "1.14.2",
|
||||
HasAsdf: true,
|
||||
AsdfVersionOutput: "elixir 1.14.2-otp-25 /path/to/.tool-versions",
|
||||
ElixirVersionOutput: "Should not be used",
|
||||
},
|
||||
{
|
||||
Case: "Version with asdf not set: should fall back to elixir --version",
|
||||
ExpectedString: "1.14.2",
|
||||
HasAsdf: true,
|
||||
AsdfVersionOutput: "elixir ______ No version is set. Run \"asdf <global|shell|local> elixir <version>\"",
|
||||
AsdfExitCode: 126,
|
||||
ElixirVersionOutput: "Erlang/OTP 25 [erts-13.1.3] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit] [dtrace]\n\nElixir 1.14.2 (compiled with Erlang/OTP 25)",
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "elixir",
|
||||
versionParam: "--version",
|
||||
versionOutput: tc.ElixirVersionOutput,
|
||||
extension: "*.ex",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
|
||||
env.On("HasCommand", "asdf").Return(tc.HasAsdf)
|
||||
var asdfErr error
|
||||
if tc.AsdfExitCode != 0 {
|
||||
asdfErr = &runtime.CommandError{ExitCode: tc.AsdfExitCode}
|
||||
}
|
||||
env.On("RunCommandWithEnv", "asdf", []string(nil), []string{"current", "elixir"}).Return(tc.AsdfVersionOutput, asdfErr)
|
||||
|
||||
r := &Elixir{}
|
||||
r.Init(props, env)
|
||||
assert.True(t, r.Enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, r.Template(), r), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
}
|
||||
}
|
||||
@@ -11,8 +11,8 @@ func (f *Flutter) Template() string {
|
||||
const flutterToolName = "flutter"
|
||||
|
||||
func (f *Flutter) Enabled() bool {
|
||||
f.extensions = dartExtensions
|
||||
f.folders = dartFolders
|
||||
f.extensions = []string{"*.dart", pubspecFileName, "pubspec.yml", "pubspec.lock"}
|
||||
f.folders = []string{".dart_tool"}
|
||||
f.tooling = map[string]*cmd{
|
||||
fvmToolName: {
|
||||
executable: fvmToolName,
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
package segments
|
||||
|
||||
type Fortran struct {
|
||||
Language
|
||||
}
|
||||
|
||||
func (f *Fortran) Template() string {
|
||||
return languageTemplate
|
||||
}
|
||||
|
||||
const gfortranToolName = "gfortran"
|
||||
|
||||
func (f *Fortran) Enabled() bool {
|
||||
f.extensions = []string{
|
||||
"*.f", "*.for", "*.fpp",
|
||||
"*.f77", "*.f90", "*.f95",
|
||||
"*.f03", "*.f08",
|
||||
"*.F", "*.FOR", "*.FPP",
|
||||
"*.F77", "*.F90", "*.F95",
|
||||
"*.F03", "*.F08",
|
||||
"fpm.toml",
|
||||
}
|
||||
f.tooling = map[string]*cmd{
|
||||
gfortranToolName: {
|
||||
executable: gfortranToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: `GNU Fortran \(.*\) ` + versionRegex,
|
||||
},
|
||||
}
|
||||
f.defaultTooling = []string{gfortranToolName}
|
||||
|
||||
return f.Language.Enabled()
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package segments
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestFortran(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
}{
|
||||
{
|
||||
Case: "GNU Fortran 10.2.1 Debian",
|
||||
ExpectedString: "10.2.1",
|
||||
Version: `GNU Fortran (Debian 10.2.1-6) 10.2.1 20210110
|
||||
Copyright (C) 2020 Free Software Foundation, Inc.
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.`,
|
||||
},
|
||||
{
|
||||
Case: "GNU Fortran 11.4.0 Ubuntu",
|
||||
ExpectedString: "11.4.0",
|
||||
Version: `GNU Fortran (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
|
||||
Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.`,
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "gfortran",
|
||||
versionParam: "--version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.f",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
f := &Fortran{}
|
||||
f.Init(props, env)
|
||||
assert.True(t, f.Enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, f.Template(), f), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package segments
|
||||
|
||||
type Julia struct {
|
||||
Language
|
||||
}
|
||||
|
||||
func (j *Julia) Template() string {
|
||||
return languageTemplate
|
||||
}
|
||||
|
||||
func (j *Julia) Enabled() bool {
|
||||
j.extensions = []string{"*.jl"}
|
||||
j.tooling = map[string]*cmd{
|
||||
juliaToolName: {
|
||||
executable: juliaToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: `julia version ` + versionRegex,
|
||||
},
|
||||
}
|
||||
j.defaultTooling = []string{juliaToolName}
|
||||
j.versionURLTemplate = "https://github.com/JuliaLang/julia/releases/tag/v{{ .Full }}"
|
||||
|
||||
return j.Language.Enabled()
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package segments
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestJulia(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
}{
|
||||
{Case: "Julia 1.6.0", ExpectedString: "1.6.0", Version: "julia version 1.6.0"},
|
||||
{Case: "Julia 1.6.1", ExpectedString: "1.6.1", Version: "julia version 1.6.1"},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "julia",
|
||||
versionParam: "--version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.jl",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
j := &Julia{}
|
||||
j.Init(props, env)
|
||||
assert.True(t, j.Enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, j.Template(), j), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package segments
|
||||
|
||||
type Kotlin struct {
|
||||
Language
|
||||
}
|
||||
|
||||
func (k *Kotlin) Template() string {
|
||||
return languageTemplate
|
||||
}
|
||||
|
||||
const kotlinToolName = "kotlin"
|
||||
|
||||
func (k *Kotlin) Enabled() bool {
|
||||
k.extensions = []string{"*.kt", "*.kts", "*.ktm"}
|
||||
k.tooling = map[string]*cmd{
|
||||
kotlinToolName: {
|
||||
executable: kotlinToolName,
|
||||
args: []string{versionFlagShortArg},
|
||||
regex: `Kotlin version ` + versionRegex,
|
||||
},
|
||||
}
|
||||
k.defaultTooling = []string{kotlinToolName}
|
||||
k.versionURLTemplate = "https://github.com/JetBrains/kotlin/releases/tag/v{{ .Full }}"
|
||||
|
||||
return k.Language.Enabled()
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package segments
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestKotlin(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
}{
|
||||
{Case: "Kotlin 1.6.10", ExpectedString: "1.6.10", Version: "Kotlin version 1.6.10-release-923 (JRE 17.0.2+0)"},
|
||||
{Case: "Kotlin 1.6.0", ExpectedString: "1.6.0", Version: "Kotlin version 1.6.0-release-915 (JRE 17.0.2+0)"},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "kotlin",
|
||||
versionParam: "-version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.kt",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
k := &Kotlin{}
|
||||
k.Init(props, env)
|
||||
assert.True(t, k.Enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, k.Template(), k), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,8 @@ const (
|
||||
versionRegexPrefixed = `(?:(?P<version>((?P<major>[0-9]+).(?P<minor>[0-9]+).(?P<patch>[0-9]+))))`
|
||||
versionRegexSemver = `(?:(?P<version>((?P<major>[0-9]+).(?P<minor>[0-9]+).(?P<patch>[0-9]+)(-(?P<prerelease>[a-z]+).(?P<buildmetadata>[0-9]+))?)))`
|
||||
|
||||
fileName = "package.json"
|
||||
fileName = "package.json"
|
||||
pubspecFileName = "pubspec.yaml"
|
||||
|
||||
asdfToolName = "asdf"
|
||||
bunToolName = "bun"
|
||||
@@ -134,8 +135,14 @@ const (
|
||||
LanguageExtensions options.Option = "extensions"
|
||||
// LanguageFolders the list of folders to validate
|
||||
LanguageFolders options.Option = "folders"
|
||||
// LanguageProjectFiles the list of project files to validate
|
||||
LanguageProjectFiles options.Option = "project_files"
|
||||
// Tooling allows enabling additional version fetching tools
|
||||
Tooling options.Option = "tooling"
|
||||
// Tools defines custom tools (executable, args, regex) for a configured language
|
||||
Tools options.Option = "tools"
|
||||
// LanguageName identifies a configured language segment; used as its cache key and preset lookup key
|
||||
LanguageName options.Option = "name"
|
||||
)
|
||||
|
||||
func (l *Language) getName() string {
|
||||
@@ -145,10 +152,13 @@ func (l *Language) getName() string {
|
||||
}
|
||||
|
||||
func (l *Language) Enabled() bool {
|
||||
l.name = l.getName()
|
||||
if l.name == "" {
|
||||
l.name = l.getName()
|
||||
}
|
||||
// override default extensions if needed
|
||||
l.extensions = l.options.StringArray(LanguageExtensions, l.extensions)
|
||||
l.folders = l.options.StringArray(LanguageFolders, l.folders)
|
||||
l.projectFiles = l.options.StringArray(LanguageProjectFiles, l.projectFiles)
|
||||
inHomeDir := func() bool {
|
||||
return l.env.Pwd() == l.env.Home()
|
||||
}
|
||||
@@ -243,6 +253,12 @@ func (l *Language) hasProjectFiles() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// InProjectDir reports whether the working directory is within a project
|
||||
// matched by one of the segment's projectFiles.
|
||||
func (l *Language) InProjectDir() bool {
|
||||
return l.projectRoot != nil
|
||||
}
|
||||
|
||||
func (l *Language) hasLanguageFolders() bool {
|
||||
return slices.ContainsFunc(l.folders, l.env.HasFolder)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,456 @@
|
||||
package segments
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/segments/options"
|
||||
)
|
||||
|
||||
// languageDefinition is a built-in preset for ConfiguredLanguage. Each entry mirrors what a
|
||||
// dedicated language segment used to hardcode: which files trigger it, which executables can
|
||||
// report its version, and how to parse that output.
|
||||
type languageDefinition struct {
|
||||
tooling map[string]*cmd
|
||||
sanitizeVersion func(string) string
|
||||
versionURLTemplate string
|
||||
extensions []string
|
||||
projectFiles []string
|
||||
folders []string
|
||||
defaultTooling []string
|
||||
}
|
||||
|
||||
const (
|
||||
gfortranToolName = "gfortran"
|
||||
rbenvToolName = "rbenv"
|
||||
rvmPromptToolName = "rvm-prompt"
|
||||
chrubyToolName = "chruby"
|
||||
rubyToolName = "ruby"
|
||||
clojureToolName = "clojure"
|
||||
leinToolName = "lein"
|
||||
crystalToolName = "crystal"
|
||||
elixirToolName = "elixir"
|
||||
kotlinToolName = "kotlin"
|
||||
luaToolName = "lua"
|
||||
luajitToolName = "luajit"
|
||||
nimToolName = "nim"
|
||||
ocamlToolName = "ocaml"
|
||||
perlToolName = "perl"
|
||||
rscriptToolName = "Rscript"
|
||||
rExeToolName = "R.exe"
|
||||
rustcToolName = "rustc"
|
||||
swiftToolName = "swift"
|
||||
valaToolName = "vala"
|
||||
zigToolName = "zig"
|
||||
)
|
||||
|
||||
// languageDefinitions holds the built-in presets, keyed by the same name a migrated segment's
|
||||
// SegmentType string used (e.g. "fortran"). ConfiguredLanguage looks itself up here by name;
|
||||
// a name with no entry (the public "language" segment type) relies entirely on the `tools` option.
|
||||
var languageDefinitions = map[string]languageDefinition{
|
||||
"fortran": {
|
||||
extensions: []string{
|
||||
"*.f", "*.for", "*.fpp",
|
||||
"*.f77", "*.f90", "*.f95",
|
||||
"*.f03", "*.f08",
|
||||
"*.F", "*.FOR", "*.FPP",
|
||||
"*.F77", "*.F90", "*.F95",
|
||||
"*.F03", "*.F08",
|
||||
"fpm.toml",
|
||||
},
|
||||
tooling: map[string]*cmd{
|
||||
gfortranToolName: {
|
||||
executable: gfortranToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: `GNU Fortran \(.*\) ` + versionRegex,
|
||||
},
|
||||
},
|
||||
defaultTooling: []string{gfortranToolName},
|
||||
},
|
||||
rubyToolName: {
|
||||
extensions: []string{"*.rb", "Rakefile", "Gemfile"},
|
||||
tooling: map[string]*cmd{
|
||||
rbenvToolName: {
|
||||
executable: rbenvToolName,
|
||||
args: []string{"version-name"},
|
||||
regex: `(?P<version>.+)`,
|
||||
},
|
||||
rvmPromptToolName: {
|
||||
executable: rvmPromptToolName,
|
||||
args: []string{"i", "v", "g"},
|
||||
regex: `(?P<version>.+)`,
|
||||
},
|
||||
chrubyToolName: {
|
||||
executable: chrubyToolName,
|
||||
args: []string(nil),
|
||||
regex: `\* (?P<version>.+)\n`,
|
||||
},
|
||||
asdfToolName: {
|
||||
executable: asdfToolName,
|
||||
args: []string{"current", rubyToolName},
|
||||
regex: `ruby\s+(?P<version>[^\s]+)\s+`,
|
||||
},
|
||||
rubyToolName: {
|
||||
executable: rubyToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: `ruby\s+(?P<version>[^\s]+)\s+`,
|
||||
},
|
||||
},
|
||||
defaultTooling: []string{rbenvToolName, rvmPromptToolName, chrubyToolName, asdfToolName, rubyToolName},
|
||||
// asdf reports "______" when no version is set for the tool; that isn't a version, it's an absence of one.
|
||||
sanitizeVersion: func(version string) string {
|
||||
if version == "______" {
|
||||
return ""
|
||||
}
|
||||
return version
|
||||
},
|
||||
},
|
||||
"clojure": {
|
||||
extensions: []string{
|
||||
"project.clj",
|
||||
"deps.edn",
|
||||
"build.boot",
|
||||
"bb.edn",
|
||||
"*.clj",
|
||||
"*.cljc",
|
||||
"*.cljs",
|
||||
},
|
||||
tooling: map[string]*cmd{
|
||||
clojureToolName: {
|
||||
executable: clojureToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: `Clojure CLI version (?P<version>(?P<major>[0-9]+)\.(?P<minor>[0-9]+)\.(?P<patch>[0-9]+)(?:\.(?P<build>[0-9]+))?)`,
|
||||
},
|
||||
leinToolName: {
|
||||
executable: leinToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: `Leiningen (?P<version>(?P<major>[0-9]+)\.(?P<minor>[0-9]+)\.(?P<patch>[0-9]+))`,
|
||||
},
|
||||
},
|
||||
defaultTooling: []string{clojureToolName, leinToolName},
|
||||
},
|
||||
"crystal": {
|
||||
extensions: []string{"*.cr", "shard.yml"},
|
||||
tooling: map[string]*cmd{
|
||||
crystalToolName: {
|
||||
executable: crystalToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: `Crystal ` + versionRegex,
|
||||
},
|
||||
},
|
||||
defaultTooling: []string{crystalToolName},
|
||||
versionURLTemplate: "https://github.com/crystal-lang/crystal/releases/tag/{{ .Full }}",
|
||||
},
|
||||
"elixir": {
|
||||
extensions: []string{"*.ex", "*.exs"},
|
||||
tooling: map[string]*cmd{
|
||||
asdfToolName: {
|
||||
executable: asdfToolName,
|
||||
args: []string{"current", elixirToolName},
|
||||
regex: `elixir\s+` + versionRegex + `[^\s]*\s+`,
|
||||
},
|
||||
elixirToolName: {
|
||||
executable: elixirToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: `Elixir ` + versionRegex,
|
||||
},
|
||||
},
|
||||
defaultTooling: []string{asdfToolName, elixirToolName},
|
||||
versionURLTemplate: "https://github.com/elixir-lang/elixir/releases/tag/v{{ .Full }}",
|
||||
},
|
||||
"julia": {
|
||||
extensions: []string{"*.jl"},
|
||||
tooling: map[string]*cmd{
|
||||
juliaToolName: {
|
||||
executable: juliaToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: `julia version ` + versionRegex,
|
||||
},
|
||||
},
|
||||
defaultTooling: []string{juliaToolName},
|
||||
versionURLTemplate: "https://github.com/JuliaLang/julia/releases/tag/v{{ .Full }}",
|
||||
},
|
||||
"kotlin": {
|
||||
extensions: []string{"*.kt", "*.kts", "*.ktm"},
|
||||
tooling: map[string]*cmd{
|
||||
kotlinToolName: {
|
||||
executable: kotlinToolName,
|
||||
args: []string{versionFlagShortArg},
|
||||
regex: `Kotlin version ` + versionRegex,
|
||||
},
|
||||
},
|
||||
defaultTooling: []string{kotlinToolName},
|
||||
versionURLTemplate: "https://github.com/JetBrains/kotlin/releases/tag/v{{ .Full }}",
|
||||
},
|
||||
"lua": {
|
||||
extensions: []string{"*.lua", "*.rockspec"},
|
||||
folders: []string{"lua"},
|
||||
tooling: map[string]*cmd{
|
||||
luaToolName: {
|
||||
executable: luaToolName,
|
||||
args: []string{"-v"},
|
||||
regex: `Lua (?P<version>((?P<major>[0-9]+).(?P<minor>[0-9]+)(.(?P<patch>[0-9]+))?))`,
|
||||
versionURLTemplate: "https://www.lua.org/manual/{{ .Major }}.{{ .Minor }}/readme.html#changes",
|
||||
},
|
||||
luajitToolName: {
|
||||
executable: luajitToolName,
|
||||
args: []string{"-v"},
|
||||
regex: `LuaJIT (?P<version>((?P<major>[0-9]+).(?P<minor>[0-9]+)(.(?P<patch>[0-9]+))?))`,
|
||||
versionURLTemplate: "https://github.com/LuaJIT/LuaJIT/tree/v{{ .Major}}.{{ .Minor}}",
|
||||
},
|
||||
},
|
||||
defaultTooling: []string{luaToolName, luajitToolName},
|
||||
},
|
||||
"nim": {
|
||||
extensions: []string{"*.nim", "*.nims"},
|
||||
tooling: map[string]*cmd{
|
||||
nimToolName: {
|
||||
executable: nimToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: `Nim Compiler Version (?P<version>(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+))`,
|
||||
},
|
||||
},
|
||||
defaultTooling: []string{nimToolName},
|
||||
},
|
||||
"ocaml": {
|
||||
extensions: []string{"*.ml", "*.mli", "dune", "dune-project", "dune-workspace"},
|
||||
tooling: map[string]*cmd{
|
||||
ocamlToolName: {
|
||||
executable: ocamlToolName,
|
||||
args: []string{versionFlagShortArg},
|
||||
regex: `The OCaml toplevel, version (?P<version>((?P<major>[0-9]+).(?P<minor>[0-9]+).(?P<patch>[0-9]+))(-(?P<prerelease>[a-z]+))?)`,
|
||||
},
|
||||
},
|
||||
defaultTooling: []string{ocamlToolName},
|
||||
},
|
||||
"perl": {
|
||||
extensions: []string{".perl-version", "*.pl", "*.pm", "*.t"},
|
||||
tooling: map[string]*cmd{
|
||||
perlToolName: {
|
||||
executable: perlToolName,
|
||||
args: []string{versionFlagShortArg},
|
||||
regex: `This is perl.*v(?P<version>(?P<major>[0-9]+)(?:\.(?P<minor>[0-9]+))(?:\.(?P<patch>[0-9]+))?).* built for .+`,
|
||||
},
|
||||
},
|
||||
defaultTooling: []string{perlToolName},
|
||||
},
|
||||
"php": {
|
||||
extensions: []string{"*.php", "composer.json", "composer.lock", ".php-version", "blade.php"},
|
||||
tooling: map[string]*cmd{
|
||||
phpToolName: {
|
||||
executable: phpToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: `(?:PHP (?P<version>((?P<major>[0-9]+).(?P<minor>[0-9]+).(?P<patch>[0-9]+))))`,
|
||||
},
|
||||
},
|
||||
defaultTooling: []string{phpToolName},
|
||||
versionURLTemplate: "https://www.php.net/ChangeLog-{{ .Major }}.php#PHP_{{ .Major }}_{{ .Minor }}",
|
||||
},
|
||||
"r": {
|
||||
extensions: []string{"*.R", "*.Rmd", "*.Rsx", "*.Rda", "*.Rd", "*.Rproj", ".Rproj.user"},
|
||||
tooling: map[string]*cmd{
|
||||
rscriptToolName: {
|
||||
executable: rscriptToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: `version ` + versionRegex,
|
||||
},
|
||||
"R": {
|
||||
executable: "R",
|
||||
args: []string{versionFlagArg},
|
||||
regex: `version ` + versionRegex,
|
||||
},
|
||||
rExeToolName: {
|
||||
executable: rExeToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: `version ` + versionRegex,
|
||||
},
|
||||
},
|
||||
defaultTooling: []string{rscriptToolName, "R", rExeToolName},
|
||||
versionURLTemplate: "https://www.r-project.org/",
|
||||
},
|
||||
"rust": {
|
||||
extensions: []string{"*.rs", "Cargo.toml", "Cargo.lock"},
|
||||
tooling: map[string]*cmd{
|
||||
rustcToolName: {
|
||||
executable: rustcToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: `(rust version|rustc) (?P<version>((?P<major>[0-9]+).(?P<minor>[0-9]+).(?P<patch>[0-9]+))(-(?P<prerelease>[a-z]+))?)(( \((?P<buildmetadata>[0-9a-f]+ [0-9]+-[0-9]+-[0-9]+)\))?)`, //nolint:lll
|
||||
},
|
||||
},
|
||||
defaultTooling: []string{rustcToolName},
|
||||
},
|
||||
"swift": {
|
||||
extensions: []string{"*.swift", "*.SWIFT", "Podfile"},
|
||||
tooling: map[string]*cmd{
|
||||
swiftToolName: {
|
||||
executable: swiftToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: `Swift version (?P<version>((?P<major>[0-9]+).(?P<minor>[0-9]+)((.|-)(?P<patch>[0-9]+|dev))?))`,
|
||||
},
|
||||
},
|
||||
defaultTooling: []string{swiftToolName},
|
||||
versionURLTemplate: "https://github.com/apple/swift/releases/tag/swift-{{ .Full }}-RELEASE",
|
||||
},
|
||||
"v": {
|
||||
extensions: []string{"*.v"},
|
||||
tooling: map[string]*cmd{
|
||||
"v": {
|
||||
executable: "v",
|
||||
args: []string{"--version"},
|
||||
regex: `V (?P<version>(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)) [a-f0-9]+`,
|
||||
},
|
||||
},
|
||||
defaultTooling: []string{"v"},
|
||||
},
|
||||
"vala": {
|
||||
extensions: []string{"*.vala"},
|
||||
tooling: map[string]*cmd{
|
||||
valaToolName: {
|
||||
executable: valaToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: `Vala (?P<version>((?P<major>[0-9]+).(?P<minor>[0-9]+).(?P<patch>[0-9]+)))`,
|
||||
},
|
||||
},
|
||||
defaultTooling: []string{valaToolName},
|
||||
versionURLTemplate: "https://gitlab.gnome.org/GNOME/vala/raw/{{ .Major }}.{{ .Minor }}/NEWS",
|
||||
},
|
||||
"zig": {
|
||||
extensions: []string{"*.zig", "*.zon"},
|
||||
projectFiles: []string{"build.zig"},
|
||||
tooling: map[string]*cmd{
|
||||
zigToolName: {
|
||||
executable: zigToolName,
|
||||
args: []string{versionArg},
|
||||
regex: `(?P<version>(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?)`, //nolint:lll
|
||||
},
|
||||
},
|
||||
defaultTooling: []string{zigToolName},
|
||||
versionURLTemplate: "https://ziglang.org/download/{{ .Major }}.{{ .Minor }}.{{ .Patch }}/release-notes.html",
|
||||
},
|
||||
"dart": {
|
||||
extensions: []string{"*.dart", pubspecFileName, "pubspec.yml", "pubspec.lock"},
|
||||
folders: []string{".dart_tool"},
|
||||
tooling: map[string]*cmd{
|
||||
fvmToolName: {
|
||||
executable: fvmToolName,
|
||||
args: []string{dartToolName, versionFlagArg},
|
||||
regex: `Dart SDK version: ` + versionRegex,
|
||||
},
|
||||
dartToolName: {
|
||||
executable: dartToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: `Dart SDK version: ` + versionRegex,
|
||||
},
|
||||
},
|
||||
defaultTooling: []string{fvmToolName, dartToolName},
|
||||
versionURLTemplate: "https://dart.dev/guides/language/evolution#dart-{{ .Major }}{{ .Minor }}",
|
||||
},
|
||||
}
|
||||
|
||||
// ConfiguredLanguage is a generic Language segment driven entirely by data: a built-in preset
|
||||
// looked up by name, and/or a user-supplied `tools` option. It backs both the migrated
|
||||
// single-purpose segment types (which set name via NewLanguage) and the public
|
||||
// "language" segment type (which reads name from the `name` option).
|
||||
type ConfiguredLanguage struct {
|
||||
Language
|
||||
}
|
||||
|
||||
func (c *ConfiguredLanguage) Template() string {
|
||||
return languageTemplate
|
||||
}
|
||||
|
||||
// NewLanguage returns a ConfiguredLanguage preset to the built-in definition
|
||||
// registered under name. Used by segment_types.go to back the migrated segment types.
|
||||
func NewLanguage(name string) *ConfiguredLanguage {
|
||||
c := &ConfiguredLanguage{}
|
||||
c.name = name
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *ConfiguredLanguage) Enabled() bool {
|
||||
if c.name == "" {
|
||||
c.name = c.options.String(LanguageName, "")
|
||||
}
|
||||
|
||||
if preset, ok := languageDefinitions[c.name]; ok {
|
||||
c.extensions = preset.extensions
|
||||
c.projectFiles = preset.projectFiles
|
||||
c.folders = preset.folders
|
||||
c.tooling = preset.tooling
|
||||
c.defaultTooling = preset.defaultTooling
|
||||
c.versionURLTemplate = preset.versionURLTemplate
|
||||
}
|
||||
|
||||
c.applyCustomTools()
|
||||
|
||||
enabled := c.Language.Enabled()
|
||||
|
||||
if preset, ok := languageDefinitions[c.name]; ok && preset.sanitizeVersion != nil {
|
||||
c.Full = preset.sanitizeVersion(c.Full)
|
||||
}
|
||||
|
||||
return enabled
|
||||
}
|
||||
|
||||
// applyCustomTools reads the `tools` option (a list of {name, executable, args, regex,
|
||||
// version_url_template}) and merges it into the tooling map. For presets, this lets a user
|
||||
// add or override a tool. For the public "language" segment type, which has no preset, this
|
||||
// is the only source of tooling, and its declaration order becomes the default tool order.
|
||||
func (c *ConfiguredLanguage) applyCustomTools() {
|
||||
raw, ok := c.options.Any(Tools, nil).([]any)
|
||||
if !ok || len(raw) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if c.tooling == nil {
|
||||
c.tooling = make(map[string]*cmd, len(raw))
|
||||
}
|
||||
|
||||
order := make([]string, 0, len(raw))
|
||||
|
||||
for _, item := range raw {
|
||||
entry, ok := toStringMap(item)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
name := stringField(entry, "name")
|
||||
if name == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
c.tooling[name] = &cmd{
|
||||
executable: stringField(entry, "executable"),
|
||||
args: options.ParseStringArray(entry["args"]),
|
||||
regex: stringField(entry, "regex"),
|
||||
versionURLTemplate: stringField(entry, "version_url_template"),
|
||||
}
|
||||
order = append(order, name)
|
||||
}
|
||||
|
||||
if _, hasPreset := languageDefinitions[c.name]; !hasPreset {
|
||||
c.defaultTooling = order
|
||||
}
|
||||
}
|
||||
|
||||
func toStringMap(value any) (map[string]any, bool) {
|
||||
switch v := value.(type) {
|
||||
case map[string]any:
|
||||
return v, true
|
||||
case map[any]any:
|
||||
out := make(map[string]any, len(v))
|
||||
for key, val := range v {
|
||||
out[fmt.Sprint(key)] = val
|
||||
}
|
||||
return out, true
|
||||
default:
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
|
||||
func stringField(entry map[string]any, key string) string {
|
||||
value, ok := entry[key]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprint(value)
|
||||
}
|
||||
@@ -0,0 +1,850 @@
|
||||
package segments
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/cache"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/segments/options"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/template"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestConfiguredLanguageFortranPreset(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
}{
|
||||
{
|
||||
Case: "GNU Fortran 10.2.1 Debian",
|
||||
ExpectedString: "10.2.1",
|
||||
Version: `GNU Fortran (Debian 10.2.1-6) 10.2.1 20210110
|
||||
Copyright (C) 2020 Free Software Foundation, Inc.
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.`,
|
||||
},
|
||||
{
|
||||
Case: "GNU Fortran 11.4.0 Ubuntu",
|
||||
ExpectedString: "11.4.0",
|
||||
Version: `GNU Fortran (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
|
||||
Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "gfortran",
|
||||
versionParam: "--version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.f",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
|
||||
f := NewLanguage("fortran")
|
||||
f.Init(props, env)
|
||||
|
||||
assert.True(t, f.Enabled(), tc.Case)
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, f.Template(), f), tc.Case)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfiguredLanguageRubyPreset(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
HasRbenv bool
|
||||
HasRvmprompt bool
|
||||
HasChruby bool
|
||||
HasAsdf bool
|
||||
HasRuby bool
|
||||
HasRubyFiles bool
|
||||
HasRakeFile bool
|
||||
HasGemFile bool
|
||||
FetchVersion bool
|
||||
}{
|
||||
{Case: "Ruby files", ExpectedString: "", FetchVersion: false, HasRubyFiles: true},
|
||||
{Case: "Rakefile", ExpectedString: "", FetchVersion: false, HasRakeFile: true},
|
||||
{Case: "Gemfile", ExpectedString: "", FetchVersion: false, HasGemFile: true},
|
||||
{Case: "Gemfile with version", ExpectedString: "err parsing info from ruby with", FetchVersion: true, HasGemFile: true},
|
||||
{
|
||||
Case: "Version with chruby",
|
||||
ExpectedString: "ruby-2.6.3",
|
||||
FetchVersion: true,
|
||||
HasRubyFiles: true,
|
||||
HasChruby: true,
|
||||
Version: ` * ruby-2.6.3
|
||||
ruby-1.9.3-p392
|
||||
jruby-1.7.0
|
||||
rubinius-2.0.0-rc1`,
|
||||
},
|
||||
{
|
||||
Case: "Version with chruby line 2",
|
||||
ExpectedString: "ruby-1.9.3-p392",
|
||||
FetchVersion: true,
|
||||
HasRubyFiles: true,
|
||||
HasChruby: true,
|
||||
Version: ` ruby-2.6.3
|
||||
* ruby-1.9.3-p392
|
||||
jruby-1.7.0
|
||||
rubinius-2.0.0-rc1`,
|
||||
},
|
||||
{
|
||||
Case: "Version with asdf",
|
||||
ExpectedString: "2.6.3",
|
||||
FetchVersion: true,
|
||||
HasRubyFiles: true,
|
||||
HasAsdf: true,
|
||||
Version: "ruby 2.6.3 /Users/jan/Projects/oh-my-posh/.tool-versions",
|
||||
},
|
||||
{
|
||||
Case: "Version with asdf not set",
|
||||
ExpectedString: "",
|
||||
FetchVersion: true,
|
||||
HasRubyFiles: true,
|
||||
HasAsdf: true,
|
||||
Version: "ruby ______ No version set. Run \"asdf <global|shell|local> ruby <version>\"",
|
||||
},
|
||||
{
|
||||
Case: "Version with ruby",
|
||||
ExpectedString: "2.6.3",
|
||||
FetchVersion: true,
|
||||
HasRubyFiles: true,
|
||||
HasRuby: true,
|
||||
Version: "ruby 2.6.3 (2019-04-16 revision 67580) [universal.x86_64-darwin20]",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "ruby",
|
||||
versionParam: "--version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.rb",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
|
||||
env.On("HasCommand", "rbenv").Return(tc.HasRbenv)
|
||||
env.On("RunCommandWithEnv", "rbenv", []string(nil), []string{"version-name"}).Return(tc.Version, nil)
|
||||
env.On("HasCommand", "rvm-prompt").Return(tc.HasRvmprompt)
|
||||
env.On("RunCommandWithEnv", "rvm-prompt", []string(nil), []string{"i", "v", "g"}).Return(tc.Version, nil)
|
||||
env.On("HasCommand", "chruby").Return(tc.HasChruby)
|
||||
env.On("RunCommandWithEnv", "chruby", []string(nil), []string(nil)).Return(tc.Version, nil)
|
||||
env.On("HasCommand", "asdf").Return(tc.HasAsdf)
|
||||
env.On("RunCommandWithEnv", "asdf", []string(nil), []string{"current", "ruby"}).Return(tc.Version, nil)
|
||||
env.On("HasFiles", "Rakefile").Return(tc.HasRakeFile)
|
||||
env.On("HasFiles", "Gemfile").Return(tc.HasGemFile)
|
||||
|
||||
props[options.FetchVersion] = tc.FetchVersion
|
||||
|
||||
ruby := NewLanguage("ruby")
|
||||
ruby.Init(props, env)
|
||||
|
||||
assert.True(t, ruby.Enabled(), tc.Case)
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, ruby.Template(), ruby), tc.Case)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfiguredLanguageClojurePreset(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
Cmd string
|
||||
}{
|
||||
{
|
||||
Case: "Clojure CLI 1.11.1.1113",
|
||||
ExpectedString: "1.11.1.1113",
|
||||
Version: "Clojure CLI version 1.11.1.1113",
|
||||
Cmd: "clojure",
|
||||
},
|
||||
{
|
||||
Case: "Leiningen 2.9.8",
|
||||
ExpectedString: "2.9.8",
|
||||
Version: "Leiningen 2.9.8 on Java 11.0.11 OpenJDK 64-Bit Server VM",
|
||||
Cmd: "lein",
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: tc.Cmd,
|
||||
versionParam: "--version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.clj",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
props[LanguageExtensions] = []string{params.extension}
|
||||
if tc.Cmd != "clojure" {
|
||||
env.On("HasCommand", "clojure").Return(false)
|
||||
}
|
||||
c := NewLanguage("clojure")
|
||||
c.Init(props, env)
|
||||
assert.True(t, c.Enabled(), tc.Case)
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, c.Template(), c), tc.Case)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfiguredLanguageCrystalPreset(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
}{
|
||||
{Case: "Crystal 1.0.0", ExpectedString: "1.0.0", Version: "Crystal 1.0.0 (2021-03-22)"},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "crystal",
|
||||
versionParam: "--version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.cr",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
c := NewLanguage("crystal")
|
||||
c.Init(props, env)
|
||||
assert.True(t, c.Enabled(), tc.Case)
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, c.Template(), c), tc.Case)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfiguredLanguageElixirPreset(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
ElixirVersionOutput string
|
||||
AsdfVersionOutput string
|
||||
HasAsdf bool
|
||||
AsdfExitCode int
|
||||
}{
|
||||
{
|
||||
Case: "Version without asdf",
|
||||
ExpectedString: "1.14.2",
|
||||
ElixirVersionOutput: "Erlang/OTP 25 [erts-13.1.3] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit] [dtrace]\n\nElixir 1.14.2 (compiled with Erlang/OTP 25)",
|
||||
},
|
||||
{
|
||||
Case: "Version with asdf",
|
||||
ExpectedString: "1.14.2",
|
||||
HasAsdf: true,
|
||||
AsdfVersionOutput: "elixir 1.14.2-otp-25 /path/to/.tool-versions",
|
||||
ElixirVersionOutput: "Should not be used",
|
||||
},
|
||||
{
|
||||
Case: "Version with asdf not set: should fall back to elixir --version",
|
||||
ExpectedString: "1.14.2",
|
||||
HasAsdf: true,
|
||||
AsdfVersionOutput: "elixir ______ No version is set. Run \"asdf <global|shell|local> elixir <version>\"",
|
||||
AsdfExitCode: 126,
|
||||
ElixirVersionOutput: "Erlang/OTP 25 [erts-13.1.3] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit] [dtrace]\n\nElixir 1.14.2 (compiled with Erlang/OTP 25)",
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "elixir",
|
||||
versionParam: "--version",
|
||||
versionOutput: tc.ElixirVersionOutput,
|
||||
extension: "*.ex",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
|
||||
env.On("HasCommand", "asdf").Return(tc.HasAsdf)
|
||||
var asdfErr error
|
||||
if tc.AsdfExitCode != 0 {
|
||||
asdfErr = &runtime.CommandError{ExitCode: tc.AsdfExitCode}
|
||||
}
|
||||
env.On("RunCommandWithEnv", "asdf", []string(nil), []string{"current", "elixir"}).Return(tc.AsdfVersionOutput, asdfErr)
|
||||
|
||||
r := NewLanguage("elixir")
|
||||
r.Init(props, env)
|
||||
assert.True(t, r.Enabled(), tc.Case)
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, r.Template(), r), tc.Case)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfiguredLanguageJuliaPreset(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
}{
|
||||
{Case: "Julia 1.6.0", ExpectedString: "1.6.0", Version: "julia version 1.6.0"},
|
||||
{Case: "Julia 1.6.1", ExpectedString: "1.6.1", Version: "julia version 1.6.1"},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "julia",
|
||||
versionParam: "--version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.jl",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
j := NewLanguage("julia")
|
||||
j.Init(props, env)
|
||||
assert.True(t, j.Enabled(), tc.Case)
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, j.Template(), j), tc.Case)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfiguredLanguageKotlinPreset(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
}{
|
||||
{Case: "Kotlin 1.6.10", ExpectedString: "1.6.10", Version: "Kotlin version 1.6.10-release-923 (JRE 17.0.2+0)"},
|
||||
{Case: "Kotlin 1.6.0", ExpectedString: "1.6.0", Version: "Kotlin version 1.6.0-release-915 (JRE 17.0.2+0)"},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "kotlin",
|
||||
versionParam: "-version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.kt",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
k := NewLanguage("kotlin")
|
||||
k.Init(props, env)
|
||||
assert.True(t, k.Enabled(), tc.Case)
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, k.Template(), k), tc.Case)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfiguredLanguageLuaPreset(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
ExpectedURL string
|
||||
Tooling []string
|
||||
HasLua bool
|
||||
HasLuaJit bool
|
||||
}{
|
||||
{
|
||||
Case: "Lua 5.4.4 - default tooling prefers lua",
|
||||
ExpectedString: "5.4.4",
|
||||
Version: "Lua 5.4.4 Copyright (C) 1994-2022 Lua.org, PUC-Rio",
|
||||
ExpectedURL: "https://www.lua.org/manual/5.4/readme.html#changes",
|
||||
HasLua: true,
|
||||
HasLuaJit: true,
|
||||
},
|
||||
{
|
||||
Case: "Lua 5.0 - tooling set to luajit but missing so fallback to lua",
|
||||
ExpectedString: "5.0",
|
||||
Version: "Lua 5.0 Copyright (C) 1994-2003 Tecgraf, PUC-Rio",
|
||||
ExpectedURL: "https://www.lua.org/manual/5.0/readme.html#changes",
|
||||
HasLua: true,
|
||||
Tooling: []string{"luajit", "lua"},
|
||||
},
|
||||
{
|
||||
Case: "LuaJIT 2.0.5 - tooling set to luajit first",
|
||||
ExpectedString: "2.0.5",
|
||||
Version: "LuaJIT 2.0.5 -- Copyright (C) 2005-2017 Mike Pall. http://luajit.org/",
|
||||
HasLuaJit: true,
|
||||
HasLua: true,
|
||||
ExpectedURL: "https://github.com/LuaJIT/LuaJIT/tree/v2.0",
|
||||
Tooling: []string{"luajit"},
|
||||
},
|
||||
{
|
||||
Case: "LuaJIT 2.1.0-beta3 - tooling set to lua first but missing so try luajit",
|
||||
ExpectedString: "2.1.0",
|
||||
Version: "LuaJIT 2.1.0-beta3 -- Copyright (C) 2005-2017 Mike Pall. http://luajit.org/",
|
||||
HasLuaJit: true,
|
||||
ExpectedURL: "https://github.com/LuaJIT/LuaJIT/tree/v2.1",
|
||||
Tooling: []string{"lua", "luajit"},
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "lua",
|
||||
versionParam: "-v",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.lua",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
|
||||
if !tc.HasLua {
|
||||
env.Unset("HasCommand")
|
||||
env.On("HasCommand", "lua").Return(false)
|
||||
}
|
||||
|
||||
env.On("HasCommand", "luajit").Return(tc.HasLuaJit)
|
||||
env.On("RunCommandWithEnv", "luajit", []string(nil), []string{"-v"}).Return(tc.Version, nil)
|
||||
env.On("Shell").Return("bash")
|
||||
|
||||
// Initialize template system for version URL rendering
|
||||
if template.Cache == nil {
|
||||
template.Cache = &cache.Template{}
|
||||
}
|
||||
template.Init(env, nil, nil)
|
||||
|
||||
if len(tc.Tooling) > 0 {
|
||||
props[Tooling] = tc.Tooling
|
||||
}
|
||||
|
||||
l := NewLanguage("lua")
|
||||
l.Init(props, env)
|
||||
|
||||
failMsg := tc.Case
|
||||
assert.True(t, l.Enabled(), failMsg)
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, l.Template(), l), failMsg)
|
||||
assert.Equal(t, tc.ExpectedURL, l.URL, failMsg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfiguredLanguageNimPreset(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
}{
|
||||
{
|
||||
Case: "Nim 2.2.0",
|
||||
ExpectedString: "2.2.0",
|
||||
Version: "Nim Compiler Version 2.2.0 [MacOSX: arm64]\nCompiled at 2024-11-30\nCopyright (c) 2006-2024 by Andreas Rumpf",
|
||||
},
|
||||
{
|
||||
Case: "Nim 1.6.12",
|
||||
ExpectedString: "1.6.12",
|
||||
Version: "Nim Compiler Version 1.6.12 [Linux: amd64]\nCompiled at 2023-06-15\nCopyright (c) 2006-2023 by Andreas Rumpf",
|
||||
},
|
||||
{
|
||||
Case: "Nim 2.0.0",
|
||||
ExpectedString: "2.0.0",
|
||||
Version: "Nim Compiler Version 2.0.0 [Windows: amd64]\nCompiled at 2023-12-25\nCopyright (c) 2006-2023 by Andreas Rumpf",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "nim",
|
||||
versionParam: "--version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.nim",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
|
||||
n := NewLanguage("nim")
|
||||
n.Init(props, env)
|
||||
|
||||
assert.True(t, n.Enabled(), tc.Case)
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, n.Template(), n), tc.Case)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfiguredLanguageOCamlPreset(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
}{
|
||||
{Case: "OCaml 4.12.0", ExpectedString: "4.12.0", Version: "The OCaml toplevel, version 4.12.0"},
|
||||
{Case: "OCaml 4.11.0", ExpectedString: "4.11.0", Version: "The OCaml toplevel, version 4.11.0"},
|
||||
{Case: "OCaml 4.13.0", ExpectedString: "4.13.0", Version: "The OCaml toplevel, version 4.13.0"},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "ocaml",
|
||||
versionParam: "-version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.ml",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
|
||||
o := NewLanguage("ocaml")
|
||||
o.Init(props, env)
|
||||
|
||||
assert.True(t, o.Enabled(), tc.Case)
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, o.Template(), o), tc.Case)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfiguredLanguagePerlPreset(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
}{
|
||||
{
|
||||
Case: "v5.12+",
|
||||
ExpectedString: "5.32.1",
|
||||
Version: "This is perl 5, version 32, subversion 1 (v5.32.1) built for MSWin32-x64-multi-thread",
|
||||
},
|
||||
{
|
||||
Case: "v5.6 - v5.10",
|
||||
ExpectedString: "5.6.1",
|
||||
Version: "This is perl, v5.6.1 built for MSWin32-x86-multi-thread",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "perl",
|
||||
versionParam: "-version",
|
||||
versionOutput: tc.Version,
|
||||
extension: ".perl-version",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
|
||||
p := NewLanguage("perl")
|
||||
p.Init(props, env)
|
||||
|
||||
assert.True(t, p.Enabled(), tc.Case)
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, p.Template(), p), tc.Case)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfiguredLanguagePhpPreset(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
}{
|
||||
{Case: "PHP 6.1.0", ExpectedString: "6.1.0", Version: "PHP 6.1.0(cli) (built: Jul 2 2021 03:59:48) ( NTS )"},
|
||||
{Case: "php 7.4.21", ExpectedString: "7.4.21", Version: "PHP 7.4.21 (cli) (built: Jul 2 2021 03:59:48) ( NTS )"},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "php",
|
||||
versionParam: "--version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.php",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
|
||||
j := NewLanguage("php")
|
||||
j.Init(props, env)
|
||||
|
||||
assert.True(t, j.Enabled(), tc.Case)
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, j.Template(), j), tc.Case)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfiguredLanguageRPreset(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
HasRscript bool
|
||||
HasR bool
|
||||
HasRexe bool
|
||||
}{
|
||||
{Case: "Rscript 4.2.0", ExpectedString: "4.2.0", HasRscript: true, Version: "Rscript (R) version 4.2.0 (2022-04-22)"},
|
||||
{Case: "Rscript 4.1.3", ExpectedString: "4.1.3", HasRscript: true, Version: "R scripting front-end version 4.1.3 (2022-03-10)"},
|
||||
{Case: "Rscript 4.1.3 patched", ExpectedString: "4.1.3", HasRscript: true, Version: "R scripting front-end version 4.1.3 Patched (2022-03-10 r81896)"},
|
||||
{Case: "Rscript 4.0.0", ExpectedString: "4.0.0", HasRscript: true, Version: "R scripting front-end version 4.0.0 (2020-04-24)"},
|
||||
{Case: "Rscript devel", ExpectedString: "4.2.0", HasRscript: true, Version: "R scripting front-end version 4.2.0 Under development (unstable) (2022-03-14 r81896)"},
|
||||
|
||||
{Case: "R 4.1.2", ExpectedString: "4.1.2", HasR: true, Version: "R version 4.1.2 (2021-11-01) -- \"Bird Hippie\""},
|
||||
{Case: "R 4.1.3 patched", ExpectedString: "4.1.3", HasR: true, Version: "R version 4.1.3 Patched (2022-03-10 r81896) -- \"One Push-Up\""},
|
||||
{Case: "R 4.0.0", ExpectedString: "4.0.0", HasR: true, Version: "R version 4.0.0 (2020-04-24) -- \"Arbor Day\""},
|
||||
|
||||
{Case: "R.exe 4.1.2", ExpectedString: "4.1.2", HasRexe: true, Version: "R version 4.1.2 (2021-11-01) -- \"Bird Hippie\""},
|
||||
{Case: "R.exe 4.1.3 patched", ExpectedString: "4.1.3", HasRexe: true, Version: "R version 4.1.3 Patched (2022-03-10 r81896) -- \"One Push-Up\""},
|
||||
{Case: "R.exe 4.0.0", ExpectedString: "4.0.0", HasRexe: true, Version: "R version 4.0.0 (2020-04-24) -- \"Arbor Day\""},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "R",
|
||||
versionParam: "--version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.R",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
|
||||
env.On("HasCommand", "Rscript").Return(tc.HasRscript)
|
||||
env.On("RunCommandWithEnv", "Rscript", []string(nil), []string{"--version"}).Return(tc.Version, nil)
|
||||
env.On("HasCommand", "R.exe").Return(tc.HasRexe)
|
||||
env.On("RunCommandWithEnv", "R.exe", []string(nil), []string{"--version"}).Return(tc.Version, nil)
|
||||
|
||||
r := NewLanguage("r")
|
||||
r.Init(props, env)
|
||||
|
||||
assert.True(t, r.Enabled(), tc.Case)
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, r.Template(), r), tc.Case)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfiguredLanguageRustPreset(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
}{
|
||||
{Case: "Rust 1.64.0", ExpectedString: "1.64.0", Version: "rustc 1.64.0"},
|
||||
{Case: "Rust 1.53.0", ExpectedString: "1.53.0", Version: "rustc 1.53.0 (4369396ce 2021-04-27)"},
|
||||
{Case: "Rust 1.66.0", ExpectedString: "1.66.0-nightly", Version: "rustc 1.66.0-nightly (01af5040f 2022-10-04)"},
|
||||
{
|
||||
Case: "Toolchain not installed",
|
||||
ExpectedString: "1.81.0",
|
||||
Version: ` info: syncing channel updates for '1.81.0-x86_64-pc-windows-msvc'
|
||||
info: latest update on 2024-09-05, rust version 1.81.0 (eeb90cda1 2024-09-04)
|
||||
info: downloading component 'cargo'
|
||||
info: downloading component 'clippy'
|
||||
info: downloading component 'rust-analyzer'
|
||||
info: downloading component 'rust-src'
|
||||
info: downloading component 'rust-std'
|
||||
info: downloading component 'rustc'
|
||||
info: downloading component 'rustfmt'
|
||||
info: installing component 'cargo'
|
||||
info: installing component 'clippy'
|
||||
info: installing component 'rust-analyzer'
|
||||
info: installing component 'rust-src'
|
||||
info: installing component 'rust-std'
|
||||
info: installing component 'rustc'`,
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "rustc",
|
||||
versionParam: "--version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.rs",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
r := NewLanguage("rust")
|
||||
r.Init(props, env)
|
||||
assert.True(t, r.Enabled(), tc.Case)
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, r.Template(), r), tc.Case)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfiguredLanguageSwiftPreset(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
}{
|
||||
{Case: "Swift 5.5.3", ExpectedString: "5.5.3", Version: "Swift version 5.5.3 (swift-5.5.3-RELEASE)"},
|
||||
{Case: "Swift 5.5.3 on Windows", ExpectedString: "5.5.3", Version: "compnerd.org Swift version 5.5.3 (swift-5.5.3-RELEASE)"},
|
||||
{Case: "Swift 5.5.3 on Mac", ExpectedString: "5.5.3", Version: "Apple Swift version 5.5.3 (swift-5.5.3-RELEASE)"},
|
||||
{Case: "Swift 5.5", ExpectedString: "5.5", Version: "Swift version 5.5 (swift-5.5-RELEASE)"},
|
||||
{Case: "Swift 5.6-dev", ExpectedString: "5.6-dev", Version: "Swift version 5.6-dev (LLVM 62b900d3d0d5be9, Swift ce64fe8867792d4)"},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "swift",
|
||||
versionParam: "--version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.swift",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
s := NewLanguage("swift")
|
||||
s.Init(props, env)
|
||||
assert.True(t, s.Enabled(), tc.Case)
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, s.Template(), s), tc.Case)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfiguredLanguageVPreset(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
}{
|
||||
{
|
||||
Case: "V 0.4.9",
|
||||
ExpectedString: "0.4.9",
|
||||
Version: "V 0.4.9 b487986",
|
||||
},
|
||||
{
|
||||
Case: "V 0.4.8",
|
||||
ExpectedString: "0.4.8",
|
||||
Version: "V 0.4.8 a123456",
|
||||
},
|
||||
{
|
||||
Case: "V 0.4.7",
|
||||
ExpectedString: "0.4.7",
|
||||
Version: "V 0.4.7 f789012",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "v",
|
||||
versionParam: "--version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.v",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
v := NewLanguage("v")
|
||||
v.Init(props, env)
|
||||
assert.True(t, v.Enabled(), tc.Case)
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, v.Template(), v), tc.Case)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfiguredLanguageValaPreset(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
}{
|
||||
{
|
||||
Case: "vala 0.48.17",
|
||||
ExpectedString: "0.48.17",
|
||||
Version: "Vala 0.48.17",
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "vala",
|
||||
versionParam: "--version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.vala",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
v := NewLanguage("vala")
|
||||
v.Init(props, env)
|
||||
assert.True(t, v.Enabled(), tc.Case)
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, v.Template(), v), tc.Case)
|
||||
}
|
||||
}
|
||||
|
||||
// TestConfiguredLanguageCustomTools exercises the `tools` option path used by the public
|
||||
// "language" segment type, which has no built-in preset and relies entirely on user config.
|
||||
func TestConfiguredLanguageCustomTools(t *testing.T) {
|
||||
env := new(mock.Environment)
|
||||
env.On("HasCommand", "mytool").Return(true)
|
||||
env.On("RunCommandWithEnv", "mytool", []string(nil), []string{"--version"}).Return("mytool version 1.2.3", nil)
|
||||
env.On("HasFiles", "*.myl").Return(true)
|
||||
env.On("Pwd").Return("/usr/home/project")
|
||||
env.On("Home").Return("/usr/home")
|
||||
|
||||
props := options.Map{
|
||||
options.FetchVersion: true,
|
||||
LanguageName: "mylang",
|
||||
LanguageExtensions: []string{"*.myl"},
|
||||
Tools: []any{
|
||||
map[string]any{
|
||||
"name": "mytool",
|
||||
"executable": "mytool",
|
||||
"args": []any{"--version"},
|
||||
"regex": `mytool version (?P<version>(?P<major>[0-9]+).(?P<minor>[0-9]+).(?P<patch>[0-9]+))`,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
l := &ConfiguredLanguage{}
|
||||
l.Init(props, env)
|
||||
|
||||
assert.True(t, l.Enabled())
|
||||
assert.Equal(t, "1.2.3", renderTemplate(env, l.Template(), l))
|
||||
assert.Equal(t, []string{"mytool"}, l.defaultTooling)
|
||||
}
|
||||
|
||||
func TestConfiguredLanguageZigPreset(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
Version string
|
||||
ExpectedString string
|
||||
ExpectedURL string
|
||||
InProjectDir bool
|
||||
}{
|
||||
{
|
||||
Case: "zig 0.13.0 - not in project dir",
|
||||
Version: "0.13.0",
|
||||
InProjectDir: false,
|
||||
ExpectedString: "0.13.0",
|
||||
ExpectedURL: "https://ziglang.org/download/0.13.0/release-notes.html",
|
||||
},
|
||||
{
|
||||
Case: "zig 0.12.0-dev.2063+804cee3b9 - not in project dir",
|
||||
Version: "0.12.0-dev.2063+804cee3b9",
|
||||
InProjectDir: false,
|
||||
ExpectedString: "0.12.0-dev.2063+804cee3b9",
|
||||
ExpectedURL: "https://ziglang.org/download/0.12.0/release-notes.html",
|
||||
},
|
||||
{
|
||||
Case: "zig 0.13.0 - in project dir",
|
||||
Version: "0.13.0",
|
||||
InProjectDir: true,
|
||||
ExpectedString: "0.13.0",
|
||||
ExpectedURL: "https://ziglang.org/download/0.13.0/release-notes.html",
|
||||
},
|
||||
{
|
||||
Case: "zig 0.12.0-dev.2063+804cee3b9 - in project dir",
|
||||
Version: "0.12.0-dev.2063+804cee3b9",
|
||||
InProjectDir: true,
|
||||
ExpectedString: "0.12.0-dev.2063+804cee3b9",
|
||||
ExpectedURL: "https://ziglang.org/download/0.12.0/release-notes.html",
|
||||
},
|
||||
}
|
||||
|
||||
// Initialize template system for version URL rendering
|
||||
if template.Cache == nil {
|
||||
template.Cache = &cache.Template{}
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "zig",
|
||||
versionParam: "version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.zig",
|
||||
}
|
||||
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
env.On("Shell").Return("bash")
|
||||
template.Init(env, nil, nil)
|
||||
|
||||
dummyDir := &runtime.FileInfo{}
|
||||
|
||||
if tc.InProjectDir {
|
||||
env.On("HasParentFilePath", "build.zig", false).Return(dummyDir, nil)
|
||||
} else {
|
||||
env.On("HasParentFilePath", "build.zig", false).Return(dummyDir, errors.New("build.zig not found"))
|
||||
}
|
||||
|
||||
zig := NewLanguage("zig")
|
||||
zig.Init(props, env)
|
||||
|
||||
assert.True(t, zig.Enabled(), tc.Case)
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, zig.Template(), zig), tc.Case)
|
||||
assert.Equal(t, tc.ExpectedURL, renderTemplate(env, zig.URL, zig), tc.Case)
|
||||
assert.Equal(t, tc.InProjectDir, zig.InProjectDir(), tc.Case)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfiguredLanguageDartPreset(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
}{
|
||||
{Case: "Dart 2.12.4", ExpectedString: "2.12.4", Version: "Dart SDK version: 2.12.4 (stable) (Thu Apr 15 12:26:53 2021 +0200) on \"macos_x64\""},
|
||||
}
|
||||
|
||||
// Initialize template system for version URL rendering
|
||||
if template.Cache == nil {
|
||||
template.Cache = &cache.Template{}
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "dart",
|
||||
versionParam: "--version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.dart",
|
||||
}
|
||||
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
env.On("Shell").Return("bash")
|
||||
template.Init(env, nil, nil)
|
||||
env.On("HasCommand", "fvm").Return(false)
|
||||
|
||||
d := NewLanguage("dart")
|
||||
d.Init(props, env)
|
||||
|
||||
assert.True(t, d.Enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, d.Template(), d), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package segments
|
||||
|
||||
type Lua struct {
|
||||
Language
|
||||
}
|
||||
|
||||
func (l *Lua) Template() string {
|
||||
return languageTemplate
|
||||
}
|
||||
|
||||
func (l *Lua) Enabled() bool {
|
||||
const (
|
||||
luaToolName = "lua"
|
||||
luajitToolName = "luajit"
|
||||
)
|
||||
|
||||
l.extensions = []string{"*.lua", "*.rockspec"}
|
||||
l.folders = []string{"lua"}
|
||||
l.tooling = map[string]*cmd{
|
||||
luaToolName: {
|
||||
executable: luaToolName,
|
||||
args: []string{"-v"},
|
||||
regex: `Lua (?P<version>((?P<major>[0-9]+).(?P<minor>[0-9]+)(.(?P<patch>[0-9]+))?))`,
|
||||
versionURLTemplate: "https://www.lua.org/manual/{{ .Major }}.{{ .Minor }}/readme.html#changes",
|
||||
},
|
||||
luajitToolName: {
|
||||
executable: luajitToolName,
|
||||
args: []string{"-v"},
|
||||
regex: `LuaJIT (?P<version>((?P<major>[0-9]+).(?P<minor>[0-9]+)(.(?P<patch>[0-9]+))?))`,
|
||||
versionURLTemplate: "https://github.com/LuaJIT/LuaJIT/tree/v{{ .Major}}.{{ .Minor}}",
|
||||
},
|
||||
}
|
||||
l.defaultTooling = []string{luaToolName, luajitToolName}
|
||||
|
||||
return l.Language.Enabled()
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
package segments
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/cache"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/template"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestLua(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
ExpectedURL string
|
||||
Tooling []string
|
||||
HasLua bool
|
||||
HasLuaJit bool
|
||||
}{
|
||||
{
|
||||
Case: "Lua 5.4.4 - default tooling prefers lua",
|
||||
ExpectedString: "5.4.4",
|
||||
Version: "Lua 5.4.4 Copyright (C) 1994-2022 Lua.org, PUC-Rio",
|
||||
ExpectedURL: "https://www.lua.org/manual/5.4/readme.html#changes",
|
||||
HasLua: true,
|
||||
HasLuaJit: true,
|
||||
},
|
||||
{
|
||||
Case: "Lua 5.0 - tooling set to luajit but missing so fallback to lua",
|
||||
ExpectedString: "5.0",
|
||||
Version: "Lua 5.0 Copyright (C) 1994-2003 Tecgraf, PUC-Rio",
|
||||
ExpectedURL: "https://www.lua.org/manual/5.0/readme.html#changes",
|
||||
HasLua: true,
|
||||
Tooling: []string{"luajit", "lua"},
|
||||
},
|
||||
{
|
||||
Case: "LuaJIT 2.0.5 - tooling set to luajit first",
|
||||
ExpectedString: "2.0.5",
|
||||
Version: "LuaJIT 2.0.5 -- Copyright (C) 2005-2017 Mike Pall. http://luajit.org/",
|
||||
HasLuaJit: true,
|
||||
HasLua: true,
|
||||
ExpectedURL: "https://github.com/LuaJIT/LuaJIT/tree/v2.0",
|
||||
Tooling: []string{"luajit"},
|
||||
},
|
||||
{
|
||||
Case: "LuaJIT 2.1.0-beta3 - tooling set to lua first but missing so try luajit",
|
||||
ExpectedString: "2.1.0",
|
||||
Version: "LuaJIT 2.1.0-beta3 -- Copyright (C) 2005-2017 Mike Pall. http://luajit.org/",
|
||||
HasLuaJit: true,
|
||||
ExpectedURL: "https://github.com/LuaJIT/LuaJIT/tree/v2.1",
|
||||
Tooling: []string{"lua", "luajit"},
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "lua",
|
||||
versionParam: "-v",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.lua",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
|
||||
if !tc.HasLua {
|
||||
env.Unset("HasCommand")
|
||||
env.On("HasCommand", "lua").Return(false)
|
||||
}
|
||||
|
||||
env.On("HasCommand", "luajit").Return(tc.HasLuaJit)
|
||||
env.On("RunCommandWithEnv", "luajit", []string(nil), []string{"-v"}).Return(tc.Version, nil)
|
||||
env.On("Shell").Return("bash")
|
||||
|
||||
// Initialize template system for version URL rendering
|
||||
if template.Cache == nil {
|
||||
template.Cache = &cache.Template{}
|
||||
}
|
||||
template.Init(env, nil, nil)
|
||||
|
||||
if len(tc.Tooling) > 0 {
|
||||
props[Tooling] = tc.Tooling
|
||||
}
|
||||
|
||||
l := &Lua{}
|
||||
l.Init(props, env)
|
||||
|
||||
failMsg := fmt.Sprintf("Failed in case: %s", tc.Case)
|
||||
assert.True(t, l.Enabled(), failMsg)
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, l.Template(), l), failMsg)
|
||||
assert.Equal(t, tc.ExpectedURL, l.URL, failMsg)
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package segments
|
||||
|
||||
type Nim struct {
|
||||
Language
|
||||
}
|
||||
|
||||
func (n *Nim) Template() string {
|
||||
return languageTemplate
|
||||
}
|
||||
|
||||
func (n *Nim) Enabled() bool {
|
||||
const nimToolName = "nim"
|
||||
|
||||
n.extensions = []string{"*.nim", "*.nims"}
|
||||
|
||||
n.tooling = map[string]*cmd{
|
||||
nimToolName: {
|
||||
executable: nimToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: `Nim Compiler Version (?P<version>(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+))`,
|
||||
},
|
||||
}
|
||||
n.defaultTooling = []string{nimToolName}
|
||||
return n.Language.Enabled()
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package segments
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNim(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
}{
|
||||
{
|
||||
Case: "Nim 2.2.0",
|
||||
ExpectedString: "2.2.0",
|
||||
Version: "Nim Compiler Version 2.2.0 [MacOSX: arm64]\nCompiled at 2024-11-30\nCopyright (c) 2006-2024 by Andreas Rumpf",
|
||||
},
|
||||
{
|
||||
Case: "Nim 1.6.12",
|
||||
ExpectedString: "1.6.12",
|
||||
Version: "Nim Compiler Version 1.6.12 [Linux: amd64]\nCompiled at 2023-06-15\nCopyright (c) 2006-2023 by Andreas Rumpf",
|
||||
},
|
||||
{
|
||||
Case: "Nim 2.0.0",
|
||||
ExpectedString: "2.0.0",
|
||||
Version: "Nim Compiler Version 2.0.0 [Windows: amd64]\nCompiled at 2023-12-25\nCopyright (c) 2006-2023 by Andreas Rumpf",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "nim",
|
||||
versionParam: "--version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.nim",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
n := &Nim{}
|
||||
n.Init(props, env)
|
||||
assert.True(t, n.Enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, n.Template(), n), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package segments
|
||||
|
||||
type OCaml struct {
|
||||
Language
|
||||
}
|
||||
|
||||
func (o *OCaml) Template() string {
|
||||
return languageTemplate
|
||||
}
|
||||
|
||||
func (o *OCaml) Enabled() bool {
|
||||
const ocamlToolName = "ocaml"
|
||||
|
||||
o.extensions = []string{"*.ml", "*.mli", "dune", "dune-project", "dune-workspace"}
|
||||
o.tooling = map[string]*cmd{
|
||||
ocamlToolName: {
|
||||
executable: ocamlToolName,
|
||||
args: []string{versionFlagShortArg},
|
||||
regex: `The OCaml toplevel, version (?P<version>((?P<major>[0-9]+).(?P<minor>[0-9]+).(?P<patch>[0-9]+))(-(?P<prerelease>[a-z]+))?)`,
|
||||
},
|
||||
}
|
||||
o.defaultTooling = []string{ocamlToolName}
|
||||
|
||||
return o.Language.Enabled()
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package segments
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestOCaml(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
}{
|
||||
{Case: "OCaml 4.12.0", ExpectedString: "4.12.0", Version: "The OCaml toplevel, version 4.12.0"},
|
||||
{Case: "OCaml 4.11.0", ExpectedString: "4.11.0", Version: "The OCaml toplevel, version 4.11.0"},
|
||||
{Case: "OCaml 4.13.0", ExpectedString: "4.13.0", Version: "The OCaml toplevel, version 4.13.0"},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "ocaml",
|
||||
versionParam: "-version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.ml",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
o := &OCaml{}
|
||||
o.Init(props, env)
|
||||
assert.True(t, o.Enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, o.Template(), o), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package segments
|
||||
|
||||
type Perl struct {
|
||||
Language
|
||||
}
|
||||
|
||||
func (p *Perl) Template() string {
|
||||
return languageTemplate
|
||||
}
|
||||
|
||||
func (p *Perl) Enabled() bool {
|
||||
const perlToolName = "perl"
|
||||
|
||||
perlRegex := `This is perl.*v(?P<version>(?P<major>[0-9]+)(?:\.(?P<minor>[0-9]+))(?:\.(?P<patch>[0-9]+))?).* built for .+`
|
||||
p.extensions = []string{
|
||||
".perl-version",
|
||||
"*.pl",
|
||||
"*.pm",
|
||||
"*.t",
|
||||
}
|
||||
p.tooling = map[string]*cmd{
|
||||
perlToolName: {
|
||||
executable: perlToolName,
|
||||
args: []string{versionFlagShortArg},
|
||||
regex: perlRegex,
|
||||
},
|
||||
}
|
||||
p.defaultTooling = []string{perlToolName}
|
||||
|
||||
return p.Language.Enabled()
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package segments
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPerl(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
PerlHomeVersion string
|
||||
PerlHomeEnabled bool
|
||||
}{
|
||||
{
|
||||
Case: "v5.12+",
|
||||
ExpectedString: "5.32.1",
|
||||
Version: "This is perl 5, version 32, subversion 1 (v5.32.1) built for MSWin32-x64-multi-thread",
|
||||
},
|
||||
{
|
||||
Case: "v5.6 - v5.10",
|
||||
ExpectedString: "5.6.1",
|
||||
Version: "This is perl, v5.6.1 built for MSWin32-x86-multi-thread",
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "perl",
|
||||
versionParam: "-version",
|
||||
versionOutput: tc.Version,
|
||||
extension: ".perl-version",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
|
||||
p := &Perl{}
|
||||
p.Init(props, env)
|
||||
assert.True(t, p.Enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, p.Template(), p), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package segments
|
||||
|
||||
type Php struct {
|
||||
Language
|
||||
}
|
||||
|
||||
func (p *Php) Template() string {
|
||||
return languageTemplate
|
||||
}
|
||||
|
||||
func (p *Php) Enabled() bool {
|
||||
p.extensions = []string{"*.php", "composer.json", "composer.lock", ".php-version", "blade.php"}
|
||||
p.tooling = map[string]*cmd{
|
||||
phpToolName: {
|
||||
executable: phpToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: `(?:PHP (?P<version>((?P<major>[0-9]+).(?P<minor>[0-9]+).(?P<patch>[0-9]+))))`,
|
||||
},
|
||||
}
|
||||
p.defaultTooling = []string{phpToolName}
|
||||
p.versionURLTemplate = "https://www.php.net/ChangeLog-{{ .Major }}.php#PHP_{{ .Major }}_{{ .Minor }}"
|
||||
|
||||
return p.Language.Enabled()
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package segments
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPhp(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
}{
|
||||
{Case: "PHP 6.1.0", ExpectedString: "6.1.0", Version: "PHP 6.1.0(cli) (built: Jul 2 2021 03:59:48) ( NTS )"},
|
||||
{Case: "php 7.4.21", ExpectedString: "7.4.21", Version: "PHP 7.4.21 (cli) (built: Jul 2 2021 03:59:48) ( NTS )"},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "php",
|
||||
versionParam: "--version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.php",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
j := &Php{}
|
||||
j.Init(props, env)
|
||||
assert.True(t, j.Enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, j.Template(), j), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
}
|
||||
}
|
||||
@@ -112,7 +112,7 @@ func (n *Project) Enabled() bool {
|
||||
},
|
||||
{
|
||||
Name: dartToolName,
|
||||
Files: []string{"pubspec.yaml"},
|
||||
Files: []string{pubspecFileName},
|
||||
Fetcher: n.getDartPackage,
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
package segments
|
||||
|
||||
type R struct {
|
||||
Language
|
||||
}
|
||||
|
||||
func (r *R) Template() string {
|
||||
return languageTemplate
|
||||
}
|
||||
|
||||
const (
|
||||
rscriptToolName = "Rscript"
|
||||
rExeToolName = "R.exe"
|
||||
)
|
||||
|
||||
func (r *R) Enabled() bool {
|
||||
rRegex := `version ` + versionRegex
|
||||
r.extensions = []string{"*.R", "*.Rmd", "*.Rsx", "*.Rda", "*.Rd", "*.Rproj", ".Rproj.user"}
|
||||
r.tooling = map[string]*cmd{
|
||||
rscriptToolName: {
|
||||
executable: rscriptToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: rRegex,
|
||||
},
|
||||
"R": {
|
||||
executable: "R",
|
||||
args: []string{versionFlagArg},
|
||||
regex: rRegex,
|
||||
},
|
||||
rExeToolName: {
|
||||
executable: rExeToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: rRegex,
|
||||
},
|
||||
}
|
||||
r.defaultTooling = []string{rscriptToolName, "R", rExeToolName}
|
||||
r.versionURLTemplate = "https://www.r-project.org/"
|
||||
|
||||
return r.Language.Enabled()
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package segments
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestR(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
HasRscript bool
|
||||
HasR bool
|
||||
HasRexe bool
|
||||
}{
|
||||
{Case: "Rscript 4.2.0", ExpectedString: "4.2.0", HasRscript: true, Version: "Rscript (R) version 4.2.0 (2022-04-22)"},
|
||||
{Case: "Rscript 4.1.3", ExpectedString: "4.1.3", HasRscript: true, Version: "R scripting front-end version 4.1.3 (2022-03-10)"},
|
||||
{Case: "Rscript 4.1.3 patched", ExpectedString: "4.1.3", HasRscript: true, Version: "R scripting front-end version 4.1.3 Patched (2022-03-10 r81896)"},
|
||||
{Case: "Rscript 4.0.0", ExpectedString: "4.0.0", HasRscript: true, Version: "R scripting front-end version 4.0.0 (2020-04-24)"},
|
||||
{Case: "Rscript devel", ExpectedString: "4.2.0", HasRscript: true, Version: "R scripting front-end version 4.2.0 Under development (unstable) (2022-03-14 r81896)"},
|
||||
|
||||
{Case: "R 4.1.2", ExpectedString: "4.1.2", HasR: true, Version: "R version 4.1.2 (2021-11-01) -- \"Bird Hippie\""},
|
||||
{Case: "R 4.1.3 patched", ExpectedString: "4.1.3", HasR: true, Version: "R version 4.1.3 Patched (2022-03-10 r81896) -- \"One Push-Up\""},
|
||||
{Case: "R 4.0.0", ExpectedString: "4.0.0", HasR: true, Version: "R version 4.0.0 (2020-04-24) -- \"Arbor Day\""},
|
||||
|
||||
{Case: "R.exe 4.1.2", ExpectedString: "4.1.2", HasRexe: true, Version: "R version 4.1.2 (2021-11-01) -- \"Bird Hippie\""},
|
||||
{Case: "R.exe 4.1.3 patched", ExpectedString: "4.1.3", HasRexe: true, Version: "R version 4.1.3 Patched (2022-03-10 r81896) -- \"One Push-Up\""},
|
||||
{Case: "R.exe 4.0.0", ExpectedString: "4.0.0", HasRexe: true, Version: "R version 4.0.0 (2020-04-24) -- \"Arbor Day\""},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "R",
|
||||
versionParam: "--version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.R",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
|
||||
env.On("HasCommand", "Rscript").Return(tc.HasRscript)
|
||||
env.On("RunCommandWithEnv", "Rscript", []string(nil), []string{"--version"}).Return(tc.Version, nil)
|
||||
env.On("HasCommand", "R.exe").Return(tc.HasRexe)
|
||||
env.On("RunCommandWithEnv", "R.exe", []string(nil), []string{"--version"}).Return(tc.Version, nil)
|
||||
|
||||
r := &R{}
|
||||
r.Init(props, env)
|
||||
|
||||
assert.True(t, r.Enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, r.Template(), r), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
package segments
|
||||
|
||||
type Ruby struct {
|
||||
Language
|
||||
}
|
||||
|
||||
func (r *Ruby) Template() string {
|
||||
return languageTemplate
|
||||
}
|
||||
|
||||
const (
|
||||
chrubyToolName = "chruby"
|
||||
rbenvToolName = "rbenv"
|
||||
rvmPromptToolName = "rvm-prompt"
|
||||
rubyToolName = "ruby"
|
||||
)
|
||||
|
||||
func (r *Ruby) Enabled() bool {
|
||||
r.extensions = []string{"*.rb", "Rakefile", "Gemfile"}
|
||||
r.tooling = map[string]*cmd{
|
||||
rbenvToolName: {
|
||||
executable: rbenvToolName,
|
||||
args: []string{"version-name"},
|
||||
regex: `(?P<version>.+)`,
|
||||
},
|
||||
rvmPromptToolName: {
|
||||
executable: rvmPromptToolName,
|
||||
args: []string{"i", "v", "g"},
|
||||
regex: `(?P<version>.+)`,
|
||||
},
|
||||
chrubyToolName: {
|
||||
executable: chrubyToolName,
|
||||
args: []string(nil),
|
||||
regex: `\* (?P<version>.+)\n`,
|
||||
},
|
||||
asdfToolName: {
|
||||
executable: asdfToolName,
|
||||
args: []string{"current", rubyToolName},
|
||||
regex: `ruby\s+(?P<version>[^\s]+)\s+`,
|
||||
},
|
||||
rubyToolName: {
|
||||
executable: rubyToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: `ruby\s+(?P<version>[^\s]+)\s+`,
|
||||
},
|
||||
}
|
||||
r.defaultTooling = []string{rbenvToolName, rvmPromptToolName, chrubyToolName, asdfToolName, rubyToolName}
|
||||
|
||||
enabled := r.Language.Enabled()
|
||||
|
||||
// this happens when no version is set
|
||||
if r.Full == "______" {
|
||||
r.Full = ""
|
||||
}
|
||||
|
||||
return enabled
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
package segments
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/segments/options"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestRuby(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
HasRbenv bool
|
||||
HasRvmprompt bool
|
||||
HasChruby bool
|
||||
HasAsdf bool
|
||||
HasRuby bool
|
||||
HasRubyFiles bool
|
||||
HasRakeFile bool
|
||||
HasGemFile bool
|
||||
FetchVersion bool
|
||||
}{
|
||||
{Case: "Ruby files", ExpectedString: "", FetchVersion: false, HasRubyFiles: true},
|
||||
{Case: "Rakefile", ExpectedString: "", FetchVersion: false, HasRakeFile: true},
|
||||
{Case: "Gemfile", ExpectedString: "", FetchVersion: false, HasGemFile: true},
|
||||
{Case: "Gemfile with version", ExpectedString: "err parsing info from ruby with", FetchVersion: true, HasGemFile: true},
|
||||
{
|
||||
Case: "Version with chruby",
|
||||
ExpectedString: "ruby-2.6.3",
|
||||
FetchVersion: true,
|
||||
HasRubyFiles: true,
|
||||
HasChruby: true,
|
||||
Version: ` * ruby-2.6.3
|
||||
ruby-1.9.3-p392
|
||||
jruby-1.7.0
|
||||
rubinius-2.0.0-rc1`,
|
||||
},
|
||||
{
|
||||
Case: "Version with chruby line 2",
|
||||
ExpectedString: "ruby-1.9.3-p392",
|
||||
FetchVersion: true,
|
||||
HasRubyFiles: true,
|
||||
HasChruby: true,
|
||||
Version: ` ruby-2.6.3
|
||||
* ruby-1.9.3-p392
|
||||
jruby-1.7.0
|
||||
rubinius-2.0.0-rc1`,
|
||||
},
|
||||
{
|
||||
Case: "Version with asdf",
|
||||
ExpectedString: "2.6.3",
|
||||
FetchVersion: true,
|
||||
HasRubyFiles: true,
|
||||
HasAsdf: true,
|
||||
Version: "ruby 2.6.3 /Users/jan/Projects/oh-my-posh/.tool-versions",
|
||||
},
|
||||
{
|
||||
Case: "Version with asdf not set",
|
||||
ExpectedString: "",
|
||||
FetchVersion: true,
|
||||
HasRubyFiles: true,
|
||||
HasAsdf: true,
|
||||
Version: "ruby ______ No version set. Run \"asdf <global|shell|local> ruby <version>\"",
|
||||
},
|
||||
{
|
||||
Case: "Version with ruby",
|
||||
ExpectedString: "2.6.3",
|
||||
FetchVersion: true,
|
||||
HasRubyFiles: true,
|
||||
HasRuby: true,
|
||||
Version: "ruby 2.6.3 (2019-04-16 revision 67580) [universal.x86_64-darwin20]",
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "ruby",
|
||||
versionParam: "--version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.rb",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
|
||||
env.On("HasCommand", "rbenv").Return(tc.HasRbenv)
|
||||
env.On("RunCommandWithEnv", "rbenv", []string(nil), []string{"version-name"}).Return(tc.Version, nil)
|
||||
env.On("HasCommand", "rvm-prompt").Return(tc.HasRvmprompt)
|
||||
env.On("RunCommandWithEnv", "rvm-prompt", []string(nil), []string{"i", "v", "g"}).Return(tc.Version, nil)
|
||||
env.On("HasCommand", "chruby").Return(tc.HasChruby)
|
||||
env.On("RunCommandWithEnv", "chruby", []string(nil), []string(nil)).Return(tc.Version, nil)
|
||||
env.On("HasCommand", "asdf").Return(tc.HasAsdf)
|
||||
env.On("RunCommandWithEnv", "asdf", []string(nil), []string{"current", "ruby"}).Return(tc.Version, nil)
|
||||
env.On("HasFiles", "Rakefile").Return(tc.HasRakeFile)
|
||||
env.On("HasFiles", "Gemfile").Return(tc.HasGemFile)
|
||||
|
||||
props[options.FetchVersion] = tc.FetchVersion
|
||||
|
||||
ruby := &Ruby{}
|
||||
ruby.Init(props, env)
|
||||
|
||||
assert.True(t, ruby.Enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, ruby.Template(), ruby), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package segments
|
||||
|
||||
type Rust struct {
|
||||
Language
|
||||
}
|
||||
|
||||
func (r *Rust) Template() string {
|
||||
return languageTemplate
|
||||
}
|
||||
|
||||
func (r *Rust) Enabled() bool {
|
||||
const rustcToolName = "rustc"
|
||||
|
||||
r.extensions = []string{"*.rs", "Cargo.toml", "Cargo.lock"}
|
||||
r.tooling = map[string]*cmd{
|
||||
rustcToolName: {
|
||||
executable: rustcToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: `(rust version|rustc) (?P<version>((?P<major>[0-9]+).(?P<minor>[0-9]+).(?P<patch>[0-9]+))(-(?P<prerelease>[a-z]+))?)(( \((?P<buildmetadata>[0-9a-f]+ [0-9]+-[0-9]+-[0-9]+)\))?)`, //nolint:lll
|
||||
},
|
||||
}
|
||||
r.defaultTooling = []string{rustcToolName}
|
||||
|
||||
return r.Language.Enabled()
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
package segments
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestRust(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
}{
|
||||
{Case: "Rust 1.64.0", ExpectedString: "1.64.0", Version: "rustc 1.64.0"},
|
||||
{Case: "Rust 1.53.0", ExpectedString: "1.53.0", Version: "rustc 1.53.0 (4369396ce 2021-04-27)"},
|
||||
{Case: "Rust 1.66.0", ExpectedString: "1.66.0-nightly", Version: "rustc 1.66.0-nightly (01af5040f 2022-10-04)"},
|
||||
{
|
||||
Case: "Toolchain not installed",
|
||||
ExpectedString: "1.81.0",
|
||||
Version: ` info: syncing channel updates for '1.81.0-x86_64-pc-windows-msvc'
|
||||
info: latest update on 2024-09-05, rust version 1.81.0 (eeb90cda1 2024-09-04)
|
||||
info: downloading component 'cargo'
|
||||
info: downloading component 'clippy'
|
||||
info: downloading component 'rust-analyzer'
|
||||
info: downloading component 'rust-src'
|
||||
info: downloading component 'rust-std'
|
||||
info: downloading component 'rustc'
|
||||
info: downloading component 'rustfmt'
|
||||
info: installing component 'cargo'
|
||||
info: installing component 'clippy'
|
||||
info: installing component 'rust-analyzer'
|
||||
info: installing component 'rust-src'
|
||||
info: installing component 'rust-std'
|
||||
info: installing component 'rustc'`,
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "rustc",
|
||||
versionParam: "--version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.rs",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
r := &Rust{}
|
||||
r.Init(props, env)
|
||||
assert.True(t, r.Enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, r.Template(), r), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package segments
|
||||
|
||||
type Swift struct {
|
||||
Language
|
||||
}
|
||||
|
||||
func (s *Swift) Template() string {
|
||||
return languageTemplate
|
||||
}
|
||||
|
||||
func (s *Swift) Enabled() bool {
|
||||
const swiftToolName = "swift"
|
||||
|
||||
s.extensions = []string{"*.swift", "*.SWIFT", "Podfile"}
|
||||
s.tooling = map[string]*cmd{
|
||||
swiftToolName: {
|
||||
executable: swiftToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: `Swift version (?P<version>((?P<major>[0-9]+).(?P<minor>[0-9]+)((.|-)(?P<patch>[0-9]+|dev))?))`,
|
||||
},
|
||||
}
|
||||
s.defaultTooling = []string{swiftToolName}
|
||||
s.versionURLTemplate = "https://github.com/apple/swift/releases/tag/swift-{{ .Full }}-RELEASE"
|
||||
|
||||
return s.Language.Enabled()
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package segments
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestSwift(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
}{
|
||||
{Case: "Swift 5.5.3", ExpectedString: "5.5.3", Version: "Swift version 5.5.3 (swift-5.5.3-RELEASE)"},
|
||||
{Case: "Swift 5.5.3 on Windows", ExpectedString: "5.5.3", Version: "compnerd.org Swift version 5.5.3 (swift-5.5.3-RELEASE)"},
|
||||
{Case: "Swift 5.5.3 on Mac", ExpectedString: "5.5.3", Version: "Apple Swift version 5.5.3 (swift-5.5.3-RELEASE)"},
|
||||
{Case: "Swift 5.5", ExpectedString: "5.5", Version: "Swift version 5.5 (swift-5.5-RELEASE)"},
|
||||
{Case: "Swift 5.6-dev", ExpectedString: "5.6-dev", Version: "Swift version 5.6-dev (LLVM 62b900d3d0d5be9, Swift ce64fe8867792d4)"},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "swift",
|
||||
versionParam: "--version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.swift",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
s := &Swift{}
|
||||
s.Init(props, env)
|
||||
assert.True(t, s.Enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, s.Template(), s), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package segments
|
||||
|
||||
type V struct {
|
||||
Language
|
||||
}
|
||||
|
||||
func (v *V) Template() string {
|
||||
return languageTemplate
|
||||
}
|
||||
|
||||
func (v *V) Enabled() bool {
|
||||
v.extensions = []string{"*.v"}
|
||||
|
||||
v.tooling = map[string]*cmd{
|
||||
"v": {
|
||||
executable: "v",
|
||||
args: []string{"--version"},
|
||||
regex: `V (?P<version>(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)) [a-f0-9]+`,
|
||||
},
|
||||
}
|
||||
v.defaultTooling = []string{"v"}
|
||||
return v.Language.Enabled()
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package segments
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestV(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
}{
|
||||
{
|
||||
Case: "V 0.4.9",
|
||||
ExpectedString: "0.4.9",
|
||||
Version: "V 0.4.9 b487986",
|
||||
},
|
||||
{
|
||||
Case: "V 0.4.8",
|
||||
ExpectedString: "0.4.8",
|
||||
Version: "V 0.4.8 a123456",
|
||||
},
|
||||
{
|
||||
Case: "V 0.4.7",
|
||||
ExpectedString: "0.4.7",
|
||||
Version: "V 0.4.7 f789012",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "v",
|
||||
versionParam: "--version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.v",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
v := &V{}
|
||||
v.Init(props, env)
|
||||
assert.True(t, v.Enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, v.Template(), v), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package segments
|
||||
|
||||
type Vala struct {
|
||||
Language
|
||||
}
|
||||
|
||||
func (v *Vala) Template() string {
|
||||
return languageTemplate
|
||||
}
|
||||
|
||||
func (v *Vala) Enabled() bool {
|
||||
const valaToolName = "vala"
|
||||
|
||||
v.extensions = []string{"*.vala"}
|
||||
v.tooling = map[string]*cmd{
|
||||
valaToolName: {
|
||||
executable: valaToolName,
|
||||
args: []string{versionFlagArg},
|
||||
regex: `Vala (?P<version>((?P<major>[0-9]+).(?P<minor>[0-9]+).(?P<patch>[0-9]+)))`,
|
||||
},
|
||||
}
|
||||
v.defaultTooling = []string{valaToolName}
|
||||
v.versionURLTemplate = "https://gitlab.gnome.org/GNOME/vala/raw/{{ .Major }}.{{ .Minor }}/NEWS"
|
||||
|
||||
return v.Language.Enabled()
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package segments
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestVala(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
Version string
|
||||
}{
|
||||
{
|
||||
Case: "vala 0.48.17",
|
||||
ExpectedString: "0.48.17",
|
||||
Version: "Vala 0.48.17",
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "vala",
|
||||
versionParam: "--version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.vala",
|
||||
}
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
v := &Vala{}
|
||||
v.Init(props, env)
|
||||
assert.True(t, v.Enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, v.Template(), v), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package segments
|
||||
|
||||
type Zig struct {
|
||||
Language
|
||||
}
|
||||
|
||||
func (zig *Zig) Template() string {
|
||||
return languageTemplate
|
||||
}
|
||||
|
||||
func (zig *Zig) Enabled() bool {
|
||||
const zigToolName = "zig"
|
||||
|
||||
zig.extensions = []string{"*.zig", "*.zon"}
|
||||
zig.projectFiles = []string{"build.zig"}
|
||||
zig.tooling = map[string]*cmd{
|
||||
zigToolName: {
|
||||
executable: zigToolName,
|
||||
args: []string{versionArg},
|
||||
regex: `(?P<version>(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?)`, //nolint:lll
|
||||
},
|
||||
}
|
||||
zig.defaultTooling = []string{zigToolName}
|
||||
|
||||
zig.versionURLTemplate = "https://ziglang.org/download/{{ .Major }}.{{ .Minor }}.{{ .Patch }}/release-notes.html"
|
||||
|
||||
return zig.Language.Enabled()
|
||||
}
|
||||
|
||||
func (zig *Zig) InProjectDir() bool {
|
||||
return zig.projectRoot != nil
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
package segments
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestZig(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
Version string
|
||||
ExpectedString string
|
||||
ExpectedURL string
|
||||
InProjectDir bool
|
||||
}{
|
||||
{
|
||||
Case: "zig 0.13.0 - not in project dir",
|
||||
Version: "0.13.0",
|
||||
InProjectDir: false,
|
||||
ExpectedString: "0.13.0",
|
||||
ExpectedURL: "https://ziglang.org/download/0.13.0/release-notes.html",
|
||||
},
|
||||
{
|
||||
Case: "zig 0.12.0-dev.2063+804cee3b9 - not in project dir",
|
||||
Version: "0.12.0-dev.2063+804cee3b9",
|
||||
InProjectDir: false,
|
||||
ExpectedString: "0.12.0-dev.2063+804cee3b9",
|
||||
ExpectedURL: "https://ziglang.org/download/0.12.0/release-notes.html",
|
||||
},
|
||||
{
|
||||
Case: "zig 0.13.0 - in project dir",
|
||||
Version: "0.13.0",
|
||||
InProjectDir: true,
|
||||
ExpectedString: "0.13.0",
|
||||
ExpectedURL: "https://ziglang.org/download/0.13.0/release-notes.html",
|
||||
},
|
||||
{
|
||||
Case: "zig 0.12.0-dev.2063+804cee3b9 - in project dir",
|
||||
Version: "0.12.0-dev.2063+804cee3b9",
|
||||
InProjectDir: true,
|
||||
ExpectedString: "0.12.0-dev.2063+804cee3b9",
|
||||
ExpectedURL: "https://ziglang.org/download/0.12.0/release-notes.html",
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
params := &mockedLanguageParams{
|
||||
cmd: "zig",
|
||||
versionParam: "version",
|
||||
versionOutput: tc.Version,
|
||||
extension: "*.zig",
|
||||
}
|
||||
|
||||
env, props := getMockedLanguageEnv(params)
|
||||
|
||||
dummyDir := &runtime.FileInfo{}
|
||||
|
||||
if tc.InProjectDir {
|
||||
env.On("HasParentFilePath", "build.zig", false).Return(dummyDir, nil)
|
||||
} else {
|
||||
env.On("HasParentFilePath", "build.zig", false).Return(dummyDir, errors.New("build.zig not found"))
|
||||
}
|
||||
|
||||
zig := &Zig{}
|
||||
zig.Init(props, env)
|
||||
|
||||
assert.True(t, zig.Enabled(), tc.Case)
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, zig.Template(), zig), tc.Case)
|
||||
assert.Equal(t, tc.ExpectedURL, renderTemplate(env, zig.URL, zig), tc.Case)
|
||||
assert.Equal(t, tc.InProjectDir, zig.InProjectDir(), tc.Case)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user