Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add color options for Attributes, command arguments and loop labels. #1724

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
82 changes: 56 additions & 26 deletions PSReadLine/Cmdlets.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,18 +72,21 @@ public enum PredictionSource

public class PSConsoleReadLineOptions
{
public const ConsoleColor DefaultCommentColor = ConsoleColor.DarkGreen;
public const ConsoleColor DefaultKeywordColor = ConsoleColor.Green;
public const ConsoleColor DefaultStringColor = ConsoleColor.DarkCyan;
public const ConsoleColor DefaultOperatorColor = ConsoleColor.DarkGray;
public const ConsoleColor DefaultVariableColor = ConsoleColor.Green;
public const ConsoleColor DefaultCommandColor = ConsoleColor.Yellow;
public const ConsoleColor DefaultParameterColor = ConsoleColor.DarkGray;
public const ConsoleColor DefaultTypeColor = ConsoleColor.Gray;
public const ConsoleColor DefaultNumberColor = ConsoleColor.White;
public const ConsoleColor DefaultMemberColor = ConsoleColor.Gray;
public const ConsoleColor DefaultEmphasisColor = ConsoleColor.Cyan;
public const ConsoleColor DefaultErrorColor = ConsoleColor.Red;
public const ConsoleColor DefaultCommentColor = ConsoleColor.DarkGreen;
public const ConsoleColor DefaultKeywordColor = ConsoleColor.Green;
public const ConsoleColor DefaultStringColor = ConsoleColor.DarkCyan;
public const ConsoleColor DefaultOperatorColor = ConsoleColor.DarkGray;
public const ConsoleColor DefaultVariableColor = ConsoleColor.Green;
public const ConsoleColor DefaultCommandColor = ConsoleColor.Yellow;
public const ConsoleColor DefaultParameterColor = ConsoleColor.DarkGray;
public const ConsoleColor DefaultTypeColor = ConsoleColor.Gray;
public const ConsoleColor DefaultNumberColor = ConsoleColor.White;
public const ConsoleColor DefaultMemberColor = ConsoleColor.Gray;
public const ConsoleColor DefaultEmphasisColor = ConsoleColor.Cyan;
public const ConsoleColor DefaultErrorColor = ConsoleColor.Red;
public const ConsoleColor DefaultAttributeColor = ConsoleColor.Cyan;
public const ConsoleColor DefaultCommandArgumentColor = ConsoleColor.Gray;
public const ConsoleColor DefaultLoopLabelColor = ConsoleColor.DarkGray;

// Use dark black by default for the suggestion text.
// Find the most suitable color using https://stackoverflow.com/a/33206814
Expand Down Expand Up @@ -457,6 +460,24 @@ public object PredictionColor
set => _predictionColor = VTColorUtils.AsEscapeSequence(value);
}

public object AttributeColor
{
get => _attributeColor;
set => _attributeColor = VTColorUtils.AsEscapeSequence(value);
}

public object CommandArgumentColor
{
get => _commandArgumentColor;
set => _commandArgumentColor = VTColorUtils.AsEscapeSequence(value);
}

public object LoopLabelColor
{
get => _loopLabelColor;
set => _loopLabelColor = VTColorUtils.AsEscapeSequence(value);
}

internal string _defaultTokenColor;
internal string _commentColor;
internal string _keywordColor;
Expand All @@ -472,24 +493,30 @@ public object PredictionColor
internal string _errorColor;
internal string _selectionColor;
internal string _predictionColor;
internal string _attributeColor;
internal string _commandArgumentColor;
internal string _loopLabelColor;

