diff --git a/assets/highlighting-tests/cs.cs b/assets/highlighting-tests/cs.cs new file mode 100644 index 00000000000..cee84344a91 --- /dev/null +++ b/assets/highlighting-tests/cs.cs @@ -0,0 +1,151 @@ +// Comments +// Single-line comment + +/* +Multi-line +comment +*/ + +global using static System.Console; +using System; + +// Numbers +42; +3.14; +.5; +10_000_000; +1e10; +1.5e-3; +0xff; +0xffu; +0xffl; +0xfful; +0xFF; +0Xff; +0XFF; +0XFFU; +0XFFL; +0XFFLU; +0b1010; +0B1010; +42u; +42U; +42l; +42L; +42UL; +42Ul; +42uL; +42ul; +42LU; +42Lu; +42lU; +42lu; +3.14f; +3.14d; +-.5_0_1e3_0d; + +// Constants +true; +false; +null; + +// Strings and Characters +'a'; +'\n'; +"double quotes with escape: \" \n \t \\"; +$"double quotes with a value {1 + 1}"; +@"double quotes with "; +$@""; +@$""; + +// Control flow keywords +if (true) +{ + +} +else if (false) +{ + +} +else +{ + +} + +for (int i = 0; i < 10; i++) +{ + if (i == 5) continue; + if (i == 8) break; +} + +while (false) { } +do { } while (true); + +switch (42) +{ + case 1: break; + default: break; +} + +try +{ + throw new Exception("oops"); +} +catch (System.Exception) +{ + +} +finally +{ + +} + +// Other keywords (some are contextually reserved) +var a = 1; +dynamic b = 2; +T c = 3; + +string Greet(string name) +{ + return "Hello, " + name; +} + +static int Factorial(int n) +{ + if (n == 0) + { + return 1; + } + + return n * Factorial(n - 1); +} + +class Animal +{ + private int _Age; + public int Age { get => _Age; } + protected bool _IsAlive; + public bool IsAlive { get => _IsAlive; } + public Animal(int age, bool isAlive) + { + _Age = age; + _IsAlive = isAlive; + } + + public virtual void Speak() { } +} + +class Dog : Animal +{ + private string _Bark; + + public Dog(string bark, int age, bool isAlive) : base(age, isAlive) + { + + } + + public override void Speak() + { + Console.WriteLine(_Bark); + } +} diff --git a/assets/highlighting-tests/markdown.md b/assets/highlighting-tests/markdown.md index 555b182f961..b0ecfbf1d1f 100644 --- a/assets/highlighting-tests/markdown.md +++ b/assets/highlighting-tests/markdown.md @@ -84,3 +84,10 @@ export function greet(name) { def greet(name: str) -> str: return f"hello {name}" ``` + +```CSharp +public string Greet(string name) +{ + return $"hello {name}"; +} +``` diff --git a/crates/lsh/definitions/cs.lsh b/crates/lsh/definitions/cs.lsh new file mode 100644 index 00000000000..18cd02f67be --- /dev/null +++ b/crates/lsh/definitions/cs.lsh @@ -0,0 +1,60 @@ +#[display_name = "C#"] +#[path = "**/*.cs"] +pub fn CSharp() { + until /$/ { + yield other; + + if /\/\/.*/ { + yield comment; + } else if /\/\*/ { + loop { + yield comment; + await input; + if /\*\// { + yield comment; + break; + } + } + } else if /[@$]{0,2}"/ { + until /$/ { + yield string; + if /\\./ {} + else if /"/ { + yield string; + break; + } + await input; + } + } else if /'/ { + until /$/ { + yield string; + if /\\./ {} + else if /'/ { + yield string; + break; + } + await input; + } + } else if /(?:global|using|static)/ { + yield keyword.control; + } else if /(?:as$|break|case|catch|checked|continue|default|do|else|for|foreach|finaly|fixed|goto|if|is$|lock|return|switch|throw|try|while|unchecked|by|descending|equals|extention|from|group|into|join|nameof|on$|or$|orderby|select|when|where|with|yield)/ { + yield keyword.control; + } else if /(?:abstract|bool|byte|char|class|const|decimal|delegate|double|enum|event|explicit|extern|float|implicit|int|interface|internal|long|namespace|new|object|operator|out|override|params|private|protected|public|readonly|ref|sealed|short|static|string|struct|this|typeof|uint|ulong|unsafe|ushort|virtual|void|volatile|add|args|async|await|dynamic|field|file|get|init|let|managed|nint|not|notnull|nuint|partial|record|required|sbyte|scoped|set|T|unmanaged|var)/ { + yield keyword.other; + } else if /(?i:-?(?i:0x[\da-fA-F_]+|0b[01_]+|[\d_]+\.?[\d_]*|\.[\d_]+)(?i:[+-]?[\d_]+|e[+-]?[\d_]+)?[uUlLfFdD]*)/ { + if /\w+/ { + // Invalid numeric literal + } else { + yield constant.numeric; + } + } else if /(?:true|false|null)/ { + yield constant.language; + }else if /(\w+)\s*\(/ { + yield $1 as method; + } else if /\w+/ { + // Gobble word chars to align the next iteration on a word boundary. + } + + yield other; + } +} diff --git a/crates/lsh/definitions/markdown.lsh b/crates/lsh/definitions/markdown.lsh index 77a005fe925..784c46e29cc 100644 --- a/crates/lsh/definitions/markdown.lsh +++ b/crates/lsh/definitions/markdown.lsh @@ -90,6 +90,16 @@ pub fn markdown() { if /.*/ {} } } + } else if /(?i:C\#|CSharp|cs)/ { + loop { + await input; + if /\s*```/ { + return; + } else { + CSharp(); + if /.*/ { } + } + } } else { loop { await input;