Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I create an AvalonEdit syntax file (.xshd) and embed it into my assembly?

I'm trying to define some custom highlighting rules for AvalonEdit. There doesn't seem to be any documentation for this -- there's some documentation on the file format, but nothing on how to actually load and use the definition once you've created it.

The "Syntax highlighting" wiki page (for the old WinForms TextEditor) documents how to load highlighting definitions from a .xshd file on disk, but I'd rather embed it as a resource, the same way AvalonEdit does with its built-in definitions.

I've looked at the code in the ICSharpCode.AvalonEdit project that loads its built-in highlighters, but the actual "load from resource" code is done in DefaultHighlightingManager.LoadHighlighting, which is private -- and which, to make things weirder, is apparently only called in release builds.

I can keep fumbling around, copy/paste some of the code from the private methods, and try to cobble something together that might or might not work, but it seems worthwhile to ask: what is the standard way to do this? Is there a recommended way for third-party code to load a highlighting definition from a resource?


Daniel's answer gave me a good start, but you need to include the namespace name in the string you pass to GetManifestResourceStream -- if you don't, you'll get a NullReferenceException (because it returns a null stream).

I wound up adding a static class called ResourceLoader to the same project folder as the .xshd file, with this method:

public static IHighlightingDefinition LoadHighlightingDefinition(
    string resourceName)
{
    var type = typeof(ResourceLoader);
    var fullName = type.Namespace + "." + resourceName;
    using (var stream = type.Assembly.GetManifestResourceStream(fullName))
    using (var reader = new XmlTextReader(stream))
        return HighlightingLoader.Load(reader, HighlightingManager.Instance);
}

Then I can just call ResourceLoader.LoadHighlightingDefinition("Name.xshd").

For anyone following along at home, the .xshd file needs to have its Build Action set to Embedded Resource.

like image 659
Joe White Avatar asked Feb 20 '11 13:02

Joe White


3 Answers

You can use the static methods in the class ICSharpCode.AvalonEdit.Highlighting.Xshd.HighlightingLoader to load .xshd files. For example:

using (Stream s = myAssembly.GetManifestResourceStream("MyHighlighting.xshd")) {
    using (XmlTextReader reader = new XmlTextReader(s)) {
        textEditor.SyntaxHighlighting = HighlightingLoader.Load(reader, HighlightingManager.Instance);
    }
}

The loading code in AvalonEdit itself is weird because it eagerly loads the xshds in debug builds (so that errors in them are noticed immediately), but delay-loads them in release builds.

like image 106
Daniel Avatar answered Nov 08 '22 01:11

Daniel


I personally prefer Darren's way of registering your highlighting definition using RegisterHighlighting, then you can use it in your XAML like other built-in definitions.

C#

public partial class App : Application
{
    public App()
    {
        using (var stream = new System.IO.MemoryStream(WpfApp15.Properties.Resources.sql))
        {
            using (var reader = new System.Xml.XmlTextReader(stream))
            {
                ICSharpCode.AvalonEdit.Highlighting.HighlightingManager.Instance.RegisterHighlighting("SQL", new string[0],
                    ICSharpCode.AvalonEdit.Highlighting.Xshd.HighlightingLoader.Load(reader,
                        ICSharpCode.AvalonEdit.Highlighting.HighlightingManager.Instance));
            }
        }
    } 
}

XAML

<avalon:TextEditor SyntaxHighlighting="SQL"/>
like image 43
Masood Lapeh Avatar answered Nov 08 '22 00:11

Masood Lapeh


For what it's worth, if you're using F#, this is a code snippet that works to register the xshd file.

let registerHighlighting() =
    try
        // Load our custom highlighting definition
        match System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("GSLhighlighting.xshd") with
            | null -> failwithf "ERROR: could not find embedded resource"
            | s ->
                use reader = new XmlTextReader(s)
                let gslHighlighting = ICSharpCode.AvalonEdit.Highlighting.Xshd.HighlightingLoader.Load(reader, HighlightingManager.Instance)
                // and register it in the HighlightingManager
                HighlightingManager.Instance.RegisterHighlighting("GSL", [| ".gsl" |], gslHighlighting)
                editor.SyntaxHighlighting <- gslHighlighting
    with _ as exn ->
        printfn "ERROR: %s" exn.Message
like image 5
Darren Avatar answered Nov 08 '22 00:11

Darren