mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2024-12-27 20:09:39 -08:00
parent
6980cb55e7
commit
5a57d6909d
|
@ -3,7 +3,6 @@ package template
|
|||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"oh-my-posh/environment"
|
||||
"oh-my-posh/regex"
|
||||
"strings"
|
||||
|
@ -66,21 +65,6 @@ func (t *Text) Render() (string, error) {
|
|||
}
|
||||
|
||||
func (t *Text) cleanTemplate() {
|
||||
unknownVariable := func(variable string, knownVariables *[]string) (string, bool) {
|
||||
variable = strings.TrimPrefix(variable, ".")
|
||||
splitted := strings.Split(variable, ".")
|
||||
if len(splitted) == 0 {
|
||||
return "", false
|
||||
}
|
||||
for _, b := range *knownVariables {
|
||||
if b == splitted[0] {
|
||||
return "", false
|
||||
}
|
||||
}
|
||||
*knownVariables = append(*knownVariables, splitted[0])
|
||||
return splitted[0], true
|
||||
}
|
||||
|
||||
knownVariables := []string{
|
||||
"Root",
|
||||
"PWD",
|
||||
|
@ -97,14 +81,72 @@ func (t *Text) cleanTemplate() {
|
|||
"Segments",
|
||||
"Templates",
|
||||
}
|
||||
matches := regex.FindAllNamedRegexMatch(`(?: |{|\()(?P<VAR>(\.[a-zA-Z_][a-zA-Z0-9]*)+)`, t.Template)
|
||||
for _, match := range matches {
|
||||
if variable, OK := unknownVariable(match["VAR"], &knownVariables); OK {
|
||||
pattern := fmt.Sprintf(`\.%s\b`, variable)
|
||||
dataVar := fmt.Sprintf(".Data.%s", variable)
|
||||
t.Template = regex.ReplaceAllString(pattern, t.Template, dataVar)
|
||||
|
||||
knownVariable := func(variable string) bool {
|
||||
variable = strings.TrimPrefix(variable, ".")
|
||||
splitted := strings.Split(variable, ".")
|
||||
if len(splitted) == 0 {
|
||||
return false
|
||||
}
|
||||
variable = splitted[0]
|
||||
for _, b := range knownVariables {
|
||||
if variable == b {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
walkAndReplace := func(node string) string {
|
||||
var result string
|
||||
var property string
|
||||
var inProperty bool
|
||||
// var literal bool
|
||||
for _, char := range node {
|
||||
switch char {
|
||||
case '.':
|
||||
var lastChar rune
|
||||
if len(result) > 0 {
|
||||
lastChar = rune(result[len(result)-1])
|
||||
}
|
||||
// only replace if we're in a valid property start
|
||||
// with a space, { or ( character
|
||||
switch lastChar {
|
||||
case ' ', '{', '(':
|
||||
property += string(char)
|
||||
inProperty = true
|
||||
default:
|
||||
result += string(char)
|
||||
}
|
||||
case ' ', '}', ')': // space or }
|
||||
if !inProperty {
|
||||
result += string(char)
|
||||
continue
|
||||
}
|
||||
// end of a variable, needs to be appended
|
||||
if !knownVariable(property) {
|
||||
result += ".Data" + property
|
||||
} else {
|
||||
result += property
|
||||
}
|
||||
property = ""
|
||||
result += string(char)
|
||||
inProperty = false
|
||||
default:
|
||||
if inProperty {
|
||||
property += string(char)
|
||||
continue
|
||||
}
|
||||
result += string(char)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// matches := regex.FindAllNamedRegexMatch(`(?: |{|\()(?P<VAR>(\.[a-zA-Z_][a-zA-Z0-9]*)+)`, t.Template)
|
||||
matches := regex.FindAllNamedRegexMatch(`(?P<NODE>{{[^{]+}})`, t.Template)
|
||||
for _, match := range matches {
|
||||
node := walkAndReplace(match["NODE"])
|
||||
t.Template = strings.Replace(t.Template, match["NODE"], node, 1)
|
||||
}
|
||||
// allow literal dots in template
|
||||
t.Template = strings.ReplaceAll(t.Template, `\.`, ".")
|
||||
}
|
||||
|
|
|
@ -10,6 +10,9 @@ import (
|
|||
)
|
||||
|
||||
func TestRenderTemplate(t *testing.T) {
|
||||
type Me struct {
|
||||
Name string
|
||||
}
|
||||
cases := []struct {
|
||||
Case string
|
||||
Expected string
|
||||
|
@ -17,11 +20,68 @@ func TestRenderTemplate(t *testing.T) {
|
|||
ShouldError bool
|
||||
Context interface{}
|
||||
}{
|
||||
{Case: "single property", Expected: "hello world", Template: "{{.Text}} world", Context: struct{ Text string }{Text: "hello"}},
|
||||
{Case: "invalid property", ShouldError: true, Template: "{{.Durp}} world", Context: struct{ Text string }{Text: "hello"}},
|
||||
{Case: "invalid template", ShouldError: true, Template: "{{ if .Text }} world", Context: struct{ Text string }{Text: "hello"}},
|
||||
{Case: "if statement true", Expected: "hello world", Template: "{{ if .Text }}{{.Text}} world{{end}}", Context: struct{ Text string }{Text: "hello"}},
|
||||
{Case: "if statement false", Expected: "world", Template: "{{ if .Text }}{{.Text}} {{end}}world", Context: struct{ Text string }{Text: ""}},
|
||||
{
|
||||
Case: "Env like property name",
|
||||
Expected: "hello world",
|
||||
Template: "{{.EnvLike}} {{.Text2}}",
|
||||
Context: struct {
|
||||
EnvLike string
|
||||
Text2 string
|
||||
}{
|
||||
EnvLike: "hello",
|
||||
Text2: "world",
|
||||
},
|
||||
},
|
||||
{
|
||||
Case: "single property with a dot literal",
|
||||
Expected: "hello world",
|
||||
Template: "{{ if eq .Text \".Net\" }}hello world{{ end }}",
|
||||
Context: struct{ Text string }{Text: ".Net"},
|
||||
},
|
||||
{
|
||||
Case: "single property",
|
||||
Expected: "hello world",
|
||||
Template: "{{.Text}} world",
|
||||
Context: struct{ Text string }{Text: "hello"},
|
||||
},
|
||||
{
|
||||
Case: "duplicate property",
|
||||
Expected: "hello jan posh",
|
||||
Template: "hello {{ .Me.Name }} {{ .Name }}",
|
||||
Context: struct {
|
||||
Name string
|
||||
Me Me
|
||||
}{
|
||||
Name: "posh",
|
||||
Me: Me{
|
||||
Name: "jan",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Case: "invalid property",
|
||||
ShouldError: true,
|
||||
Template: "{{.Durp}} world",
|
||||
Context: struct{ Text string }{Text: "hello"},
|
||||
},
|
||||
{
|
||||
Case: "invalid template",
|
||||
ShouldError: true,
|
||||
Template: "{{ if .Text }} world",
|
||||
Context: struct{ Text string }{Text: "hello"},
|
||||
},
|
||||
{
|
||||
Case: "if statement true",
|
||||
Expected: "hello world",
|
||||
Template: "{{ if .Text }}{{.Text}} world{{end}}",
|
||||
Context: struct{ Text string }{Text: "hello"},
|
||||
},
|
||||
{
|
||||
Case: "if statement false",
|
||||
Expected: "world",
|
||||
Template: "{{ if .Text }}{{.Text}} {{end}}world",
|
||||
Context: struct{ Text string }{Text: ""},
|
||||
},
|
||||
{
|
||||
Case: "if statement true with 2 properties",
|
||||
Expected: "hello world",
|
||||
|
@ -86,6 +146,8 @@ func TestRenderTemplate(t *testing.T) {
|
|||
if tc.ShouldError {
|
||||
assert.Error(t, err)
|
||||
continue
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
assert.Equal(t, tc.Expected, text, tc.Case)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue