feat(language): expose version info

This commit is contained in:
Jan De Dobbeleer 2021-12-03 20:19:57 +01:00 committed by Jan De Dobbeleer
parent d477923f16
commit a24786b97d
15 changed files with 75 additions and 75 deletions

View file

@ -1,7 +1,7 @@
package main package main
type angular struct { type angular struct {
language *language language
} }
func (a *angular) string() string { func (a *angular) string() string {
@ -9,7 +9,7 @@ func (a *angular) string() string {
} }
func (a *angular) init(props properties, env environmentInfo) { func (a *angular) init(props properties, env environmentInfo) {
a.language = &language{ a.language = language{
env: env, env: env,
props: props, props: props,
extensions: []string{"angular.json"}, extensions: []string{"angular.json"},

View file

@ -1,7 +1,7 @@
package main package main
type azfunc struct { type azfunc struct {
language *language language
} }
func (az *azfunc) string() string { func (az *azfunc) string() string {
@ -9,7 +9,7 @@ func (az *azfunc) string() string {
} }
func (az *azfunc) init(props properties, env environmentInfo) { func (az *azfunc) init(props properties, env environmentInfo) {
az.language = &language{ az.language = language{
env: env, env: env,
props: props, props: props,
extensions: []string{"host.json", "local.settings.json", "function.json"}, extensions: []string{"host.json", "local.settings.json", "function.json"},

View file

@ -1,7 +1,7 @@
package main package main
type crystal struct { type crystal struct {
language *language language
} }
func (c *crystal) string() string { func (c *crystal) string() string {
@ -9,7 +9,7 @@ func (c *crystal) string() string {
} }
func (c *crystal) init(props properties, env environmentInfo) { func (c *crystal) init(props properties, env environmentInfo) {
c.language = &language{ c.language = language{
env: env, env: env,
props: props, props: props,
extensions: []string{"*.cr", "shard.yml"}, extensions: []string{"*.cr", "shard.yml"},

View file

@ -1,7 +1,7 @@
package main package main
type dart struct { type dart struct {
language *language language
} }
func (d *dart) string() string { func (d *dart) string() string {
@ -9,7 +9,7 @@ func (d *dart) string() string {
} }
func (d *dart) init(props properties, env environmentInfo) { func (d *dart) init(props properties, env environmentInfo) {
d.language = &language{ d.language = language{
env: env, env: env,
props: props, props: props,
extensions: []string{"*.dart", "pubspec.yaml", "pubspec.yml", "pubspec.lock", ".dart_tool"}, extensions: []string{"*.dart", "pubspec.yaml", "pubspec.yml", "pubspec.lock", ".dart_tool"},

View file

@ -1,7 +1,7 @@
package main package main
type dotnet struct { type dotnet struct {
language *language language
} }
const ( const (
@ -22,7 +22,7 @@ func (d *dotnet) string() string {
} }
func (d *dotnet) init(props properties, env environmentInfo) { func (d *dotnet) init(props properties, env environmentInfo) {
d.language = &language{ d.language = language{
env: env, env: env,
props: props, props: props,
extensions: []string{"*.cs", "*.csx", "*.vb", "*.sln", "*.csproj", "*.vbproj", "*.fs", "*.fsx", "*.fsproj", "global.json"}, extensions: []string{"*.cs", "*.csx", "*.vb", "*.sln", "*.csproj", "*.vbproj", "*.fs", "*.fsx", "*.fsproj", "global.json"},

View file

@ -1,7 +1,7 @@
package main package main
type golang struct { type golang struct {
language *language language
} }
func (g *golang) string() string { func (g *golang) string() string {
@ -9,7 +9,7 @@ func (g *golang) string() string {
} }
func (g *golang) init(props properties, env environmentInfo) { func (g *golang) init(props properties, env environmentInfo) {
g.language = &language{ g.language = language{
env: env, env: env,
props: props, props: props,
extensions: []string{"*.go", "go.mod"}, extensions: []string{"*.go", "go.mod"},

View file

@ -3,7 +3,7 @@ package main
import "fmt" import "fmt"
type java struct { type java struct {
language *language language
} }
func (j *java) string() string { func (j *java) string() string {
@ -17,7 +17,7 @@ func (j *java) init(props properties, env environmentInfo) {
args: []string{"-Xinternalversion"}, args: []string{"-Xinternalversion"},
regex: javaRegex, regex: javaRegex,
} }
j.language = &language{ j.language = language{
env: env, env: env,
props: props, props: props,
extensions: []string{ extensions: []string{

View file

@ -1,7 +1,7 @@
package main package main
type julia struct { type julia struct {
language *language language
} }
func (j *julia) string() string { func (j *julia) string() string {
@ -9,7 +9,7 @@ func (j *julia) string() string {
} }
func (j *julia) init(props properties, env environmentInfo) { func (j *julia) init(props properties, env environmentInfo) {
j.language = &language{ j.language = language{
env: env, env: env,
props: props, props: props,
extensions: []string{"*.jl"}, extensions: []string{"*.jl"},

View file

@ -25,44 +25,23 @@ type cmd struct {
executable string executable string
args []string args []string
regex string regex string
version
} }
func (c *cmd) parse(versionInfo string) error { func (c *cmd) parse(versionInfo string) (*version, error) {
values := findNamedRegexMatch(c.regex, versionInfo) values := findNamedRegexMatch(c.regex, versionInfo)
if len(values) == 0 { if len(values) == 0 {
return errors.New("cannot parse version string") return nil, errors.New("cannot parse version string")
} }
c.version.Full = values["version"] version := &version{
c.version.Major = values["major"] Full: values["version"],
c.version.Minor = values["minor"] Major: values["major"],
c.version.Patch = values["patch"] Minor: values["minor"],
c.version.Prerelease = values["prerelease"] Patch: values["patch"],
c.version.BuildMetadata = values["buildmetadata"] Prerelease: values["prerelease"],
return nil BuildMetadata: values["buildmetadata"],
}
func (c *cmd) buildVersionURL(text, template string) string {
if template == "" {
return text
} }
truncatingSprintf := func(str string, args ...interface{}) (string, error) { return version, nil
n := strings.Count(str, "%s")
if n > len(args) {
return "", errors.New("Too many parameters")
}
if n == 0 {
return fmt.Sprintf(str, args...), nil
}
return fmt.Sprintf(str, args[:n]...), nil
}
version, err := truncatingSprintf(template, text, c.version.Major, c.version.Minor, c.version.Patch)
if err != nil {
return text
}
return version
} }
type language struct { type language struct {
@ -71,13 +50,14 @@ type language struct {
extensions []string extensions []string
commands []*cmd commands []*cmd
versionURLTemplate string versionURLTemplate string
activeCommand *cmd
exitCode int exitCode int
loadContext loadContext loadContext loadContext
inContext inContext inContext inContext
matchesVersionFile matchesVersionFile matchesVersionFile matchesVersionFile
homeEnabled bool homeEnabled bool
displayMode string displayMode string
version
} }
const ( const (
@ -120,7 +100,7 @@ func (l *language) string() string {
segmentTemplate := l.props.getString(SegmentTemplate, "{{.Full}}") segmentTemplate := l.props.getString(SegmentTemplate, "{{.Full}}")
template := &textTemplate{ template := &textTemplate{
Template: segmentTemplate, Template: segmentTemplate,
Context: l.activeCommand.version, Context: l.version,
Env: l.env, Env: l.env,
} }
text, err := template.render() text, err := template.render()
@ -132,11 +112,11 @@ func (l *language) string() string {
versionURLTemplate := l.props.getString(VersionURLTemplate, "") versionURLTemplate := l.props.getString(VersionURLTemplate, "")
// backward compatibility // backward compatibility
if versionURLTemplate == "" { if versionURLTemplate == "" {
text = l.activeCommand.buildVersionURL(text, l.versionURLTemplate) text = l.buildVersionURL(text)
} else { } else {
template := &textTemplate{ template := &textTemplate{
Template: versionURLTemplate, Template: versionURLTemplate,
Context: l.activeCommand.version, Context: l.version,
Env: l.env, Env: l.env,
} }
url, err := template.render() url, err := template.render()
@ -203,19 +183,19 @@ func (l *language) setVersion() error {
if !l.env.hasCommand(command.executable) { if !l.env.hasCommand(command.executable) {
continue continue
} }
version, err := l.env.runCommand(command.executable, command.args...) versionStr, err := l.env.runCommand(command.executable, command.args...)
if exitErr, ok := err.(*commandError); ok { if exitErr, ok := err.(*commandError); ok {
l.exitCode = exitErr.exitCode l.exitCode = exitErr.exitCode
return fmt.Errorf("err executing %s with %s", command.executable, command.args) return fmt.Errorf("err executing %s with %s", command.executable, command.args)
} }
if version == "" { if versionStr == "" {
continue continue
} }
err = command.parse(version) version, err := command.parse(versionStr)
if err != nil { if err != nil {
return fmt.Errorf("err parsing info from %s with %s", command.executable, version) return fmt.Errorf("err parsing info from %s with %s", command.executable, versionStr)
} }
l.activeCommand = command l.version = *version
return nil return nil
} }
return errors.New(l.props.getString(MissingCommandText, "")) return errors.New(l.props.getString(MissingCommandText, ""))
@ -245,3 +225,24 @@ func (l *language) setVersionFileMismatch() {
} }
l.props[ForegroundOverride] = l.props.getColor(VersionMismatchColor, l.props.getColor(ForegroundOverride, "")) l.props[ForegroundOverride] = l.props.getColor(VersionMismatchColor, l.props.getColor(ForegroundOverride, ""))
} }
func (l *language) buildVersionURL(text string) string {
if l.versionURLTemplate == "" {
return text
}
truncatingSprintf := func(str string, args ...interface{}) (string, error) {
n := strings.Count(str, "%s")
if n > len(args) {
return "", errors.New("Too many parameters")
}
if n == 0 {
return fmt.Sprintf(str, args...), nil
}
return fmt.Sprintf(str, args[:n]...), nil
}
version, err := truncatingSprintf(l.versionURLTemplate, text, l.version.Major, l.version.Minor, l.version.Patch)
if err != nil {
return text
}
return version
}

View file

@ -3,8 +3,9 @@ package main
import "fmt" import "fmt"
type node struct { type node struct {
language *language
packageManagerIcon string packageManagerIcon string
language
} }
const ( const (
@ -22,7 +23,7 @@ func (n *node) string() string {
} }
func (n *node) init(props properties, env environmentInfo) { func (n *node) init(props properties, env environmentInfo) {
n.language = &language{ n.language = language{
env: env, env: env,
props: props, props: props,
extensions: []string{"*.js", "*.ts", "package.json", ".nvmrc", "pnpm-workspace.yaml", ".pnpmfile.cjs", ".npmrc"}, extensions: []string{"*.js", "*.ts", "package.json", ".nvmrc", "pnpm-workspace.yaml", ".pnpmfile.cjs", ".npmrc"},
@ -64,9 +65,9 @@ func (n *node) matchesVersionFile() bool {
regex := fmt.Sprintf( regex := fmt.Sprintf(
`(?im)^v?%s(\.?%s)?(\.?%s)?$`, `(?im)^v?%s(\.?%s)?(\.?%s)?$`,
n.language.activeCommand.version.Major, n.language.version.Major,
n.language.activeCommand.version.Minor, n.language.version.Minor,
n.language.activeCommand.version.Patch, n.language.version.Patch,
) )
return matchString(regex, fileVersion) return matchString(regex, fileVersion)

View file

@ -33,12 +33,10 @@ func TestNodeMatchesVersionFile(t *testing.T) {
env.On("getFileContent", ".nvmrc").Return(tc.RCVersion) env.On("getFileContent", ".nvmrc").Return(tc.RCVersion)
node := &node{ node := &node{
language: &language{ language: language{
env: env, env: env,
activeCommand: &cmd{
version: nodeVersion, version: nodeVersion,
}, },
},
} }
assert.Equal(t, tc.Expected, node.matchesVersionFile(), tc.Case) assert.Equal(t, tc.Expected, node.matchesVersionFile(), tc.Case)
} }
@ -67,7 +65,7 @@ func TestNodeInContext(t *testing.T) {
env.On("hasFiles", "package-lock.json").Return(tc.hasNPM) env.On("hasFiles", "package-lock.json").Return(tc.hasNPM)
env.On("hasFiles", "package.json").Return(tc.hasDefault) env.On("hasFiles", "package.json").Return(tc.hasDefault)
node := &node{ node := &node{
language: &language{ language: language{
env: env, env: env,
props: map[Property]interface{}{ props: map[Property]interface{}{
YarnIcon: "yarn", YarnIcon: "yarn",

View file

@ -1,7 +1,7 @@
package main package main
type php struct { type php struct {
language *language language
} }
func (n *php) string() string { func (n *php) string() string {
@ -9,7 +9,7 @@ func (n *php) string() string {
} }
func (n *php) init(props properties, env environmentInfo) { func (n *php) init(props properties, env environmentInfo) {
n.language = &language{ n.language = language{
env: env, env: env,
props: props, props: props,
extensions: []string{"*.php", "composer.json", "composer.lock", ".php-version"}, extensions: []string{"*.php", "composer.json", "composer.lock", ".php-version"},

View file

@ -3,7 +3,7 @@ package main
import "fmt" import "fmt"
type python struct { type python struct {
language *language language
venvName string venvName string
} }
@ -24,7 +24,7 @@ func (p *python) string() string {
} }
func (p *python) init(props properties, env environmentInfo) { func (p *python) init(props properties, env environmentInfo) {
p.language = &language{ p.language = language{
env: env, env: env,
props: props, props: props,
extensions: []string{"*.py", "*.ipynb", "pyproject.toml", "venv.bak", "venv", ".venv"}, extensions: []string{"*.py", "*.ipynb", "pyproject.toml", "venv.bak", "venv", ".venv"},

View file

@ -1,7 +1,7 @@
package main package main
type ruby struct { type ruby struct {
language *language language
} }
func (r *ruby) string() string { func (r *ruby) string() string {
@ -14,7 +14,7 @@ func (r *ruby) string() string {
} }
func (r *ruby) init(props properties, env environmentInfo) { func (r *ruby) init(props properties, env environmentInfo) {
r.language = &language{ r.language = language{
env: env, env: env,
props: props, props: props,
extensions: []string{"*.rb", "Rakefile", "Gemfile"}, extensions: []string{"*.rb", "Rakefile", "Gemfile"},

View file

@ -1,7 +1,7 @@
package main package main
type rust struct { type rust struct {
language *language language
} }
func (r *rust) string() string { func (r *rust) string() string {
@ -9,7 +9,7 @@ func (r *rust) string() string {
} }
func (r *rust) init(props properties, env environmentInfo) { func (r *rust) init(props properties, env environmentInfo) {
r.language = &language{ r.language = language{
env: env, env: env,
props: props, props: props,
extensions: []string{"*.rs", "Cargo.toml", "Cargo.lock"}, extensions: []string{"*.rs", "Cargo.toml", "Cargo.lock"},