feat(pwsh): support PromptText

This commit is contained in:
Jan De Dobbeleer 2022-02-19 16:49:26 +01:00 committed by Jan De Dobbeleer
parent 3d4fc5b6dd
commit cb70ed4b41
9 changed files with 193 additions and 42 deletions

View file

@ -0,0 +1,86 @@
---
id: config-line-error
title: Line error
sidebar_label: Line error
---
:::info
This feature only works in `powershell` for the time being.
:::
Line error, when enabled, replaces the last part of the prompt when the text entered is invalid. It leverages
[PSReadLine's][psreadline] `-PromptText` setting by adding two distinct prompts. One for a valid line,
and one for when there's an error. As PSReadLine will rewrite the last part of
your prompt with the value of either based on the line's context, you will need to make sure everything
is compatible with your config as **these values are only set once** on shell start.
There are two config settings you need to tweak:
- `valid_line`: displays when the line is valid (again)
- `error_line`: displays when the line is faulty
You can use go [text/template][go-text-template] templates extended with [sprig][sprig] to enrich the text.
Environment variables are available, just like the [`console_title_template`][console-title] functionality.
## Configuration
You need to extend or create a custom theme with your prompt overrides. For example:
```json
{
"$schema": "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json",
"blocks": {
...
}
"valid_line": {
"background": "transparent",
"foreground": "#ffffff",
"template": "<#e0def4,#286983>\uf42e </><#286983,transparent>\ue0b4</> "
},
"error_line": {
"background": "transparent",
"foreground": "#ffffff",
"template": "<#eb6f92,#286983>\ue009 </><#286983,transparent>\ue0b4</> "
}
}
```
The configuration has the following properties:
- background: `string` [color][colors]
- foreground: `string` [color][colors]
- template: `string` - A go [text/template][go-text-template] template extended with [sprig][sprig] utilizing the
properties below - defaults to ` `
## Template ([info][templates])
- `.Root`: `boolean` - is the current user root/admin or not
- `.PWD`: `string` - the current working directory
- `.Folder`: `string` - the current working folder
- `.Shell`: `string` - the current shell name
- `.UserName`: `string` - the current user name
- `.HostName`: `string` - the host name
- `.Env.VarName`: `string` - Any environment variable where `VarName` is the environment variable name
## Enable the feature
Invoke Oh My Posh in your `$PROFILE` and add the following line below.
```powershell
oh-my-posh --init --shell pwsh --config $env:POSH_THEMES_PATH/jandedobbeleer.omp.json | Invoke-Expression
// highlight-start
Enable-PoshLineError
// highlight-end
```
:::caution
If you import **PSReadLine** separately, make sure to import it before the `Enable-PoshLineError` command.
:::
Restart your shell or reload your `$PROFILE` using `. $PROFILE` for the changes to take effect.
[go-text-template]: https://golang.org/pkg/text/template/
[sprig]: https://masterminds.github.io/sprig/
[console-title]: /docs/config-title#console-title-template
[psreadline]: https://github.com/PowerShell/PSReadLine
[templates]: /docs/config-templates

View file

@ -118,3 +118,4 @@ Restart your shell or reload `.zshrc` using `source ~/.zshrc` for the changes to
[console-title]: /docs/config-title#console-title-template [console-title]: /docs/config-title#console-title-template
[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

View file

@ -27,6 +27,7 @@ module.exports = {
"config-colors", "config-colors",
"config-templates", "config-templates",
"config-transient", "config-transient",
"config-line-error",
"config-tooltips", "config-tooltips",
"config-fonts", "config-fonts",
], ],

View file

@ -39,7 +39,9 @@ type Config struct {
TerminalBackground string `json:"terminal_background,omitempty"` TerminalBackground string `json:"terminal_background,omitempty"`
Blocks []*Block `json:"blocks,omitempty"` Blocks []*Block `json:"blocks,omitempty"`
Tooltips []*Segment `json:"tooltips,omitempty"` Tooltips []*Segment `json:"tooltips,omitempty"`
TransientPrompt *TransientPrompt `json:"transient_prompt,omitempty"` TransientPrompt *ExtraPrompt `json:"transient_prompt,omitempty"`
ValidLine *ExtraPrompt `json:"valid_line,omitempty"`
ErrorLine *ExtraPrompt `json:"error_line,omitempty"`
Palette color.Palette `json:"palette,omitempty"` Palette color.Palette `json:"palette,omitempty"`
format string format string
@ -55,7 +57,7 @@ func (cfg *Config) MakeColors(env environment.Environment) color.AnsiColors {
return color.MakeColors(cfg.Palette, !cacheDisabled) return color.MakeColors(cfg.Palette, !cacheDisabled)
} }
type TransientPrompt struct { type ExtraPrompt struct {
Template string `json:"template,omitempty"` Template string `json:"template,omitempty"`
Background string `json:"background,omitempty"` Background string `json:"background,omitempty"`
Foreground string `json:"foreground,omitempty"` Foreground string `json:"foreground,omitempty"`
@ -119,7 +121,7 @@ func loadConfig(env environment.Environment) *Config {
// initialize default values // initialize default values
if cfg.TransientPrompt == nil { if cfg.TransientPrompt == nil {
cfg.TransientPrompt = &TransientPrompt{} cfg.TransientPrompt = &ExtraPrompt{}
} }
return &cfg return &cfg

View file

@ -266,24 +266,48 @@ func (e *Engine) RenderTooltip(tip string) string {
return "" return ""
} }
func (e *Engine) RenderTransientPrompt() string { type ExtraPromptType int
if e.Config.TransientPrompt == nil {
const (
Transient ExtraPromptType = iota
Valid
Error
)
func (e *Engine) RenderExtraPrompt(promptType ExtraPromptType) string {
var prompt *ExtraPrompt
switch promptType {
case Transient:
prompt = e.Config.TransientPrompt
case Valid:
prompt = e.Config.ValidLine
case Error:
prompt = e.Config.ErrorLine
}
if prompt == nil {
return ""
}
getTemplate := func(template string) string {
if len(template) != 0 {
return template
}
switch promptType { // nolint: exhaustive
case Transient:
return "{{ .Shell }}> "
default:
return "" return ""
} }
promptTemplate := e.Config.TransientPrompt.Template
if len(promptTemplate) == 0 {
promptTemplate = "{{ .Shell }}> "
} }
tmpl := &template.Text{ tmpl := &template.Text{
Template: promptTemplate, Template: getTemplate(prompt.Template),
Env: e.Env, Env: e.Env,
} }
prompt, err := tmpl.Render() promptText, err := tmpl.Render()
if err != nil { if err != nil {
prompt = err.Error() promptText = err.Error()
} }
e.Writer.SetColors(e.Config.TransientPrompt.Background, e.Config.TransientPrompt.Foreground) e.Writer.SetColors(prompt.Background, prompt.Foreground)
e.Writer.Write(e.Config.TransientPrompt.Background, e.Config.TransientPrompt.Foreground, prompt) e.Writer.Write(prompt.Background, prompt.Foreground, promptText)
switch e.Env.Shell() { switch e.Env.Shell() {
case zsh: case zsh:
// escape double quotes contained in the prompt // escape double quotes contained in the prompt

View file

@ -3,7 +3,7 @@
if ($ExecutionContext.SessionState.LanguageMode -ne "ConstrainedLanguage") { if ($ExecutionContext.SessionState.LanguageMode -ne "ConstrainedLanguage") {
[console]::InputEncoding = [console]::OutputEncoding = New-Object System.Text.UTF8Encoding [console]::InputEncoding = [console]::OutputEncoding = New-Object System.Text.UTF8Encoding
} }
elseif ($env:POSH_CONSTRAINED_LANGUAGE_MODE -ne $true){ elseif ($env:POSH_CONSTRAINED_LANGUAGE_MODE -ne $true) {
Write-Host "[WARNING] ConstrainedLanguage mode detected, unable to set console to UTF-8. Write-Host "[WARNING] ConstrainedLanguage mode detected, unable to set console to UTF-8.
When using PowerShell in ConstrainedLanguage mode, please set the When using PowerShell in ConstrainedLanguage mode, please set the
console mode manually to UTF-8. See here for more information: console mode manually to UTF-8. See here for more information:
@ -210,6 +210,13 @@ function global:Enable-PoshTransientPrompt {
} }
} }
function global:Enable-PoshLineError {
$omp = "::OMP::"
$validLine = @(&$omp --config="$Env:POSH_THEME" --print-valid 2>&1) -join "`n"
$errorLine = @(&$omp --config="$Env:POSH_THEME" --print-error 2>&1) -join "`n"
Set-PSReadLineOption -PromptText $validLine, $errorLine
}
<# <#
.SYNOPSIS .SYNOPSIS
Returns an ansi formatted hyperlink Returns an ansi formatted hyperlink

View file

@ -29,10 +29,14 @@ const (
type Args struct { type Args struct {
ErrorCode *int ErrorCode *int
PrintInit *bool
PrintConfig *bool PrintConfig *bool
ConfigFormat *string
PrintShell *bool PrintShell *bool
PrintTransient *bool
PrintValid *bool
PrintError *bool
Config *string Config *string
ConfigFormat *string
Shell *string Shell *string
PWD *string PWD *string
PSWD *string PSWD *string
@ -42,7 +46,6 @@ type Args struct {
Millis *bool Millis *bool
Eval *bool Eval *bool
Init *bool Init *bool
PrintInit *bool
ExportPNG *bool ExportPNG *bool
Author *string Author *string
CursorPadding *int CursorPadding *int
@ -51,7 +54,6 @@ type Args struct {
BGColor *string BGColor *string
StackCount *int StackCount *int
Command *string Command *string
PrintTransient *bool
Plain *bool Plain *bool
CachePath *bool CachePath *bool
Migrate *bool Migrate *bool

View file

@ -133,6 +133,14 @@ func main() {
"terminal-width", "terminal-width",
0, 0,
"The width of the terminal"), "The width of the terminal"),
PrintValid: flag.Bool(
"print-valid",
false,
"Print the valid prompt"),
PrintError: flag.Bool(
"print-error",
false,
"Print the failed prompt"),
} }
flag.Parse() flag.Parse()
if *args.Version { if *args.Version {
@ -210,7 +218,15 @@ func main() {
return return
} }
if *args.PrintTransient { if *args.PrintTransient {
fmt.Print(eng.RenderTransientPrompt()) fmt.Print(eng.RenderExtraPrompt(engine.Transient))
return
}
if *args.PrintValid {
fmt.Print(eng.RenderExtraPrompt(engine.Valid))
return
}
if *args.PrintError {
fmt.Print(eng.RenderExtraPrompt(engine.Error))
return return
} }
if len(*args.Command) != 0 { if len(*args.Command) != 0 {

View file

@ -64,6 +64,18 @@
"description": "https://ohmyposh.dev/docs/config-templates", "description": "https://ohmyposh.dev/docs/config-templates",
"default": "" "default": ""
}, },
"extra_prompt": {
"type": "object",
"default": {},
"properties": {
"template": {
"type": "string",
"title": "Prompt Template"
},
"background": { "$ref": "#/definitions/color" },
"foreground": { "$ref": "#/definitions/color" }
}
},
"block": { "block": {
"type": "object", "type": "object",
"description": "https://ohmyposh.dev/docs/config-overview#block", "description": "https://ohmyposh.dev/docs/config-overview#block",
@ -2008,7 +2020,7 @@
"tooltips": { "tooltips": {
"type": "array", "type": "array",
"title": "Tooltip list, prompt elements to display based on context", "title": "Tooltip list, prompt elements to display based on context",
"description": "https://ohmyposh.dev/docs/beta#tooltips", "description": "https://ohmyposh.dev/docs/config-tooltips",
"default": [], "default": [],
"items": { "items": {
"allOf": [{ "$ref": "#/definitions/segment" }], "allOf": [{ "$ref": "#/definitions/segment" }],
@ -2025,19 +2037,19 @@
} }
}, },
"transient_prompt": { "transient_prompt": {
"type": "object", "$ref": "#/definitions/extra_prompt",
"title": "Transient Prompt Settings", "title": "Transient Prompt Setting",
"description": "https://ohmyposh.dev/docs/beta#transient-prompt", "description": "https://ohmyposh.dev/docs/config-transient"
"default": {},
"properties": {
"template": {
"type": "string",
"title": "Transient Prompt Template",
"default": "{{ .Shell }}> <#f7dc66>{{ .Command }}</>"
}, },
"background": { "$ref": "#/definitions/color" }, "valid_line": {
"foreground": { "$ref": "#/definitions/color" } "$ref": "#/definitions/extra_prompt",
} "title": "Valid Prompt Setting",
"description": "https://ohmyposh.dev/docs/config-prompt-override"
},
"error_line": {
"$ref": "#/definitions/extra_prompt",
"title": "Error Prompt Setting",
"description": "https://ohmyposh.dev/docs/config-prompt-override"
}, },
"palette": { "palette": {
"type": "object", "type": "object",