AvalonEdit: Cascading HighlightingColorizers
C#.NetAvaloneditC# Problem Overview
I want to cascade the SyntaxHighlighting Engine of AvalonEdit. I have 2 HighlightingDefinitions
. The first one is the main syntax. The second one is a complex multiline-preprocessor-markup-language. For this reason it is too complicated to embbed the second grammar in the first one. The easier way is to render the first syntax, and change the affected line-parts (based on the second syntax) afterwards.
So I instantiated a new HighlightingColorizer
with the second language and added it to the LineTransformers
. But the second language colorizes the complete document and not only the lineparts with the preprocessor-directives: the non-preprocessor-code is black.
As I debugged the ColorizeLine
-method of the second line transformer, the lines of the non-highlighted code (= no preprocessor code) have not been colorized, as expected. But the color of the lines are black.
So does the HighlightingColorizer
reset all previous highlighting of the whole document before it starts to colorize?
Or what else could be the problem? How can I properly cascade 2 HighlightingColorizers
?
C# Solutions
Solution 1 - C#
The problem is that the HighlightingColorizer
does not directly store a reference to the DocumentHighlighter
, but instead stores it via TextView.Services
. This is done to allow attaching the same colorizer to multiple editors, so that each editor gets its own DocumentHighlighter
.
When you attach a second colorizer, it overwrites the IHighlighter
stored in the service container; and both colorizers end up using the new highlighter.
Also, note that the 'copy to clipboard' logic in HtmlClipboard
directly accesses the IHighlighter
service, it does not use any colorizers. (copying text to Word preserves the syntax highlighting only, no other transformations like fold markers)
There are essentially two approaches to solve this issue:
-
Do not store the additional highlighter as a service. You can do this by creating your own copy of the
HighlightingColorizer
class, and use a field in that class instead of accessingtextView.Services
. This is an easy change, but additional highlighters will not be used when copying text to the clipboard. -
Create an
IHighlighter
implementation that combines theHighlightedLine
s from multipleDocumentHighlighter
s. This is the approach we are using for the C# semantic highlighting in SharpDevelop 5, which works as an additional highlighter that extends the existing .xshd-based C# highlighting. However, this approach is complex (mergingHighlightedLine
s is non-trivial given the ordering and nesting constraints on the sections), and requires an API change to theIHighlighter
interface in order to deal with theOnHighlightStateChanged
notification (AvalonEdit 4.x uses a derived class nested inHighlightingColorizer
to get access to this callback; AvalonEdit 5.0 will use an event).