177 lines
6.1 KiB
C#
177 lines
6.1 KiB
C#
using System.Text;
|
|
using syntax.Tokenization;
|
|
|
|
namespace syntax.Diagnostics;
|
|
|
|
public static class ConsoleColors
|
|
{
|
|
public const string Reset = "\e[0m";
|
|
public const string Bold = "\e[1m";
|
|
public const string Faint = "\e[2m";
|
|
public const string Italic = "\e[3m";
|
|
public const string Underline = "\e[4m";
|
|
public const string SlowBlink = "\e[5m";
|
|
public const string RapidBlink = "\e[6m";
|
|
public const string SwapBgAndFg = "\e[7m";
|
|
public const string Conceal = "\e[8m";
|
|
public const string CrossedOut = "\e[9m";
|
|
|
|
public const string DefaultFont = "\e[10m";
|
|
public const string AltFont1 = "\e[11m";
|
|
public const string AltFont2 = "\e[12m";
|
|
public const string AltFont3 = "\e[13m";
|
|
public const string AltFont4 = "\e[14m";
|
|
public const string AltFont5 = "\e[15m";
|
|
public const string AltFont6 = "\e[16m";
|
|
public const string AltFont7 = "\e[17m";
|
|
public const string AltFont8 = "\e[18m";
|
|
public const string AltFont9 = "\e[19m";
|
|
|
|
public const string Black = "\e[30m";
|
|
public const string Red = "\e[31m";
|
|
public const string Green = "\e[32m";
|
|
public const string Yellow = "\e[33m";
|
|
public const string Blue = "\e[34m";
|
|
public const string Magenta = "\e[35m";
|
|
public const string Cyan = "\e[36m";
|
|
public const string White = "\e[37m";
|
|
|
|
public const string BrightBlack = "\e[90m";
|
|
public const string BrightRed = "\e[91m";
|
|
public const string BrightGreen = "\e[92m";
|
|
public const string BrightYellow = "\e[93m";
|
|
public const string BrightBlue = "\e[94m";
|
|
public const string BrightMagenta = "\e[95m";
|
|
public const string BrightCyan = "\e[96m";
|
|
public const string BrightWhite = "\e[97m";
|
|
|
|
private static bool IsColorSupported()
|
|
{
|
|
var term = Environment.GetEnvironmentVariable("TERM");
|
|
var colorTerm = Environment.GetEnvironmentVariable("COLORTERM");
|
|
return !string.IsNullOrEmpty(term) || !string.IsNullOrEmpty(colorTerm) || !Console.IsOutputRedirected;
|
|
}
|
|
|
|
public static string Colorize(string text, string color)
|
|
{
|
|
return IsColorSupported() ? $"{color}{text}{Reset}" : text;
|
|
}
|
|
|
|
private static string GetTokenColor(Token token)
|
|
{
|
|
switch (token)
|
|
{
|
|
case DocumentationToken:
|
|
return Faint;
|
|
case IdentifierToken:
|
|
return White;
|
|
case LiteralToken literal:
|
|
return literal.Kind switch
|
|
{
|
|
LiteralKind.String => Green,
|
|
LiteralKind.Integer or LiteralKind.Float => BrightBlue,
|
|
LiteralKind.Bool => Blue,
|
|
_ => White
|
|
};
|
|
case ModifierToken:
|
|
return White;
|
|
case SymbolToken symbol:
|
|
switch (symbol.Symbol)
|
|
{
|
|
case Symbol.If:
|
|
case Symbol.Else:
|
|
case Symbol.While:
|
|
case Symbol.Break:
|
|
case Symbol.Continue:
|
|
case Symbol.Return:
|
|
return Magenta;
|
|
case Symbol.Func:
|
|
case Symbol.Struct:
|
|
case Symbol.Namespace:
|
|
case Symbol.Let:
|
|
case Symbol.Alloc:
|
|
return Blue;
|
|
case Symbol.Assign:
|
|
case Symbol.Bang:
|
|
case Symbol.Equal:
|
|
case Symbol.NotEqual:
|
|
case Symbol.LessThan:
|
|
case Symbol.LessThanOrEqual:
|
|
case Symbol.GreaterThan:
|
|
case Symbol.GreaterThanOrEqual:
|
|
case Symbol.Plus:
|
|
case Symbol.Minus:
|
|
case Symbol.Star:
|
|
case Symbol.ForwardSlash:
|
|
case Symbol.Caret:
|
|
case Symbol.Ampersand:
|
|
return White;
|
|
case Symbol.Semicolon:
|
|
case Symbol.Colon:
|
|
case Symbol.Comma:
|
|
case Symbol.Period:
|
|
case Symbol.DoubleColon:
|
|
return Faint;
|
|
case Symbol.OpenParen:
|
|
case Symbol.CloseParen:
|
|
case Symbol.OpenBrace:
|
|
case Symbol.CloseBrace:
|
|
case Symbol.OpenBracket:
|
|
case Symbol.CloseBracket:
|
|
return Yellow;
|
|
default:
|
|
return White;
|
|
}
|
|
default:
|
|
return White;
|
|
}
|
|
}
|
|
|
|
public static string ColorizeSource(string source)
|
|
{
|
|
var sourceText = new SourceText(string.Empty, source);
|
|
var tokens = Tokenizer.Tokenize(sourceText).Value;
|
|
var result = new StringBuilder();
|
|
var lastCharIndex = 0;
|
|
|
|
foreach (var token in tokens)
|
|
{
|
|
var tokenStartIndex = GetCharacterIndex(sourceText, token.Span.Start);
|
|
var tokenEndIndex = GetCharacterIndex(sourceText, token.Span.End);
|
|
|
|
if (tokenStartIndex > lastCharIndex)
|
|
{
|
|
var between = sourceText.Content.Substring(lastCharIndex, tokenStartIndex - lastCharIndex);
|
|
result.Append(between);
|
|
}
|
|
|
|
var tokenText = sourceText.Content.Substring(tokenStartIndex, tokenEndIndex - tokenStartIndex);
|
|
|
|
result.Append(Colorize(tokenText, GetTokenColor(token)));
|
|
lastCharIndex = tokenEndIndex;
|
|
}
|
|
|
|
if (lastCharIndex < sourceText.Content.Length)
|
|
{
|
|
var remaining = sourceText.Content[lastCharIndex..];
|
|
result.Append(Colorize(remaining, Faint));
|
|
}
|
|
|
|
return result.ToString();
|
|
}
|
|
|
|
private static int GetCharacterIndex(SourceText sourceText, SourceLocation location)
|
|
{
|
|
var lines = sourceText.Content.Split('\n');
|
|
var index = 0;
|
|
|
|
for (var i = 0; i < location.Line - 1 && i < lines.Length; i++)
|
|
{
|
|
index += lines[i].Length + 1;
|
|
}
|
|
|
|
index += location.Column - 1;
|
|
|
|
return Math.Min(index, sourceText.Content.Length);
|
|
}
|
|
} |