From 266ba45ecb5e4a771c51d71d55569bbf18a20edf Mon Sep 17 00:00:00 2001 From: Jason Shirk Date: Fri, 18 Oct 2019 19:39:28 -0700 Subject: [PATCH] Improve handling of color in prompts --- PSReadLine/Cmdlets.cs | 4 ++-- PSReadLine/ReadLine.cs | 2 +- PSReadLine/Render.cs | 29 +++++++++++++++++++---------- test/UnitTestReadLine.cs | 6 +++--- 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/PSReadLine/Cmdlets.cs b/PSReadLine/Cmdlets.cs index b2ff9de6e..e4e4658b9 100644 --- a/PSReadLine/Cmdlets.cs +++ b/PSReadLine/Cmdlets.cs @@ -321,7 +321,7 @@ public object ContinuationPromptColor /// If the prompt function is pure, this value can be inferred, e.g. /// the default prompt will use "> " for this value. /// - public string PromptText { get; set; } + public string[] PromptText { get; set; } public object DefaultTokenColor { @@ -663,7 +663,7 @@ public int AnsiEscapeTimeout [Parameter] [ValidateNotNull] - public string PromptText { get; set; } + public string[] PromptText { get; set; } [Parameter] public ViModeStyle ViModeIndicator diff --git a/PSReadLine/ReadLine.cs b/PSReadLine/ReadLine.cs index fb07be6a0..a74595fa8 100644 --- a/PSReadLine/ReadLine.cs +++ b/PSReadLine/ReadLine.cs @@ -761,7 +761,7 @@ private void DelayedOneTimeInitialize() if (i >= 0) { - _options.PromptText = evaluatedPrompt.Substring(i); + _options.PromptText = new [] { evaluatedPrompt.Substring(i) }; } } } diff --git a/PSReadLine/Render.cs b/PSReadLine/Render.cs index 02cb1da12..75ae79b7e 100644 --- a/PSReadLine/Render.cs +++ b/PSReadLine/Render.cs @@ -364,18 +364,18 @@ void MaybeEmphasize(int i, string currColor) /// private bool RenderErrorPrompt(RenderData renderData, string defaultColor) { - // We may need to flip the color on the prompt if the error state changed. - - int bufferWidth = _console.BufferWidth; - string promptText = _options.PromptText; - - if (string.IsNullOrEmpty(promptText) || _initialY < 0) + if (_initialY < 0 + || _options.PromptText == null + || _options.PromptText.Length == 0 + || String.IsNullOrEmpty(_options.PromptText[0])) { // No need to flip the prompt color if either the error prompt is not defined // or the initial cursor point has already been scrolled off the buffer. return false; } + // We may need to flip the color on the prompt if the error state changed. + renderData.errorPrompt = (_parseErrors != null && _parseErrors.Length > 0); if (renderData.errorPrompt == _previousRender.errorPrompt) { @@ -386,9 +386,15 @@ private bool RenderErrorPrompt(RenderData renderData, string defaultColor) // We need to update the prompt _console.SetCursorPosition(_initialX, _initialY); + string promptText = + (renderData.errorPrompt && _options.PromptText.Length == 2) + ? _options.PromptText[1] + : _options.PromptText[0]; + // promptBufferCells is the number of visible characters in the prompt int promptBufferCells = LengthInBufferCells(promptText); bool renderErrorPrompt = false; + int bufferWidth = _console.BufferWidth; if (_console.CursorLeft >= promptBufferCells) { @@ -419,12 +425,15 @@ private bool RenderErrorPrompt(RenderData renderData, string defaultColor) if (renderErrorPrompt) { - string color = renderData.errorPrompt ? _options._errorColor : defaultColor; - if (renderData.errorPrompt && promptBufferCells != promptText.Length) + if (!promptText.Contains('\x1b')) { - promptText = promptText.Substring(promptText.Length - promptBufferCells); + string color = renderData.errorPrompt ? _options._errorColor : defaultColor; + if (renderData.errorPrompt && promptBufferCells != promptText.Length) + { + promptText = promptText.Substring(promptText.Length - promptBufferCells); + } + _console.Write(color); } - _console.Write(color); _console.Write(promptText); _console.Write("\x1b[0m"); } diff --git a/test/UnitTestReadLine.cs b/test/UnitTestReadLine.cs index bba9de340..b17e3345a 100644 --- a/test/UnitTestReadLine.cs +++ b/test/UnitTestReadLine.cs @@ -354,7 +354,7 @@ private void SetPrompt(string prompt) var options = new SetPSReadLineOption {ExtraPromptLineCount = 0}; if (string.IsNullOrEmpty(prompt)) { - options.PromptText = ""; + options.PromptText = new [] {""}; PSConsoleReadLine.SetOptions(options); return; } @@ -365,7 +365,7 @@ private void SetPrompt(string prompt) if (!char.IsWhiteSpace(prompt[i])) break; } - options.PromptText = prompt.Substring(i); + options.PromptText = new [] { prompt.Substring(i) }; var lineCount = 1 + prompt.Count(c => c == '\n'); if (lineCount > 1) @@ -474,7 +474,7 @@ private void TestSetup(KeyMode keyMode, params KeyHandler[] keyHandlers) MaximumKillRingCount = PSConsoleReadLineOptions.DefaultMaximumKillRingCount, ShowToolTips = PSConsoleReadLineOptions.DefaultShowToolTips, WordDelimiters = PSConsoleReadLineOptions.DefaultWordDelimiters, - PromptText = "", + PromptText = new [] {""}, Colors = new Hashtable { { "ContinuationPrompt", MakeCombinedColor(_console.ForegroundColor, _console.BackgroundColor) }, { "Emphasis", MakeCombinedColor(PSConsoleReadLineOptions.DefaultEmphasisColor, _console.BackgroundColor) },