fisheva / Eva-Theme

A comfortable and semantic theme.
https://marketplace.visualstudio.com/items?itemName=fisheva.eva-theme
MIT License
457 stars 38 forks source link

Fix textmate for cs #112

Closed sharpchen closed 11 months ago

sharpchen commented 11 months ago

Fix

fisheva commented 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!

sharpchen commented 11 months ago

Add code example as comment in json? Or paste them here.

fisheva commented 11 months ago

Paste here.

sharpchen commented 11 months ago

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 };
fisheva commented 11 months ago

@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.

20231221115139

Thanks for your contribution to Eva Theme!

sharpchen commented 11 months ago
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;
    }
}
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();
    }
}
fisheva commented 10 months ago

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. WX20231221-222312@2x

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.

sharpchen commented 10 months ago

What about color typeof, nameof, sizeof and default with #FF6AB3? For a few reasons:

fisheva commented 10 months ago

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!

sharpchen commented 10 months ago

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.

fisheva commented 10 months ago

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.