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

[Proposal]: String/Character escape sequence \e as a short-hand for \u001b (<ESCAPE>) #7400

Open
3 of 4 tasks
Unknown6656 opened this issue Jul 27, 2023 · 11 comments
Open
3 of 4 tasks
Assignees
Labels
Implemented Needs ECMA Spec This feature has been implemented in C#, but still needs to be merged into the ECMA specification Proposal champion
Milestone

Comments

@Unknown6656
Copy link
Contributor

Unknown6656 commented Jul 27, 2023

Initial discussion: #7394
Initial approval: @CyrusNajmabadi

String/Character escape sequence \e

Summary

An addition of the string/character escape sequence \e as a shortcut/short-hand replacement for the character code point 0x1b, commonly known as the ESCAPE (or ESC) character. This character is currently accessible using one of the following escape sequences:

  • \u001b
  • \U0000001b
  • \x1b (not recommended, see the picture attached at the bottom.)

With the implementation of this proposal, the following assertions should be true:

char escape_char = '\e';

Assert.IsTrue(escape_char == (char)0x1b, "...");
Assert.IsTrue(escape_char == '\u001b', "...");
Assert.IsTrue(escape_char == '\U0000001b', "...");
Assert.IsTrue(escape_char == '\x1b', "...");

Motivation

Although the System.Console class exposes quite a few possibilities to interact with the Terminal, it by far does not support every functionalities or features. Predominant among these are 24bit color support, bold, italic, underlined, or blinking text, as well as a few other features.

However, these can be emulated by printing (a series of) so-called VT100/ANSI escape codes to the System.Console.Out stream (A reference of ANSI escape sequences can be found in the section Attachments and References of this proposal). Each VT100 escape sequence starts with the character 0x1b (ASCII ESC), followed by a series of characters, such as:

Console.WriteLine("This is a regular text");
Console.WriteLine("\u001b[1mThis is a bold text\u001b[0m");
Console.WriteLine("\u001b[2mThis is a dimmed text\u001b[0m");
Console.WriteLine("\u001b[3mThis is an italic text\u001b[0m");
Console.WriteLine("\u001b[4mThis is an underlined text\u001b[0m");
Console.WriteLine("\u001b[5mThis is a blinking text\u001b[0m");
Console.WriteLine("\u001b[6mThis is a fast blinking text\u001b[0m");
Console.WriteLine("\u001b[7mThis is an inverted text\u001b[0m");
Console.WriteLine("\u001b[8mThis is a hidden text\u001b[0m");
Console.WriteLine("\u001b[9mThis is a crossed-out text\u001b[0m");
Console.WriteLine("\u001b[21mThis is a double-underlined text\u001b[0m");
Console.WriteLine("\u001b[38;2;255;0;0mThis is a red text\u001b[0m");
Console.WriteLine("\u001b[48;2;0;255;0mThis is a green background\u001b[0m");
Console.WriteLine("\u001b[38;2;0;0;255;48;2;255;255;0mThis is a blue text with a yellow background\u001b[0m");

which result in the following output in wt.exe and cmd.exe:
image

Due to the recurring usage \u001b, a shorter abbreviation such as \e would be welcome. This is comparable to how \n can be used as an abbreviation for \u000a.

A further motivation for this proposal is the recurrent usage of the sequence \u001b inside of ESC/POS commands when interacting with (thermal) printers, as e.g. referenced in the following documents and articles (thanks @jnm2 !):

Detailed design

I propose the language syntax specification to be changed as follows in section 6.4.5.5:

fragment Simple_Escape_Sequence
-    : '\\\'' | '\\"' | '\\\\' | '\\0' | '\\a' | '\\b' | '\\f' | '\\n' | '\\r' | '\\t' | '\\v'
+    : '\\\'' | '\\"' | '\\\\' | '\\0' | '\\a' | '\\b' | '\\f' | '\\n' | '\\r' | '\\t' | '\\v' | '\\e'
    ;

As well as the addition of the last line to the following table in the specifications:

A simple escape sequence represents a Unicode character, as described in the table below.

Escape sequence Character name Unicode code point
\' Single quote U+0027
... ... ...
\e Escape character U+001B

The type of a Character_Literal is char.

Drawbacks

Every new language feature request brings added complexity to the compiler. However, I shall argue that the implementation of this specific feature mainly involves variation of existing code concerning the parsing of existing escape sequences such as \v, \f, or \a. Furthermore, a certain complexity involves the adaptation of Roslyn's unit tests to accommodate this feature.

Alternatives

