AvalonEdit: Cascading HighlightingColorizers
Asked Answered
I

1

67

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?

Insulin answered 24/1, 2012 at 18:35 Comment(2)
I've worked a bit with AvalonEdit- and IIRC it does reset all highlighting when you apply another colorizer. The best way around this would be to re-attempt to embed the second grammar within the first- failing that you would have to mess with AvalonEdit's codebase to change how it interprets and re-applies the color scheme. The latter would probably be non-trivial as I dont think its going to be as easy an 'commenting the reset' or something like that.Prophylaxis
@Xeno is right here. You will definately have to edit the code base if you do not wish to use XML definition files. However, I am not sure why you would not want to do this - they can be as long as you want and can be used to colorize the smalled detail. I have just written a file to do a simalar thing with embedded SQL; it is fast and works well...Ardrey
A
7

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:

  1. 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 accessing textView.Services. This is an easy change, but additional highlighters will not be used when copying text to the clipboard.

  2. Create an IHighlighter implementation that combines the HighlightedLines from multiple DocumentHighlighters. 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 (merging HighlightedLines is non-trivial given the ordering and nesting constraints on the sections), and requires an API change to the IHighlighter interface in order to deal with the OnHighlightStateChanged notification (AvalonEdit 4.x uses a derived class nested in HighlightingColorizer to get access to this callback; AvalonEdit 5.0 will use an event).

Alloway answered 18/10, 2012 at 17:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.