internal void ResetColors()
{
var fg = Console.ForegroundColor;
DefaultTokenColor = fg;
CommentColor = DefaultCommentColor;
KeywordColor = DefaultKeywordColor;
StringColor = DefaultStringColor;
OperatorColor = DefaultOperatorColor;
VariableColor = DefaultVariableColor;
CommandColor = DefaultCommandColor;
ParameterColor = DefaultParameterColor;
TypeColor = DefaultTypeColor;
NumberColor = DefaultNumberColor;
MemberColor = DefaultNumberColor;
EmphasisColor = DefaultEmphasisColor;
ErrorColor = DefaultErrorColor;
PredictionColor = DefaultPredictionColor;
DefaultTokenColor = fg;
CommentColor = DefaultCommentColor;
KeywordColor = DefaultKeywordColor;
StringColor = DefaultStringColor;
OperatorColor = DefaultOperatorColor;
VariableColor = DefaultVariableColor;
CommandColor = DefaultCommandColor;
ParameterColor = DefaultParameterColor;
TypeColor = DefaultTypeColor;
NumberColor = DefaultNumberColor;
MemberColor = DefaultNumberColor;
EmphasisColor = DefaultEmphasisColor;
ErrorColor = DefaultErrorColor;
PredictionColor = DefaultPredictionColor;
AttributeColor = DefaultAttributeColor;
CommandArgumentColor = DefaultCommandArgumentColor;
LoopLabelColor = DefaultLoopLabelColor;

var bg = Console.BackgroundColor;
if (fg == VTColorUtils.UnknownColor || bg == VTColorUtils.UnknownColor)
Expand Down Expand Up @@ -527,6 +554,9 @@ internal void SetColor(string property, object value)
{"Member", (o, v) => o.MemberColor = v},
{"Selection", (o, v) => o.SelectionColor = v},
{"Prediction", (o, v) => o.PredictionColor = v},
{"Attribute", (o, v) => o.AttributeColor = v},
{"CommandArgument", (o, v) => o.CommandArgumentColor = v},
{"LoopLabel", (o, v) => o.LoopLabelColor = v},
};

Interlocked.CompareExchange(ref ColorSetters, setters, null);
Expand Down
12 changes: 12 additions & 0 deletions PSReadLine/PSReadLine.format.ps1xml
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,18 @@ $d = [Microsoft.PowerShell.KeyHandler]::GetGroupingDescription($_.Group)
<ListItem>
<PropertyName>PredictionSource</PropertyName>
</ListItem>
<ListItem>
<Label>AttributeColor</Label>
<ScriptBlock>[Microsoft.PowerShell.VTColorUtils]::FormatColor($_.AttributeColor)</ScriptBlock>
</ListItem>
<ListItem>
<Label>CommandColor</Label>
<ScriptBlock>[Microsoft.PowerShell.VTColorUtils]::FormatColor($_.CommandColor)</ScriptBlock>
</ListItem>
<ListItem>
<Label>CommandArgumentColor</Label>
<ScriptBlock>[Microsoft.PowerShell.VTColorUtils]::FormatColor($_.CommandArgumentColor)</ScriptBlock>
</ListItem>
<ListItem>
<Label>CommentColor</Label>
<ScriptBlock>[Microsoft.PowerShell.VTColorUtils]::FormatColor($_.CommentColor)</ScriptBlock>
Expand All @@ -189,6 +197,10 @@ $d = [Microsoft.PowerShell.KeyHandler]::GetGroupingDescription($_.Group)
<Label>KeywordColor</Label>
<ScriptBlock>[Microsoft.PowerShell.VTColorUtils]::FormatColor($_.KeywordColor)</ScriptBlock>
</ListItem>
<ListItem>
<Label>LoopLabelColor</Label>
<ScriptBlock>[Microsoft.PowerShell.VTColorUtils]::FormatColor($_.LoopLabelColor)</ScriptBlock>
</ListItem>
<ListItem>
<Label>MemberColor</Label>
<ScriptBlock>[Microsoft.PowerShell.VTColorUtils]::FormatColor($_.MemberColor)</ScriptBlock>
Expand Down
13 changes: 13 additions & 0 deletions PSReadLine/Render.cs
Original file line number Diff line number Diff line change
Expand Up @@ -952,6 +952,9 @@ private string GetTokenColor(Token token)

case TokenKind.Number:
return _options._numberColor;

case TokenKind.Label:
return _options._loopLabelColor;
}

if ((token.TokenFlags & TokenFlags.Keyword) != 0)
Expand All @@ -964,6 +967,11 @@ private string GetTokenColor(Token token)
return _options._operatorColor;
}

if ((token.TokenFlags & TokenFlags.AttributeName) != 0)
{
return _options._attributeColor;
}

