Skip to content

Commit 4be9473

Browse files
committed
Change selection coloring to not use inverse
Adds Selection as a configuration option for colors. Fix #597
1 parent 8ba9d82 commit 4be9473

File tree

5 files changed

+48
-25
lines changed

5 files changed

+48
-25
lines changed

PSReadLine/Changes.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ There are known issues:
66

77
* Some custom key bindings are broken (#580)
88
* You must use a real terminal emulator, e.g. Windows 10 Creators Update or later, or ConEmu or any Unix terminal. (#596)
9-
* Selection highlighting is weird and broken with extended colors on Windows (#597)
109

1110
Breaking changes:
1211
* Requires PowerShell V5 or later and .Net 4.6.1

PSReadLine/Cmdlets.cs

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,12 @@ public object ErrorColor
384384
set => _errorColor = VTColorUtils.AsEscapeSequence(value);
385385
}
386386

387+
public object SelectionColor
388+
{
389+
get => _selectionColor;
390+
set => _selectionColor = VTColorUtils.AsEscapeSequence(value);
391+
}
392+
387393
internal string _defaultTokenColor;
388394
internal string _commentColor;
389395
internal string _keywordColor;
@@ -397,10 +403,12 @@ public object ErrorColor
397403
internal string _memberColor;
398404
internal string _emphasisColor;
399405
internal string _errorColor;
406+
internal string _selectionColor;
400407

401408
internal void ResetColors()
402409
{
403-
DefaultTokenColor = Console.ForegroundColor;
410+
var fg = Console.ForegroundColor;
411+
DefaultTokenColor = fg;
404412
CommentColor = DefaultCommentColor;
405413
KeywordColor = DefaultKeywordColor;
406414
StringColor = DefaultStringColor;
@@ -413,6 +421,16 @@ internal void ResetColors()
413421
MemberColor = DefaultNumberColor;
414422
EmphasisColor = DefaultEmphasisColor;
415423
ErrorColor = DefaultErrorColor;
424+
425+
var bg = Console.BackgroundColor;
426+
if (fg == VTColorUtils.UnknownColor || bg == VTColorUtils.UnknownColor)
427+
{
428+
// TODO: light vs. dark
429+
fg = ConsoleColor.Black;
430+
bg = ConsoleColor.Gray;
431+
}
432+
433+
SelectionColor = VTColorUtils.AsEscapeSequence(bg, fg);
416434
}
417435

418436
private static Dictionary<string, Action<PSConsoleReadLineOptions, object>> ColorSetters = null;
@@ -438,6 +456,7 @@ internal void SetColor(string property, object value)
438456
{"Type", (o, v) => o.TypeColor = v},
439457
{"Number", (o, v) => o.NumberColor = v},
440458
{"Member", (o, v) => o.MemberColor = v},
459+
{"Selection", (o, v) => o.SelectionColor = v },
441460
};
442461

443462
Interlocked.CompareExchange(ref ColorSetters, setters, null);
@@ -649,16 +668,6 @@ protected override void EndProcessing()
649668
}
650669
}
651670

