using System; using System.Linq; using TextMateSharp.Grammars; using TextMateSharp.Model; using TextMateSharp.Registry; using TextMateSharp.Themes; namespace Unity.CodeEditor.TextMate { internal static class TextMate { internal static void RegisterExceptionHandler(Action handler) { _exceptionHandler = handler; } internal static Installation InstallTextMate( this TextEditor editor, IRegistryOptions registryOptions, bool initCurrentDocument = true) { return new Installation(editor, registryOptions, initCurrentDocument); } internal class Installation { private IRegistryOptions _textMateRegistryOptions; private Registry _textMateRegistry; private TextEditor _editor; private TextEditorModel _editorModel; private IGrammar _grammar; private TMModel _tmModel; private TextMateColoringTransformer _transformer; internal IRegistryOptions RegistryOptions { get { return _textMateRegistryOptions; } } internal TextEditorModel EditorModel { get { return _editorModel; } } internal Installation(TextEditor editor, IRegistryOptions registryOptions, bool initCurrentDocument = true) { _textMateRegistryOptions = registryOptions; _textMateRegistry = new Registry(registryOptions); _editor = editor; SetTheme(registryOptions.GetDefaultTheme()); editor.DocumentChanged += OnEditorOnDocumentChanged; if (initCurrentDocument) { OnEditorOnDocumentChanged(editor, EventArgs.Empty); } } internal void SetGrammar(string scopeName) { _grammar = _textMateRegistry.LoadGrammar(scopeName); GetOrCreateTransformer().SetGrammar(_grammar); _editor.TextArea.TextView.Redraw(); } internal void SetTheme(IRawTheme theme) { _textMateRegistry.SetTheme(theme); GetOrCreateTransformer().SetTheme(_textMateRegistry.GetTheme()); _tmModel?.InvalidateLine(0); _editorModel?.InvalidateViewPortLines(); } internal void Dispose() { _editor.DocumentChanged -= OnEditorOnDocumentChanged; DisposeEditorModel(_editorModel); DisposeTMModel(_tmModel, _transformer); DisposeTransformer(_transformer); } void OnEditorOnDocumentChanged(object sender, EventArgs args) { try { DisposeEditorModel(_editorModel); DisposeTMModel(_tmModel, _transformer); _editorModel = new TextEditorModel(_editor.TextArea.TextView, _editor.Document, _exceptionHandler); _tmModel = new TMModel(_editorModel); _tmModel.SetGrammar(_grammar); _transformer = GetOrCreateTransformer(); _transformer.SetModel(_editor.Document, _tmModel); _tmModel.AddModelTokensChangedListener(_transformer); } catch (Exception ex) { _exceptionHandler?.Invoke(ex); } } TextMateColoringTransformer GetOrCreateTransformer() { var transformer = _editor.TextArea.TextView.LineTransformers.OfType().FirstOrDefault(); if (transformer is null) { transformer = new TextMateColoringTransformer( _editor.TextArea.TextView, _exceptionHandler); _editor.TextArea.TextView.LineTransformers.Add(transformer); } return transformer; } static void DisposeTransformer(TextMateColoringTransformer transformer) { if (transformer == null) return; transformer.Dispose(); } static void DisposeTMModel(TMModel tmModel, TextMateColoringTransformer transformer) { if (tmModel == null) return; if (transformer != null) tmModel.RemoveModelTokensChangedListener(transformer); tmModel.Dispose(); } static void DisposeEditorModel(TextEditorModel editorModel) { if (editorModel == null) return; editorModel.Dispose(); } } static Action _exceptionHandler; } }