if ((token.TokenFlags & TokenFlags.TypeName) != 0)
{
return _options._typeColor;
Expand All @@ -974,6 +982,11 @@ private string GetTokenColor(Token token)
return _options._memberColor;
}

if ((token.Kind == TokenKind.Identifier | token.Kind == TokenKind.Generic) && token.TokenFlags == TokenFlags.None)
{
return _options._commandArgumentColor;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this is accurate to reflect command arguments. Could the condition be true for something that is not a command argument?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so, I've pasted a lot of code into the console to test the colors and I haven't found any unexpected results regarding command arguments missing color or affecting something that wasn't a command argument.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest using logical or instead of bitwise or.

That said, with these changes, which tokens get the default now? I can't think of any, in which case, it seems unnecessary to introduce a new option.


return _options._defaultTokenColor;
}

Expand Down
45 changes: 23 additions & 22 deletions test/HistoryTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -781,14 +781,14 @@ public void InteractiveHistorySearch()
TokenClassification.Command, "echo",
TokenClassification.None, " ",
emphasisColors, 'a',
TokenClassification.None, "aa",
TokenClassification.CommandArgument, "aa",
NextLine,
statusColors, "bck-i-search: a_")),
'b', CheckThat(() => AssertScreenIs(2,
TokenClassification.Command, "echo",
TokenClassification.None, " ",
emphasisColors, "ab",
TokenClassification.None, 'b',
TokenClassification.CommandArgument, 'b',
NextLine,
statusColors, "bck-i-search: ab_")),
'c', CheckThat(() => AssertScreenIs(2,
Expand All @@ -806,21 +806,21 @@ public void InteractiveHistorySearch()
TokenClassification.Command, "echo",
TokenClassification.None, " ",
emphasisColors, 'a',
TokenClassification.None, "aa",
TokenClassification.CommandArgument, "aa",
NextLine,
statusColors, "bck-i-search: a_")),
_.Ctrl_r, CheckThat(() => AssertScreenIs(2,
TokenClassification.Command, "echo",
TokenClassification.None, " ",
emphasisColors, 'a',
TokenClassification.None, "bb",
TokenClassification.CommandArgument, "bb",
NextLine,
statusColors, "bck-i-search: a_")),
_.Ctrl_r, CheckThat(() => AssertScreenIs(2,
TokenClassification.Command, "echo",
TokenClassification.None, " ",
emphasisColors, 'a',
TokenClassification.None, "bc",
TokenClassification.CommandArgument, "bc",
NextLine,
statusColors, "bck-i-search: a_"))));

Expand All @@ -833,15 +833,15 @@ public void InteractiveHistorySearch()
TokenClassification.Command, "echo",
TokenClassification.None, " ",
emphasisColors, 'a',
TokenClassification.None, "bc",
TokenClassification.CommandArgument, "bc",
NextLine,
statusColors, "bck-i-search: a_")),
'b',
CheckThat(() => AssertScreenIs(2,
TokenClassification.Command, "echo",
TokenClassification.None, " ",
emphasisColors, "ab",
TokenClassification.None, 'c',
TokenClassification.CommandArgument, 'c',
NextLine,
statusColors, "bck-i-search: ab_"))));

Expand All @@ -853,14 +853,14 @@ public void InteractiveHistorySearch()
TokenClassification.Command, "echo",
TokenClassification.None, " ",
emphasisColors, 'a',
TokenClassification.None, "bc",
TokenClassification.CommandArgument, "bc",
NextLine,
statusColors, "bck-i-search: a_")),
_.Ctrl_g,
CheckThat(() => AssertScreenIs(2,
TokenClassification.Command, "echo",
TokenClassification.None, " ",
TokenClassification.None, "zed",
TokenClassification.CommandArgument, "zed",
NextLine))));

