feat(transient): color template support

This commit is contained in:
Jan De Dobbeleer 2022-03-24 12:53:20 +01:00 committed by Jan De Dobbeleer
parent e1a1febc79
commit 8b5c2a35ca
9 changed files with 94 additions and 86 deletions

View file

@ -25,6 +25,34 @@ Oh My Posh supports multiple different color references, being:
`darkGray` `lightRed` `lightGreen` `lightYellow` `lightBlue` `lightMagenta` `lightCyan` `lightWhite` `darkGray` `lightRed` `lightGreen` `lightYellow` `lightBlue` `lightMagenta` `lightCyan` `lightWhite`
## Color templates
Array of string templates to define the color based on the current context.
Under the hood this uses go's [text/template][go-text-template] feature extended with [sprig][sprig] and
offers a few standard properties to work with. For segments, you can look at the **Template Properties**
section in the documentation. The general template properties are listed [here][template-properties].
The following sample is based on the [AWS Segment][aws].
```json
{
"type": "aws",
"style": "powerline",
"powerline_symbol": "\uE0B0",
"foreground": "#ffffff",
"background": "#111111",
"foreground_templates": [
"{{if contains \"default\" .Profile}}#FFA400{{end}}",
"{{if contains \"jan\" .Profile}}#f1184c{{end}}"
]
}
```
The logic is as follows: when `foreground_templates` contains an array, we will check every template line until there's
one that returns a non-empty string. So, when the contents of `.Profile` contain the word `default`, the first template
returns `#FFA400` and that's the color that will be used. If it contains `jan`, it returns `#f1184c`. When none of the
templates returns a value, the foreground value `#ffffff` is used as a fallback value.
## Color overrides ## Color overrides
You have the ability to override the foreground and/or background color for text in any property that accepts it. You have the ability to override the foreground and/or background color for text in any property that accepts it.
@ -164,3 +192,5 @@ For example, `p:foreground` and `p:background` will be correctly set to "#CAF0F8
[ansicolors]: https://htmlcolorcodes.com/color-chart/material-design-color-chart/ [ansicolors]: https://htmlcolorcodes.com/color-chart/material-design-color-chart/
[git]: /docs/segment-git [git]: /docs/segment-git
[battery]: /docs/segment-battery [battery]: /docs/segment-battery
[template-properties]: /docs/config-templates#global-properties
[aws]: /docs/aws

View file