652-
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
653-
internal class ValidateColorAttribute : ValidateArgumentsAttribute
654-
{
655-
protected override void Validate(object arguments, EngineIntrinsics engineIntrinsics)
656-
{
657-
if (!VTColorUtils.IsValidColor(arguments))
658-
throw new ValidationMetadataException(PSReadLineResources.InvalidColorParameter);
659-
}
660-
}
661-
662671
public class ChangePSReadLineKeyHandlerCommandBase : PSCmdlet
663672
{
664673
[Parameter(Position = 0, Mandatory = true)]
@@ -837,9 +846,7 @@ protected override void EndProcessing()
837846

838847
public static class VTColorUtils
839848
{
840-
internal static bool IsValidColorImpl(ConsoleColor c) => true;
841-
842-
internal static bool IsValidColorImpl(string s) => true;
849+
public const ConsoleColor UnknownColor = (ConsoleColor) (-1);
843850

844851
public static bool IsValidColor(object o)
845852
{
@@ -922,6 +929,20 @@ public static string AsEscapeSequence(object o, bool isBackground)
922929
throw new ArgumentException("o");
923930
}
924931

932+
public static string AsEscapeSequence(ConsoleColor fg, ConsoleColor bg)
933+
{
934+
if (fg < 0 || fg >= (ConsoleColor) ForegroundColorMap.Length)
935+
throw new ArgumentOutOfRangeException(nameof(fg));
936+
if (bg < 0 || bg >= (ConsoleColor) ForegroundColorMap.Length)
937+
throw new ArgumentOutOfRangeException(nameof(bg));
938+
939+
string ExtractCode(string s)
940+
{
941+
return s.Substring(2).TrimEnd(new[] {'m'});
942+
}
943+
return "\x1b[" + ExtractCode(ForegroundColorMap[(int)fg]) + ";" + ExtractCode(BackgroundColorMap[(int)bg]) + "m";
944+
}
945+
925946
private static readonly string[] BackgroundColorMap = {
926947
"\x1b[40m", // Black
927948
"\x1b[44m", // DarkBlue

PSReadLine/Completion.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -592,9 +592,9 @@ public void UpdateMenuSelection(int selectedItem, bool select, bool showTooltips
592592

593593
console.SetCursorPosition(col, row);
594594

595-
if (select) console.Write("\x001b[7m");
595+
if (select) console.Write(Singleton.Options._selectionColor);
596596
console.Write(GetMenuItem(listItem, ColumnWidth));
597-
if (select) console.Write("\x001b[27m");
597+
if (select) console.Write("\x1b[0m");
598598

599599
ToolTipLines = 0;
600600
if (showTooltips)
@@ -605,7 +605,7 @@ public void UpdateMenuSelection(int selectedItem, bool select, bool showTooltips
605605
console.Write(toolTip);
606606
ToolTipLines = toolTipLines;
607607

608-
console.Write("\x001b[0m");
608+
console.Write("\x1b[0m");
609609
}
610610

611611
console.RestoreCursor();

PSReadLine/Render.cs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,13 @@ private int GenerateRender(string defaultColor)
145145
string activeColor = "";
146146
bool afterLastToken = false;
147147
int currentLogicalLine = 0;
148+
bool inSelectedRegion = false;
148149

149150
void UpdateColorsIfNecessary(string newColor)
150151
{
151152
if (!object.ReferenceEquals(newColor, activeColor))
152153
{
153-
_consoleBufferLines[currentLogicalLine].Append(newColor);
154+
if (!inSelectedRegion) _consoleBufferLines[currentLogicalLine].Append(newColor);
154155
activeColor = newColor;
155156
}
156157
}
@@ -177,7 +178,6 @@ void MaybeEmphasize(int i, string currColor)
177178
Color = defaultColor
178179
});
179180

180-
bool inSelectedRegion = false;
181181
int selectionStart = -1;
182182
int selectionEnd = -1;
183183
if (_visualSelectionCommandCount > 0)
@@ -194,12 +194,13 @@ void MaybeEmphasize(int i, string currColor)
194194
{
195195
if (i == selectionStart)
196196
{
197-
_consoleBufferLines[currentLogicalLine].Append("\x1b[7m");
197+
_consoleBufferLines[currentLogicalLine].Append(Options.SelectionColor);
198198
inSelectedRegion = true;
199199
}
200200
else if (i == selectionEnd)
201201
{
202-
_consoleBufferLines[currentLogicalLine].Append("\x1b[27m");
202+
_consoleBufferLines[currentLogicalLine].Append("\x1b[0m");
203+
_consoleBufferLines[currentLogicalLine].Append(activeColor);
203204
inSelectedRegion = false;
204205
}
205206

@@ -270,7 +271,7 @@ void MaybeEmphasize(int i, string currColor)
270271
if (inSelectedRegion)
271272
{
272273
// Turn off inverse before end of line, turn on after continuation prompt
273-
_consoleBufferLines[currentLogicalLine].Append("\x1b[27m");
274+
_consoleBufferLines[currentLogicalLine].Append("\x1b[0m");
274275
}
275276

276277
currentLogicalLine += 1;
@@ -288,7 +289,7 @@ void MaybeEmphasize(int i, string currColor)
288289
if (inSelectedRegion)
289290
{
290291
// Turn off inverse before end of line, turn on after continuation prompt
291-
_consoleBufferLines[currentLogicalLine].Append("\x1b[7m");
292+
_consoleBufferLines[currentLogicalLine].Append(Options.SelectionColor);
292293
}
293294
}
294295
else
@@ -309,7 +310,7 @@ void MaybeEmphasize(int i, string currColor)
309310

310311
if (inSelectedRegion)
311312
{
312-
_consoleBufferLines[currentLogicalLine].Append("\x1b[27m");
313+
_consoleBufferLines[currentLogicalLine].Append("\x1b[0m");
313314
}
314315

315316
if (_statusLinePrompt != null)

docs/Set-PSReadLineOption.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,8 @@ The valid keys include:
323323

324324
-- Error: The error color, e.g. in the prompt.
325325

326+
-- Selection: The color to highlight the menu selection or selected text.
327+
326328
-- Default: The default token color.
327329

328330
-- Comment: The comment token color.

0 commit comments

Comments
 (0)