// Test that a random function terminates the search and has an
Expand All @@ -872,7 +872,7 @@ public void InteractiveHistorySearch()
TokenClassification.Command, "echo",
TokenClassification.None, " ",
emphasisColors, 'a',
TokenClassification.None, "bc",
TokenClassification.CommandArgument, "bc",
NextLine,
statusColors, "bck-i-search: a_")),
_.Alt_d, "zed"));
Expand All @@ -886,7 +886,7 @@ public void InteractiveHistorySearch()
TokenClassification.Command, "echo",
TokenClassification.None, " ",
emphasisColors, 'a',
TokenClassification.None, "bc",
TokenClassification.CommandArgument, "bc",
NextLine,
statusColors, "bck-i-search: a_")),
_.Escape, "y"));
Expand All @@ -900,15 +900,15 @@ public void InteractiveHistorySearch()
TokenClassification.Command, "echo",
TokenClassification.None, " ",
emphasisColors, "ab",
TokenClassification.None, 'b',
TokenClassification.CommandArgument, 'b',
NextLine,
statusColors, "bck-i-search: ab_")),
_.Backspace,
CheckThat(() => AssertScreenIs(2,
TokenClassification.Command, "echo",
TokenClassification.None, " ",
emphasisColors, 'a',
TokenClassification.None, "aa",
TokenClassification.CommandArgument, "aa",
NextLine,
statusColors, "bck-i-search: a_"))));

Expand All @@ -919,30 +919,30 @@ public void InteractiveHistorySearch()
TokenClassification.Command, "echo",
TokenClassification.None, " ",
emphasisColors, 'a',
TokenClassification.None, "bc",
TokenClassification.CommandArgument, "bc",
NextLine,
statusColors, "bck-i-search: a_")),
_.Ctrl_r,
CheckThat(() => AssertScreenIs(2,
TokenClassification.Command, "echo",
TokenClassification.None, " ",
emphasisColors, 'a',
TokenClassification.None, "bzz",
TokenClassification.CommandArgument, "bzz",
NextLine,
statusColors, "bck-i-search: a_")),
_.Ctrl_r,
CheckThat(() => AssertScreenIs(2,
TokenClassification.Command, "echo",
TokenClassification.None, " ",
TokenClassification.None, "abzz",
TokenClassification.CommandArgument, "abzz",
NextLine,
statusColors, "failed-bck-i-search: a_")),
_.Ctrl_s,
CheckThat(() => AssertScreenIs(2,
TokenClassification.Command, "echo",
TokenClassification.None, " ",
emphasisColors, 'a',
TokenClassification.None, "bzz",
TokenClassification.CommandArgument, "bzz",
NextLine,
statusColors, "fwd-i-search: a_")),
_.Ctrl_g));
Expand All @@ -952,7 +952,8 @@ public void InteractiveHistorySearch()
Test("echo aa1", Keys(_.Ctrl_r, "zz", _.Backspace, _.Backspace, "a1",
CheckThat(() => AssertScreenIs(2,
TokenClassification.Command, "echo",
TokenClassification.None, " a",
TokenClassification.None, " ",
TokenClassification.CommandArgument, "a",
emphasisColors, "a1",
NextLine,
statusColors, "bck-i-search: a1_"))
Expand All @@ -967,31 +968,31 @@ public void InteractiveHistorySearch()
TokenClassification.Command, "echo",
TokenClassification.None, " ",
emphasisColors, "aa",
TokenClassification.None, "2",
TokenClassification.CommandArgument, "2",
NextLine,
statusColors, "bck-i-search: aa_")),
_.Ctrl_r,
CheckThat(() => AssertScreenIs(2,
TokenClassification.Command, "echo",
TokenClassification.None, " ",
emphasisColors, "aa",
TokenClassification.None, "1",
TokenClassification.CommandArgument, "1",
NextLine,
statusColors, "bck-i-search: aa_")),
_.Backspace,
CheckThat(() => AssertScreenIs(2,
TokenClassification.Command, "echo",
TokenClassification.None, " ",
emphasisColors, "a",
TokenClassification.None, "a2",
TokenClassification.CommandArgument, "a2",
NextLine,
statusColors, "bck-i-search: a_")),
'a', _.Ctrl_r,
CheckThat(() => AssertScreenIs(2,
TokenClassification.Command, "echo",
TokenClassification.None, " ",
emphasisColors, "aa",
TokenClassification.None, "1",
TokenClassification.CommandArgument, "1",
NextLine,
statusColors, "bck-i-search: aa_")),
_.Backspace));
Expand Down