Closed sharpchen closed 11 months ago
Wow, so many new scope values added. Can you provide a piece of C# code? It should include the code corresponding to all the new Scope values you added so that I can compare the display effect before and after the merge. Thank you!
Add code example as comment in json? Or paste them here.
Paste here.
You can paste this in markdown block, vscode use textmate rules to colorize so you don't have to create project. There are too many keywords involved, I can't list example for each keyword, but this should include almost all of them.
// new-expression
var nums = new[] { 1, 2, 3 };
var p = new Person();
Person p = new();
record class C<T> where T : new()
{
event Action<object> WhateverEvent;
readonly List<T> _list = new();
public delegate void MessageDelegate(string message);
public delegate int AnotherDelegate(MyType m, long num);
public C() : base() { }
public static T operator +(C<T> left, object right) => default;
}
// reflection.operators
public struct Point
{
public Point(byte tag, double x, double y) => (Tag, X, Y) = (tag, x, y);
public byte Tag { get; }
public double X { get; init; } // prop-def
public double Y { get; init; }
}
Console.WriteLine(sizeof(byte));
Console.WriteLine(sizeof(double));
DisplaySizeOf<Point>();
DisplaySizeOf<decimal>();
unsafe
{
Console.WriteLine(sizeof(Point*));
}
void PrintType<T>() => Console.WriteLine(typeof(T));
Console.WriteLine(typeof(List<string>));
PrintType<int>();
PrintType<System.Int32>();
PrintType<Dictionary<int, char>>();
Console.WriteLine(nameof(System.Collections.Generic)); // output: Generic
Console.WriteLine(nameof(List<int>)); // output: List
Console.WriteLine(nameof(List<int>.Count)); // output: Count
Console.WriteLine(nameof(List<int>.Add)); // output: Add
Span<byte> buffer = length <= 1024 ? stackalloc byte[length] : new byte[length];
// pattern matching
string? GetMessage() => null;
if (GetMessage() is {} and var message)
{
Console.WriteLine(message);
}
string WaterState(int tempInFahrenheit) =>
tempInFahrenheit switch
{
(> 32) and (< 212) => "liquid",
< 32 => "solid",
> 212 => "gas",
32 => "solid/liquid transition",
212 => "liquid / gas transition",
};
public decimal CalculateDiscount(Order order) =>
order switch
{
{ Items: > 10, Cost: > 1000.00m } => 0.10m,
{ Items: > 5, Cost: > 500.00m } => 0.05m,
{ Cost: > 250.00m } => 0.02m,
null => throw new ArgumentNullException(nameof(order), "Can't calculate discount on null order"),
var someObject => 0m,
};
decimal balance = 0m;
foreach (string[] transaction in ReadRecords())
{
balance += transaction switch
{
[_, "DEPOSIT", _, var amount] => decimal.Parse(amount),
[_, "WITHDRAWAL", .., var amount] => -decimal.Parse(amount),
[_, "INTEREST", var amount] => decimal.Parse(amount),
[_, "FEE", var fee] => -decimal.Parse(fee),
_ /* discard symbol */ => throw new InvalidOperationException($"Record {string.Join(", ", transaction)} is not in the expected format!"),
};
Console.WriteLine($"Record: {string.Join(", ", transaction)}, New balance: {balance:C}");
}
void MatchMessage(string message)
{
var result = message is ['a' or 'A', .. var s, 'a' or 'A']
? $"Message {message} matches; inner part is {s}."
: $"Message {message} doesn't match.";
Console.WriteLine(result);
}
MatchMessage("aBBA"); // output: Message aBBA matches; inner part is BB.
MatchMessage("apron"); // output: Message apron doesn't match.
void Validate(int[] numbers)
{
var result = numbers is [< 0, .. { Length: 2 or 4 }, > 0] ? "valid" : "not valid";
Console.WriteLine(result);
}
Validate(new[] { -1, 0, 1 }); // output: not valid
Validate(new[] { -1, 0, 0, 1 }); // output: valid
// enum
public enum LogLevel
{
Error,
Warning
}
// goto
Start:
Console.ReadKey();
goto Start;
// preprocessor
#nullable enable
class C
{
#if DEBUG
internal
#else
private
#endif
static string M() => string.Empty;
}
// tuple element
var (a, b) = GetTuple();
// linq
var innerGroupJoinQuery =
from category in categories
join prod in products on category.ID equals prod.CategoryID into prodGroup
select new { CategoryName = category.Name, Products = prodGroup };
@sharpchen I made some color modifications to the following scope values that you submitted (the color in the comment was yours):
"editor.tokenColorCustomizations": {
"textMateRules": [
{
"name": "cs.lambda",
"scope": "keyword.operator.arrow.cs",
"settings": {
"foreground": "#437AED", //#00BEC4
}
},
{
"name": "cs.enum",
"scope": "entity.name.type.enum.cs",
"settings": {
"foreground": "#5D5D5F", //#00BEC4
}
},
{
"scope": "variable.language.base.cs,storage.type.accessor.get.cs,storage.type.accessor.set.cs,storage.type.accessor.init.cs,keyword.operator.expression.nameof.cs,keyword.operator.expression.typeof.cs,keyword.operator.expression.sizeof.cs,",
"settings": {
"foreground": "#437AED", //#7C4DFF
}
},
{
"name": "default",
"scope": "keyword.operator.expression.default.cs,keyword.operator.expression.pattern.is.cs,keyword.operator.expression.pattern.combinator.or.cs,keyword.operator.expression.pattern.combinator.and.cs,keyword.operator.expression.pattern.combinator.not.cs,keyword.operator.expression.query.let.cs,keyword.operator.expression.query.by.cs,keyword.operator.expression.query.on.cs,keyword.operator.expression.query.ascending.cs,keyword.operator.expression.query.descending.cs,keyword.operator.expression.query.from.cs,keyword.operator.expression.query.in.cs,keyword.operator.expression.query.select.cs,keyword.operator.expression.query.where.cs,keyword.operator.expression.query.join.cs,keyword.operator.expression.query.on.cs,keyword.operator.expression.query.equals.cs,keyword.operator.expression.query.into.cs,keyword.operator.expression.query.orderby.cs",
"settings": {
"foreground": "#C838C6", //#7C4DFF
}
},
{
"name": "cs.preprocessor",
"scope": "meta.preprocessor.cs",
"settings": {
"foreground": "", //#7C4DFF
}
},
],
},
They will be updated along with other scope values you submitted, in the 2.4.8 version of the Eva Theme tonight. You can see change log at here.
Thanks for your contribution to Eva Theme!
typeof
, nameof
, sizeof
and default
are actually operators in C#
that resolve values at compile time, though they look like macros. That's why I color them with #7C4DFF
. And for default
, I noticed you color it as the same as control flow keyword. However, default
can be both control flow keyword and an operator, they are in different scope. In conclusion, typeof
, nameof
, sizeof
and default
should be same colored, and not as functions.record class C<T> where T : new()
{
public static T operator +(C<T> left, object right) => default(T);// keyword.operator.expression.default.cs
}
void DisplayMeasurement(double measurement)
{
switch (measurement)
{
default: // keyword.control.conditional.default.cs
Console.WriteLine($"Measured value is {measurement}.");
break;
}
}
base
keyword, it should be same as this
(currently #F02B77
). They are both very special reference keyword for the inheritance.record class C<T> : B<T> where T : new()
{
object? obj;
public C(object obj) : base()
{
this.obj = obj;
}
public C() : this(default) { }
public override void M()
{
base.M();
}
}
enum
? Why is enum
the only type colored so poorš¤In the semantics of Eva Theme,
#7C4DFF
is used for keywords with declarative meanings, such as variable declaration, function declaration, class declaration, and so on.
typeof
, sizeof
, and nameof
do not have this declarative meaning. However, their syntax and appearance are very similar to functions, and their functionality is also very similar to functions as they take a parameter and process it. So I set them blue.
default
has already been assigned purple color in the context of flow control, and I simply don't want the same word to be displayed in two different colors. Otherwise, it should be displayed in blue here too.
Ok, I will set base
to have the same color as this
.
I don't dislike enums. It's just that, in my opinion, an enum and an array are very similar in form, with the array name being a variable color. Therefore, enum names are also assigned the color of variables.
What about color typeof
, nameof
, sizeof
and default
with #FF6AB3
? For a few reasons:
typeof
, nameof
, sizeof
and default
are part of the language, as primitive types(int
, string
...) are also #FF6AB3
.typeof
, nameof
, sizeof
and default
resolve values at compile time, however function or method return at runtime. And they accept type as parameter while function or method take instance as parameter. C#
developers can be very sensitive to these fundamental difference. There is huge difference except the form.typeof
for javascript
with #FF6AB3
default
operator should have different color from the control-flow one, C#
developers have the ability or will be very sensitive to tell different usage of the same keyword but still same color. It just makes sense to keep the semantics of the language using different colors, that's why they assign different scopes for a same keyword! Differentiating the colors ofĀ nameof
,Ā sizeof
Ā from function colors can distinguish between compile-time processing of values and runtime processing of values.
But it breaks the semantic meaning of the pink color, which would be the same if replaced with any other color. Only functions are closest to their writing style and functional logic.
In the Eva Theme, the semantic meaning of pink is data types. SettingĀ typeof
Ā in JS as pink is because JS doesn't have type annotations, andĀ typeof
Ā returns a data type, so I want users to associateĀ data types when they see typeof
in JS. Additionally, the way it is written in JS is very similar to type annotations in TS. I once changed the color of typeof
in JS to blue, but it didn't look good, so I reverted it.
The essence of this problem is that the richness of code semantics far exceeds the number of available colors. Therefore, theme makers have to assign reasonable code semantics within the limited color choices, making the code interface display colors good-looking and semantically.
Currently, Class, Interfaces, and Struct have the same color, sometimes, they appear consecutively in the code, resulting in insufficient differentiation. I have always wanted to add new colors to solve this problem. However, adding new colors is not an easy task either. The new color must simultaneously satisfy the following:
1) good-looking. 2) Sufficient differentiation from various existing character colors. 3) Remains clear and visible under the background color and various existing selection colors.
So, in your previous comment, I can only satisfy one requirement, to differentiate the meanings of default
, while it will be blue, like sizeof
.
It's been a long time since I had such an in-depth discussion with someone about Eva Theme. It's a great time chatting today! It's too late now, I'm going to sleep. I will update Eva Theme tomorrow. Good night!
I understand your consideration, wish someday we could have more color categories for more concepts or have a color as fallback. What came into my mind is about keyword operators, like typeof
, keyof
, instanceof
in ts, nameof
and is
in cs, typeid
in cpp and so on. These operators are common design from many languages. They all return something but differ from arithmetic operators in semantics. It's definitely a thing worth to do.
Eva Theme has just been updated to version 2.4.9, incorporating all the discussed content above. Note that your editor.tokenColorCustomizations
settings can override the theme display.
Fix