Skip to content

Commit

Permalink
Use \e instead of \u001B or \x1B (#99659)
Browse files Browse the repository at this point in the history
  • Loading branch information
stephentoub authored Apr 5, 2024
1 parent 997f09c commit 7def0b7
Show file tree
Hide file tree
Showing 11 changed files with 111 additions and 111 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public void Parse(string message)
ConsoleColor? foreground = null;
ConsoleColor? background = null;
var span = message.AsSpan();
const char EscapeChar = '\x1B';
const char EscapeChar = '\e';
ConsoleColor? color = null;
bool isBright = false;
for (int i = 0; i < span.Length; i++)
Expand All @@ -59,7 +59,7 @@ public void Parse(string message)
{
if (span[i + 3] == 'm')
{
// Example: \x1B[1m
// Example: \e[1m
if (IsDigit(span[i + 2]))
{
escapeCode = (int)(span[i + 2] - '0');
Expand All @@ -77,7 +77,7 @@ public void Parse(string message)
}
else if (span.Length >= i + 5 && span[i + 4] == 'm')
{
// Example: \x1B[40m
// Example: \e[40m
if (IsDigit(span[i + 2]) && IsDigit(span[i + 3]))
{
escapeCode = (int)(span[i + 2] - '0') * 10 + (int)(span[i + 3] - '0');
Expand Down Expand Up @@ -127,28 +127,28 @@ public void Parse(string message)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool IsDigit(char c) => (uint)(c - '0') <= ('9' - '0');

internal const string DefaultForegroundColor = "\x1B[39m\x1B[22m"; // reset to default foreground color
internal const string DefaultBackgroundColor = "\x1B[49m"; // reset to the background color
internal const string DefaultForegroundColor = "\e[39m\e[22m"; // reset to default foreground color
internal const string DefaultBackgroundColor = "\e[49m"; // reset to the background color

internal static string GetForegroundColorEscapeCode(ConsoleColor color)
{
return color switch
{
ConsoleColor.Black => "\x1B[30m",
ConsoleColor.DarkRed => "\x1B[31m",
ConsoleColor.DarkGreen => "\x1B[32m",
ConsoleColor.DarkYellow => "\x1B[33m",
ConsoleColor.DarkBlue => "\x1B[34m",
ConsoleColor.DarkMagenta => "\x1B[35m",
ConsoleColor.DarkCyan => "\x1B[36m",
ConsoleColor.Gray => "\x1B[37m",
ConsoleColor.Red => "\x1B[1m\x1B[31m",
ConsoleColor.Green => "\x1B[1m\x1B[32m",
ConsoleColor.Yellow => "\x1B[1m\x1B[33m",
ConsoleColor.Blue => "\x1B[1m\x1B[34m",
ConsoleColor.Magenta => "\x1B[1m\x1B[35m",
ConsoleColor.Cyan => "\x1B[1m\x1B[36m",
ConsoleColor.White => "\x1B[1m\x1B[37m",
ConsoleColor.Black => "\e[30m",
ConsoleColor.DarkRed => "\e[31m",
ConsoleColor.DarkGreen => "\e[32m",
ConsoleColor.DarkYellow => "\e[33m",
ConsoleColor.DarkBlue => "\e[34m",
ConsoleColor.DarkMagenta => "\e[35m",
ConsoleColor.DarkCyan => "\e[36m",
ConsoleColor.Gray => "\e[37m",
ConsoleColor.Red => "\e[1m\e[31m",
ConsoleColor.Green => "\e[1m\e[32m",
ConsoleColor.Yellow => "\e[1m\e[33m",
ConsoleColor.Blue => "\e[1m\e[34m",
ConsoleColor.Magenta => "\e[1m\e[35m",
ConsoleColor.Cyan => "\e[1m\e[36m",
ConsoleColor.White => "\e[1m\e[37m",
_ => DefaultForegroundColor // default foreground color
};
}
Expand All @@ -157,14 +157,14 @@ internal static string GetBackgroundColorEscapeCode(ConsoleColor color)
{
return color switch
{
ConsoleColor.Black => "\x1B[40m",
ConsoleColor.DarkRed => "\x1B[41m",
ConsoleColor.DarkGreen => "\x1B[42m",
ConsoleColor.DarkYellow => "\x1B[43m",
ConsoleColor.DarkBlue => "\x1B[44m",
ConsoleColor.DarkMagenta => "\x1B[45m",
ConsoleColor.DarkCyan => "\x1B[46m",
ConsoleColor.Gray => "\x1B[47m",
ConsoleColor.Black => "\e[40m",
ConsoleColor.DarkRed => "\e[41m",
ConsoleColor.DarkGreen => "\e[42m",
ConsoleColor.DarkYellow => "\e[43m",
ConsoleColor.DarkBlue => "\e[44m",
ConsoleColor.DarkMagenta => "\e[45m",
ConsoleColor.DarkCyan => "\e[46m",
ConsoleColor.Gray => "\e[47m",
_ => DefaultBackgroundColor // Use default background color
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ namespace Microsoft.Extensions.Logging.Console.Test
{
public class AnsiParserTests
{
private const char EscapeChar = '\x1B';
private const char EscapeChar = '\e';

[Theory]
[InlineData(1, "No Color", "No Color")]
[InlineData(2, "\x1B[41mColored\x1B[49mNo Color", "No Color")]
[InlineData(2, "\x1B[41m\x1B[1m\x1B[31mmColored\x1B[39m\x1B[49mNo Color", "No Color")]
[InlineData(2, "\e[41mColored\e[49mNo Color", "No Color")]
[InlineData(2, "\e[41m\e[1m\e[31mmColored\e[39m\e[49mNo Color", "No Color")]
public void Parse_CheckTimesWrittenToConsole(int numSegments, string message, string lastSegment)
{
// Arrange
Expand Down Expand Up @@ -151,33 +151,33 @@ public void Parse_RepeatedColorChange_PicksLastSet()

[Theory]
// supported
[InlineData("\x1B[77mInfo", "Info")]
[InlineData("\x1B[77m\x1B[1m\x1B[2m\x1B[0mInfo\x1B[1m", "Info")]
[InlineData("\x1B[7mInfo", "Info")]
[InlineData("\x1B[40m\x1B[1m\x1B[33mwarn\x1B[39m\x1B[22m\x1B[49m:", "warn", ":")]
[InlineData("\e[77mInfo", "Info")]
[InlineData("\e[77m\e[1m\e[2m\e[0mInfo\e[1m", "Info")]
[InlineData("\e[7mInfo", "Info")]
[InlineData("\e[40m\e[1m\e[33mwarn\e[39m\e[22m\e[49m:", "warn", ":")]
// unsupported: skips
[InlineData("Info\x1B[77m:", "Info", ":")]
[InlineData("Info\x1B[7m:", "Info", ":")]
[InlineData("Info\e[77m:", "Info", ":")]
[InlineData("Info\e[7m:", "Info", ":")]
// treats as content
[InlineData("\x1B", "\x1B")]
[InlineData("\x1B ", "\x1B ")]
[InlineData("\x1Bm", "\x1Bm")]
[InlineData("\x1B m", "\x1B m")]
[InlineData("\x1Bxym", "\x1Bxym")]
[InlineData("\x1B[", "\x1B[")]
[InlineData("\x1B[m", "\x1B[m")]
[InlineData("\x1B[ ", "\x1B[ ")]
[InlineData("\x1B[ m", "\x1B[ m")]
[InlineData("\x1B[xym", "\x1B[xym")]
[InlineData("\x1B[7777m", "\x1B[7777m")]
[InlineData("\x1B\x1B\x1B", "\x1B\x1B\x1B")]
[InlineData("Message\x1B\x1B\x1B", "Message\x1B\x1B\x1B")]
[InlineData("\x1B\x1BMessage\x1B", "\x1B\x1BMessage\x1B")]
[InlineData("\x1B\x1B\x1BMessage", "\x1B\x1B\x1BMessage")]
[InlineData("Message\x1B ", "Message\x1B ")]
[InlineData("\x1BmMessage", "\x1BmMessage")]
[InlineData("\x1B[77m\x1B m\x1B[40m", "\x1B m")]
[InlineData("\x1B mMessage\x1Bxym", "\x1B mMessage\x1Bxym")]
[InlineData("\e", "\e")]
[InlineData("\e ", "\e ")]
[InlineData("\em", "\em")]
[InlineData("\e m", "\e m")]
[InlineData("\exym", "\exym")]
[InlineData("\e[", "\e[")]
[InlineData("\e[m", "\e[m")]
[InlineData("\e[ ", "\e[ ")]
[InlineData("\e[ m", "\e[ m")]
[InlineData("\e[xym", "\e[xym")]
[InlineData("\e[7777m", "\e[7777m")]
[InlineData("\e\e\e", "\e\e\e")]
[InlineData("Message\e\e\e", "Message\e\e\e")]
[InlineData("\e\eMessage\e", "\e\eMessage\e")]
[InlineData("\e\e\eMessage", "\e\e\eMessage")]
[InlineData("Message\e ", "Message\e ")]
[InlineData("\emMessage", "\emMessage")]
[InlineData("\e[77m\e m\e[40m", "\e m")]
[InlineData("\e mMessage\exym", "\e mMessage\exym")]
public void Parse_ValidSupportedOrUnsupportedCodesInMessage_MessageParsedSuccessfully(string messageWithUnsupportedCode, params string[] output)
{
// Arrange
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public void WriteColoredMessage_WithForegroundEscapeCode_AndNoBackgroundColorSpe
var message = "Request received";
var expectedMessage = AnsiParser.GetForegroundColorEscapeCode(ConsoleColor.DarkGreen)
+ message
+ "\x1B[39m\x1B[22m"; //resets foreground color
+ "\e[39m\e[22m"; //resets foreground color
var textWriter = new StringWriter();

// Act
Expand All @@ -33,7 +33,7 @@ public void WriteColoredMessage_WithBackgroundEscapeCode_AndNoForegroundColorSpe
var message = "Request received";
var expectedMessage = AnsiParser.GetBackgroundColorEscapeCode(ConsoleColor.Red)
+ message
+ "\x1B[49m"; //resets background color
+ "\e[49m"; //resets background color
var textWriter = new StringWriter();

// Act
Expand All @@ -51,8 +51,8 @@ public void WriteColoredMessage_InOrder_WhenBothForegroundOrBackgroundColorsSpec
var expectedMessage = AnsiParser.GetBackgroundColorEscapeCode(ConsoleColor.Red)
+ AnsiParser.GetForegroundColorEscapeCode(ConsoleColor.DarkGreen)
+ "Request received"
+ "\x1B[39m\x1B[22m" //resets foreground color
+ "\x1B[49m"; //resets background color
+ "\e[39m\e[22m" //resets foreground color
+ "\e[49m"; //resets background color
var textWriter = new StringWriter();

// Act
Expand Down
2 changes: 1 addition & 1 deletion src/libraries/System.Console/src/System/IO/KeyParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace System.IO;

internal static class KeyParser
{
private const char Escape = '\u001B';
private const char Escape = '\e';
private const char Delete = '\u007F';
private const char VtSequenceEndTag = '~';
private const char ModifierSeparator = ';';
Expand Down
10 changes: 5 additions & 5 deletions src/libraries/System.Console/src/System/TerminalFormatStrings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ internal sealed class TerminalFormatStrings
/// doesn't contain it (as appears to be the case with e.g. screen and tmux on Ubuntu), at the risk
/// of outputting the sequence on some terminal that's not compatible.
/// </remarks>
public const string CursorPositionReport = "\x1B[6n";
public const string CursorPositionReport = "\e[6n";
/// <summary>
/// The dictionary of keystring to ConsoleKeyInfo.
/// Only some members of the ConsoleKeyInfo are used; in particular, the actual char is ignored.
Expand Down Expand Up @@ -210,13 +210,13 @@ private static string GetTitle(TermInfo.Database db)
case "linux":
case "rxvt":
case "xterm":
return "\x1B]0;%p1%s\x07";
return "\e]0;%p1%s\x07";
case "cygwin":
return "\x1B];%p1%s\x07";
return "\e];%p1%s\x07";
case "konsole":
return "\x1B]30;%p1%s\x07";
return "\e]30;%p1%s\x07";
case "screen":
return "\x1Bk%p1%s\x1B\\";
return "\ek%p1%s\e\\";
default:
return string.Empty;
}
Expand Down
44 changes: 22 additions & 22 deletions src/libraries/System.Console/tests/KeyParserTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public class KeyParserTests
yield return ('.', ConsoleKey.OemPeriod);
yield return (',', ConsoleKey.OemComma);

yield return ('\u001B', ConsoleKey.Escape);
yield return ('\e', ConsoleKey.Escape);

for (char i = '0'; i <= '9'; i++)
{
Expand Down Expand Up @@ -212,7 +212,7 @@ public void KeysAreProperlyMapped(TerminalData terminalData, byte[] recordedByte
yield return (GetString(33), ConsoleKey.F19);
yield return (GetString(34), ConsoleKey.F20);

static string GetString(int i) => $"\u001B[{i}~";
static string GetString(int i) => $"\e[{i}~";
}
}

Expand All @@ -223,7 +223,7 @@ public static IEnumerable<object[]> VTSequencesArguments
[MemberData(nameof(VTSequencesArguments))]
public void VTSequencesAreProperlyMapped(TerminalData terminalData, string input, ConsoleKey expectedKey)
{
if (terminalData is RxvtUnicode && input == "\u001B[4~" && expectedKey == ConsoleKey.End)
if (terminalData is RxvtUnicode && input == "\e[4~" && expectedKey == ConsoleKey.End)
{
expectedKey = ConsoleKey.Select; // rxvt binds this key to Select in Terminfo and uses "^[[8~" for End key
}
Expand All @@ -239,10 +239,10 @@ public void VTSequencesAreProperlyMapped(TerminalData terminalData, string input
{
get
{
yield return ("\u001BOa", ConsoleKey.UpArrow);
yield return ("\u001BOb", ConsoleKey.DownArrow);
yield return ("\u001BOc", ConsoleKey.RightArrow);
yield return ("\u001BOd", ConsoleKey.LeftArrow);
yield return ("\eOa", ConsoleKey.UpArrow);
yield return ("\eOb", ConsoleKey.DownArrow);
yield return ("\eOc", ConsoleKey.RightArrow);
yield return ("\eOd", ConsoleKey.LeftArrow);
}
}

Expand Down Expand Up @@ -272,9 +272,9 @@ public void ExtendedStringCodePath()
// Ctrl+Backspace
yield return ("\b", new[] { new ConsoleKeyInfo('\b', ConsoleKey.Backspace, false, false, true) });
// Alt+Backspace
yield return ("\u001B\u007F", new[] { new ConsoleKeyInfo((char)0x7F, ConsoleKey.Backspace, false, true, false) });
yield return ("\e\u007F", new[] { new ConsoleKeyInfo((char)0x7F, ConsoleKey.Backspace, false, true, false) });
// Ctrl+Alt+Backspace
yield return ("\u001B\b", new[] { new ConsoleKeyInfo('\b', ConsoleKey.Backspace, false, true, true) });
yield return ("\e\b", new[] { new ConsoleKeyInfo('\b', ConsoleKey.Backspace, false, true, true) });
// Enter
yield return ("\r", new[] { new ConsoleKeyInfo('\r', ConsoleKey.Enter, false, false, false) });
// Ctrl+Enter
Expand All @@ -283,18 +283,18 @@ public void ExtendedStringCodePath()
// Escape key pressed multiple times
for (int i = 1; i <= 5; i++)
{
yield return (new string('\u001B', i), Enumerable.Repeat(new ConsoleKeyInfo('\u001B', ConsoleKey.Escape, false, false, false), i).ToArray());
yield return (new string('\e', i), Enumerable.Repeat(new ConsoleKeyInfo('\e', ConsoleKey.Escape, false, false, false), i).ToArray());
}

// Home key (^[[H) followed by H key
yield return ("\u001B[HH", new[]
yield return ("\e[HH", new[]
{
new ConsoleKeyInfo(default, ConsoleKey.Home, false, false, false),
new ConsoleKeyInfo('H', ConsoleKey.H, true, false, false)
});

// escape sequence (F12 '^[[24~') followed by an extra tylde:
yield return ($"\u001B[24~~", new[]
yield return ($"\e[24~~", new[]
{
new ConsoleKeyInfo(default, ConsoleKey.F12, false, false, false),
new ConsoleKeyInfo('~', default, false, false, false),
Expand All @@ -304,9 +304,9 @@ public void ExtendedStringCodePath()
// Invalid modifiers (valid values are <2, 8>)
foreach (int invalidModifier in new[] { 0, 1, 9 })
{
yield return ($"\u001B[1;{invalidModifier}H", new[]
yield return ($"\e[1;{invalidModifier}H", new[]
{
new ConsoleKeyInfo('\u001B', ConsoleKey.Escape, false, false, false),
new ConsoleKeyInfo('\e', ConsoleKey.Escape, false, false, false),
new ConsoleKeyInfo('[', default, false, false, false),
new ConsoleKeyInfo('1', ConsoleKey.D1, false, false, false),
new ConsoleKeyInfo(';', default, false, false, false),
Expand All @@ -317,29 +317,29 @@ public void ExtendedStringCodePath()
// Invalid ID (valid values are <1, 34> except of 9, 16, 22, 27, 30 and 35)
foreach (int invalidId in new[] { 16, 22, 27, 30, 35, 36, 77, 99 })
{
yield return ($"\u001B[{invalidId}~", new[]
yield return ($"\e[{invalidId}~", new[]
{
new ConsoleKeyInfo('\u001B', ConsoleKey.Escape, false, false, false),
new ConsoleKeyInfo('\e', ConsoleKey.Escape, false, false, false),
new ConsoleKeyInfo('[', default, false, false, false),
new ConsoleKeyInfo((char)('0' + invalidId / 10), ConsoleKey.D0 + invalidId / 10, false, false, false),
new ConsoleKeyInfo((char)('0' + invalidId % 10), ConsoleKey.D0 + invalidId % 10, false, false, false),
new ConsoleKeyInfo('~', default, false, false, false),
});
}
// too long ID (more than 2 digits)
yield return ($"\u001B[111~", new[]
yield return ($"\e[111~", new[]
{
new ConsoleKeyInfo('\u001B', ConsoleKey.Escape, false, false, false),
new ConsoleKeyInfo('\e', ConsoleKey.Escape, false, false, false),
new ConsoleKeyInfo('[', default, false, false, false),
new ConsoleKeyInfo('1', ConsoleKey.D1, false, false, false),
new ConsoleKeyInfo('1', ConsoleKey.D1, false, false, false),
new ConsoleKeyInfo('1', ConsoleKey.D1, false, false, false),
new ConsoleKeyInfo('~', default, false, false, false),
});
// missing closing tag (tylde):
yield return ($"\u001B[24", new[]
yield return ($"\e[24", new[]
{
new ConsoleKeyInfo('\u001B', ConsoleKey.Escape, false, false, false),
new ConsoleKeyInfo('\e', ConsoleKey.Escape, false, false, false),
new ConsoleKeyInfo('[', default, false, false, false),
new ConsoleKeyInfo('2', ConsoleKey.D2, false, false, false),
new ConsoleKeyInfo('4', ConsoleKey.D4, false, false, false),
Expand Down Expand Up @@ -386,7 +386,7 @@ public void NewLineEscapeSequenceProducesCharacter()
{
XTermData xTerm = new();

ConsoleKeyInfo consoleKeyInfo = Parse("\u001BOM".ToCharArray(), xTerm.TerminalDb, xTerm.Verase, 3);
ConsoleKeyInfo consoleKeyInfo = Parse("\eOM".ToCharArray(), xTerm.TerminalDb, xTerm.Verase, 3);

Assert.Equal(ConsoleKey.Enter, consoleKeyInfo.Key);
Assert.Equal('\r', consoleKeyInfo.KeyChar);
Expand All @@ -398,7 +398,7 @@ public void BackTabEscapeSequence()
{
XTermData xTerm = new();

ConsoleKeyInfo consoleKeyInfo = Parse("\u001B[Z".ToCharArray(), xTerm.TerminalDb, xTerm.Verase, 3);
ConsoleKeyInfo consoleKeyInfo = Parse("\e[Z".ToCharArray(), xTerm.TerminalDb, xTerm.Verase, 3);

Assert.Equal(ConsoleKey.Tab, consoleKeyInfo.Key);
Assert.Equal(default, consoleKeyInfo.KeyChar);
Expand Down
Loading

0 comments on commit 7def0b7

Please sign in to comment.