Files
2026-08-05 14:45:08 -05:00

95 lines
3.7 KiB
C#

using Godot;
using Godot.Collections;
using System;
using System.Text.RegularExpressions;
namespace ReEdit.Syntax
{
public partial class Lua : SyntaxHighlighter
{
// Define Godot colors matching VS Code defaults
private static readonly Color ColorKeyword = Color.FromHtml("#C586C0"); // Purple
private static readonly Color ColorFunction = Color.FromHtml("#DCDCAA"); // Yellow
private static readonly Color ColorString = Color.FromHtml("#CE9178"); // Peach
private static readonly Color ColorLocal = Color.FromHtml("#CE7882"); // redish
private static readonly Color ColorNumber = Color.FromHtml("#B5CEA8"); // Sage Green
private static readonly Color ColorVariable = Color.FromHtml("#9CDCFE"); // Sky Blue
private static readonly Color ColorConstant = Color.FromHtml("#4FC1FF"); // Cyan Blue
private static readonly Color ColorComment = Color.FromHtml("#6A9955"); // Foliage Green
private static readonly Color ColorOperator = Color.FromHtml("#D4D4D4"); // Light Gray
// Token rule definition structure
private struct TokenRule
{
public Regex Regex;
public Color Color;
public TokenRule(string pattern, Color color)
{
Regex = new Regex("^(" + pattern + ")", RegexOptions.Compiled);
Color = color;
}
}
private static readonly TokenRule[] Rules = new TokenRule[]
{
new TokenRule(@"--\[\[[\s\S]*?\]\]|--.*", ColorComment),
new TokenRule(@"\[\[[\s\S]*?\]\]|""([^""\\]|\\.)*""|'([^'\\]|\\.)*'", ColorString),
new TokenRule(@"\b(and|break|do|else|elseif|end|for|function|if|in|not|or|repeat|return|then|until|while)\b", ColorKeyword),
new TokenRule(@"\b(local)\b", ColorLocal),
new TokenRule(@"\b(true|false|nil)\b", ColorConstant),
new TokenRule(@"\b[a-zA-Z_][a-zA-Z0-9_]*(?=\s*\()", ColorFunction),
new TokenRule(@"\b0x[0-9a-fA-F]+\b|\b\d+(\.\d+)?\b", ColorNumber),
new TokenRule(@"==|~=|<=|>=|\.\.|[.+\-*/%^#=<>(){}\[\];,:]", ColorOperator),
new TokenRule(@"\b[a-zA-Z_][a-zA-Z0-9_]*\b", ColorVariable)
};
public override Godot.Collections.Dictionary _GetLineSyntaxHighlighting(int lineIdx)
{
var highlightingData = new Godot.Collections.Dictionary();
string lineText = GetTextEdit().GetLine(lineIdx);
int currentColumn = 0;
int lineLength = lineText.Length;
while (currentColumn < lineLength)
{
if (char.IsWhiteSpace(lineText[currentColumn]))
{
currentColumn++;
continue;
}
string remainingText = lineText.Substring(currentColumn);
bool matchFound = false;
foreach (var rule in Rules)
{
Match match = rule.Regex.Match(remainingText);
if (match.Success)
{
int tokenLength = match.Length;
var colorContainer = new Dictionary { { "color", rule.Color } };
highlightingData[currentColumn] = colorContainer;
currentColumn += tokenLength;
matchFound = true;
break;
}
}
if (!matchFound)
{
var fallbackColor = new Dictionary { { "color", ColorVariable } };
highlightingData[currentColumn] = fallbackColor;
currentColumn++;
}
}
return highlightingData;
}
}
}