using System; using System.Collections.Generic; using Avalonia; using AvaloniaEdit; using AvaloniaEdit.TextMate; using TextMateSharp.Grammars; namespace AuroraDesk.Presentation.Attached; /// /// 为 提供基于 TextMate 的语法高亮附加属性, /// 通过 MVVM 绑定即可切换语法与主题。 /// public static class TextMateHelper { public static readonly AttachedProperty LanguageProperty = AvaloniaProperty.RegisterAttached( "Language", typeof(TextMateHelper)); private static readonly AttachedProperty RegistryOptionsProperty = AvaloniaProperty.RegisterAttached( "RegistryOptions", typeof(TextMateHelper)); private static readonly AttachedProperty InstallationProperty = AvaloniaProperty.RegisterAttached( "Installation", typeof(TextMateHelper)); private static readonly IReadOnlyDictionary LanguageScopes = new Dictionary(StringComparer.OrdinalIgnoreCase) { ["C#"] = "source.cs", ["JavaScript"] = "source.js", ["TypeScript"] = "source.ts", ["HTML"] = "text.html.basic", ["CSS"] = "source.css", ["JSON"] = "source.json", ["XML"] = "text.xml", ["Python"] = "source.python", ["Java"] = "source.java", ["SQL"] = "source.sql" }; static TextMateHelper() => LanguageProperty.Changed.AddClassHandler(OnLanguageChanged); public static void SetLanguage(TextEditor editor, string? value) => editor.SetValue(LanguageProperty, value); public static string? GetLanguage(TextEditor editor) => editor.GetValue(LanguageProperty); private static void OnLanguageChanged(TextEditor editor, AvaloniaPropertyChangedEventArgs change) { var language = change.NewValue as string; var registryOptions = EnsureRegistryOptions(editor); var installation = EnsureInstallation(editor, registryOptions); if (installation == null) { return; } var scope = ResolveScope(language); if (!string.IsNullOrWhiteSpace(scope)) { try { installation.SetGrammar(scope); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"TextMateHelper: 设置语法失败 - {ex.Message}"); } } } private static RegistryOptions EnsureRegistryOptions(TextEditor editor) { var registryOptions = editor.GetValue(RegistryOptionsProperty); if (registryOptions == null) { registryOptions = new RegistryOptions(ThemeName.DarkPlus); editor.SetValue(RegistryOptionsProperty, registryOptions); } return registryOptions; } private static TextMate.Installation? EnsureInstallation(TextEditor editor, RegistryOptions registryOptions) { var installation = editor.GetValue(InstallationProperty); if (installation == null) { try { installation = editor.InstallTextMate(registryOptions); editor.SetValue(InstallationProperty, installation); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"TextMateHelper: 安装失败 - {ex.Message}"); } } return installation; } private static string ResolveScope(string? language) { if (string.IsNullOrWhiteSpace(language)) { return "source.cs"; } return LanguageScopes.TryGetValue(language, out var value) ? value : "source.cs"; } }