The usage of the escape character 0x1b can be implemented using traditional methods, amongst which are:

  • \u001b
  • \U0000001b
  • \x1b (not recommended, see the picture attached at the bottom.)$
  • (char)0x1b
  • The assignment of (char)0x1b to a constant variable/field and its usage inside of interpolated strings instead of the direct utilization of the proposed sequence \e.

Unresolved questions

  • Possible impact on existing code analyzers and existing test cases inside the compiler or .NET runtime.
  • Should C# come with a new analyzer, which suggests the refactoring of existing occurrences of \x1b, \u001b, etc. towards \e?
  • Impact on other .NET languages? This is not relevant for VB.NET, as all strings are de-facto verbatim (except for the escapement of double quotes). But what about F#? Should this escape sequence also be proposed there?

Design meetings

Attachments and References

@CyrusNajmabadi CyrusNajmabadi changed the title [Proposal]: String/Character escape sequence \e as a short-hand for \u001b [Proposal]: String/Character escape sequence \e as a short-hand for \u001b (<esc>) Jul 27, 2023
@CyrusNajmabadi CyrusNajmabadi self-assigned this Jul 27, 2023
@CyrusNajmabadi CyrusNajmabadi changed the title [Proposal]: String/Character escape sequence \e as a short-hand for \u001b (<esc>) [Proposal]: String/Character escape sequence \e as a short-hand for \u001b (<ESCAPE>) Jul 27, 2023
@CyrusNajmabadi
Copy link
Member

Championing. Hoping to take as an exceedingly cheap change/QOL improvement to the language for console developers.

@theunrepentantgeek
Copy link

Wouldn't this be a breaking change? The meaning of any existing string containing \e will change - maintainers will need to change to \\e to maintain the existing meaning.

I don't think it's a significant breaking change, but I thought this was worth mentioning.

@HaloFour
Copy link
Contributor

HaloFour commented Jul 27, 2023

@theunrepentantgeek

Unrecognized escape sequences are illegal. It's safe to add new escape sequences.

var s = "foo\ebar"; // error CS1009: Unrecognized escape sequence

@CyrusNajmabadi
Copy link
Member

CyrusNajmabadi commented Jul 27, 2023

\e is illegal in the language today. So it's fine to give illegal code legal meaning :)

I would def reject thsi if \e was legal, as it would be totally reasonable to expect some piece of generated code to have used \e in how it emitted things if it was overzealous with escapes.

@CyrusNajmabadi
Copy link
Member

Damnit @HaloFour :D

@theunrepentantgeek
Copy link

I stand corrected! Thanks @HaloFour and @CyrusNajmabadi.

@Unknown6656 Unknown6656 changed the title [Proposal]: String/Character escape sequence \e as a short-hand for \u001b (<ESCAPE>) [Proposal]: String/Character escape sequence \e as a short-hand for \u001b (<ESCAPE>) Jul 28, 2023
@333fred 333fred added the Needs Implementation The specification for this issue has been approved, it needs an implementation label Oct 16, 2023
@333fred 333fred added this to the Any Time milestone Oct 16, 2023
@333fred
Copy link
Member

333fred commented Oct 16, 2023

The LDM has approved the proposed specification for implementation. The issue is in the Any Time milestone, which means that it is approved for community implementation if anyone wants to do so. The C# team itself is unlikely to dedicate time to implementing this ourselves.

@CyrusNajmabadi
Copy link
Member

@Unknown6656 if you want to work on an implementation here, i'm very happy to help out :) I can also do this myself, but i'm not sure when i'll have time for it.

@Unknown6656
Copy link
Contributor Author

Closing this issue, as it has been implemented by @CyrusNajmabadi and merged into roslyn's main branch with dotnet/roslyn#70497.

Minimal working example: https://sharplab.io/#v2:EYLgtghglgdgNAFxAJwK4wD4AECMA6XATgApjYEBKAcgB0BTKigbiA== :

System.Console.WriteLine((int)'\e');
// output:  "27"

Thank you, @CyrusNajmabadi for all your work! ❤️

@HaloFour
Copy link
Contributor

Shouldn't the issue remain open until the specification work is complete?

@jnm2 jnm2 reopened this Feb 23, 2024
@333fred 333fred added Implemented Needs ECMA Spec This feature has been implemented in C#, but still needs to be merged into the ECMA specification and removed Needs Implementation The specification for this issue has been approved, it needs an implementation labels Feb 23, 2024
@Unknown6656
Copy link
Contributor Author

@HaloFour ah fair enough, you're absolutely right!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Implemented Needs ECMA Spec This feature has been implemented in C#, but still needs to be merged into the ECMA specification Proposal champion
Projects
None yet
Development

No branches or pull requests

6 participants