@ -39,9 +39,9 @@ understand how to configure a segment.
- leading_diamond: `string` - leading_diamond: `string`
- trailing_diamond: `string` - trailing_diamond: `string`
- foreground: `string` [color][colors] - foreground: `string` [color][colors]
- foreground_templates: `array` of `string` values - foreground_templates: foreground [color templates][color-templates]
- background: `string` [color][colors] - background: `string` [color][colors]
- background_templates: `array` of `string` values - background_templates: background [color templates][color-templates]
- properties: `array` of `Property`: `string` - properties: `array` of `Property`: `string`
## Type ## Type
@ -89,46 +89,6 @@ its foreground color.
Text character to use at the end of the segment. Will take the background color of the segment as its foreground color. Text character to use at the end of the segment. Will take the background color of the segment as its foreground color.
## Foreground
[Color][colors] to use as the segment text foreground color. Also supports transparency using the `transparent` keyword.
## Foreground Templates
Array if string templates to define the foreground color for the given Segment based on the Segment's Template Properties.
Under the hood this uses go's [text/template][go-text-template] feature extended with [sprig][sprig] and
offers a few standard properties to work with. For supported Segments, look for the **Template Properties** section in
the documentation.
The following sample is based on the [AWS Segment][aws].
```json
{
"type": "aws",
"style": "powerline",
"powerline_symbol": "\uE0B0",
"foreground": "#ffffff",
"background": "#111111",
"foreground_templates": [
"{{if contains \"default\" .Profile}}#FFA400{{end}}",
"{{if contains \"jan\" .Profile}}#f1184c{{end}}"
]
}
```
The logic is as follows: when `background_templates` contains an array, we will check every template line until there's
one that returns a non-empty string. So, when the contents of `.Profile` contain the word `default`, the first template
returns `#FFA400` and that's the color that will be used. If it contains `jan`, it returns `#f1184c`. When none of the
templates returns a value, the foreground value `#ffffff` is used.
## Background
[Color][colors] to use as the segment text background color. Also supports transparency using the `transparent` keyword.
## Background Templates
Same as [Foreground Templates][fg-templ] but for the background color.
## Properties ## Properties
An array of **Properties** with a value. This is used inside of the segment logic to tweak what the output of the segment An array of **Properties** with a value. This is used inside of the segment logic to tweak what the output of the segment
@ -198,7 +158,6 @@ This means that for user Bill, who has a user account `Bill` on Windows and `bil
[colors]: /docs/config-colors [colors]: /docs/config-colors
[go-text-template]: https://golang.org/pkg/text/template/ [go-text-template]: https://golang.org/pkg/text/template/
[sprig]: https://masterminds.github.io/sprig/ [sprig]: https://masterminds.github.io/sprig/
[fg-templ]: /docs/config-overview#foreground-templates
[regex]: https://www.regular-expressions.info/tutorial.html [regex]: https://www.regular-expressions.info/tutorial.html
[aws]: /docs/aws
[templates]: /docs/config-templates [templates]: /docs/config-templates
[color-templates]: /docs/config-colors#color-templates

View file

@ -44,8 +44,10 @@ You need to extend or create a custom theme with your transient prompt. For exam
The configuration has the following properties: The configuration has the following properties:
- background: `string` [color][colors]
- foreground: `string` [color][colors] - foreground: `string` [color][colors]
- foreground_templates: foreground [color templates][color-templates]
- background: `string` [color][colors]
- background_templates: background [color templates][color-templates]
- template: `string` - A go [text/template][go-text-template] template extended with [sprig][sprig] utilizing the - template: `string` - A go [text/template][go-text-template] template extended with [sprig][sprig] utilizing the
properties below - defaults to `{{ .Shell }}> ` properties below - defaults to `{{ .Shell }}> `
@ -131,3 +133,4 @@ Restart your shell or reload fish using `exec fish` for the changes to take effe
[sprig]: https://masterminds.github.io/sprig/ [sprig]: https://masterminds.github.io/sprig/
[clink]: https://chrisant996.github.io/clink/ [clink]: https://chrisant996.github.io/clink/
[templates]: /docs/config-templates [templates]: /docs/config-templates
[color-templates]: /docs/config-colors#color-templates

27
src/color/templates.go Normal file
View file

@ -0,0 +1,27 @@
package color
import (
"oh-my-posh/environment"
"oh-my-posh/template"
)
type Templates []string
func (t Templates) Resolve(context interface{}, env environment.Environment, defaultColor string) string {
if len(t) == 0 {
return defaultColor
}
txtTemplate := &template.Text{
Context: context,
Env: env,
}
for _, tmpl := range t {
txtTemplate.Template = tmpl
value, err := txtTemplate.Render()
if err != nil || value == "" {
continue
}
return value
}
return defaultColor
}

View file

@ -59,9 +59,11 @@ func (cfg *Config) MakeColors(env environment.Environment) color.AnsiColors {
} }
type ExtraPrompt struct { type ExtraPrompt struct {
Template string `json:"template,omitempty"` Template string `json:"template,omitempty"`
Background string `json:"background,omitempty"` Foreground string `json:"foreground,omitempty"`
Foreground string `json:"foreground,omitempty"` ForegroundTemplates color.Templates `json:"foreground_templates,omitempty"`
Background string `json:"background,omitempty"`
BackgroundTemplates color.Templates `json:"background_templates,omitempty"`
} }
func (cfg *Config) print(message string) { func (cfg *Config) print(message string) {

View file

@ -319,8 +319,10 @@ func (e *Engine) PrintExtraPrompt(promptType ExtraPromptType) string {
if err != nil { if err != nil {
promptText = err.Error() promptText = err.Error()
} }
e.Writer.SetColors(prompt.Background, prompt.Foreground) foreground := prompt.ForegroundTemplates.Resolve(nil, e.Env, prompt.Foreground)
e.Writer.Write(prompt.Background, prompt.Foreground, promptText) background := prompt.BackgroundTemplates.Resolve(nil, e.Env, prompt.Background)
e.Writer.SetColors(background, foreground)
e.Writer.Write(background, foreground, promptText)
switch e.Env.Shell() { switch e.Env.Shell() {
case shell.ZSH: case shell.ZSH:
// escape double quotes contained in the prompt // escape double quotes contained in the prompt

View file

@ -3,6 +3,7 @@ package engine
import ( import (
"errors" "errors"
"fmt" "fmt"
"oh-my-posh/color"
"oh-my-posh/environment" "oh-my-posh/environment"
"oh-my-posh/properties" "oh-my-posh/properties"
"oh-my-posh/segments" "oh-my-posh/segments"
@ -14,18 +15,18 @@ import (
// Segment represent a single segment and it's configuration // Segment represent a single segment and it's configuration
type Segment struct { type Segment struct {
Type SegmentType `json:"type,omitempty"` Type SegmentType `json:"type,omitempty"`
Tips []string `json:"tips,omitempty"` Tips []string `json:"tips,omitempty"`
Style SegmentStyle `json:"style,omitempty"` Style SegmentStyle `json:"style,omitempty"`
PowerlineSymbol string `json:"powerline_symbol,omitempty"` PowerlineSymbol string `json:"powerline_symbol,omitempty"`
InvertPowerline bool `json:"invert_powerline,omitempty"` InvertPowerline bool `json:"invert_powerline,omitempty"`
Foreground string `json:"foreground,omitempty"` Foreground string `json:"foreground,omitempty"`
ForegroundTemplates []string `json:"foreground_templates,omitempty"` ForegroundTemplates color.Templates `json:"foreground_templates,omitempty"`
Background string `json:"background,omitempty"` Background string `json:"background,omitempty"`
BackgroundTemplates []string `json:"background_templates,omitempty"` BackgroundTemplates color.Templates `json:"background_templates,omitempty"`
LeadingDiamond string `json:"leading_diamond,omitempty"` LeadingDiamond string `json:"leading_diamond,omitempty"`
TrailingDiamond string `json:"trailing_diamond,omitempty"` TrailingDiamond string `json:"trailing_diamond,omitempty"`
Properties properties.Map `json:"properties,omitempty"` Properties properties.Map `json:"properties,omitempty"`
writer SegmentWriter writer SegmentWriter
text string text string
@ -207,25 +208,6 @@ func (segment *Segment) cwdExcluded() bool {
return environment.DirMatchesOneOf(segment.env, segment.env.Pwd(), list) return environment.DirMatchesOneOf(segment.env, segment.env.Pwd(), list)
} }
func (segment *Segment) getColor(templates []string, defaultColor string) string {
if len(templates) == 0 {
return defaultColor
}
txtTemplate := &template.Text{
Context: segment.writer,
Env: segment.env,
}
for _, tmpl := range templates {
txtTemplate.Template = tmpl
value, err := txtTemplate.Render()
if err != nil || value == "" {
continue
}
return value
}
return defaultColor
}
func (segment *Segment) shouldInvokeWithTip(tip string) bool { func (segment *Segment) shouldInvokeWithTip(tip string) bool {
for _, t := range segment.Tips { for _, t := range segment.Tips {
if t == tip { if t == tip {
@ -237,14 +219,14 @@ func (segment *Segment) shouldInvokeWithTip(tip string) bool {
func (segment *Segment) foreground() string { func (segment *Segment) foreground() string {
if len(segment.foregroundCache) == 0 { if len(segment.foregroundCache) == 0 {
segment.foregroundCache = segment.getColor(segment.ForegroundTemplates, segment.Foreground) segment.foregroundCache = segment.ForegroundTemplates.Resolve(segment.writer, segment.env, segment.Foreground)
} }
return segment.foregroundCache return segment.foregroundCache
} }
func (segment *Segment) background() string { func (segment *Segment) background() string {
if len(segment.backgroundCache) == 0 { if len(segment.backgroundCache) == 0 {
segment.backgroundCache = segment.getColor(segment.BackgroundTemplates, segment.Background) segment.backgroundCache = segment.BackgroundTemplates.Resolve(segment.writer, segment.env, segment.Background)
} }
return segment.backgroundCache return segment.backgroundCache
} }

View file

@ -5,11 +5,12 @@ set --global omp_tooltip_command ""
set --global omp_transient 0 set --global omp_transient 0
function fish_prompt function fish_prompt
set --local omp_status_cache_temp $status
if test "$omp_transient" = "1" if test "$omp_transient" = "1"
::OMP:: prompt print transient --config $POSH_THEME --shell fish ::OMP:: prompt print transient --config $POSH_THEME --shell fish --error $omp_status_cache --execution-time $omp_duration --stack-count $omp_stack_count
return return
end end
set --global omp_status_cache $status set --global omp_status_cache $omp_status_cache_temp
set --global omp_stack_count (count $dirstack) set --global omp_stack_count (count $dirstack)
set --global omp_duration "$CMD_DURATION$cmd_duration" set --global omp_duration "$CMD_DURATION$cmd_duration"
# check if variable set, < 3.2 case # check if variable set, < 3.2 case

View file

@ -72,8 +72,10 @@
"type": "string", "type": "string",
"title": "Prompt Template" "title": "Prompt Template"
}, },
"foreground": { "$ref": "#/definitions/color" },
"foreground_templates": { "$ref": "#/definitions/color_templates" },
"background": { "$ref": "#/definitions/color" }, "background": { "$ref": "#/definitions/color" },
"foreground": { "$ref": "#/definitions/color" } "background_templates": { "$ref": "#/definitions/color_templates" }
} }
}, },
"block": { "block": {