简体   繁体   English

AvalonEdit:是否可以突出显示此语法?

[英]AvalonEdit: is it possible to highlight this syntax?

I have a simple "language" (similar to template languages and simple markup languages such as BBcode — basically it's just normal text with some variables, tags and similar features) and I want to highlight its syntax. 我有一个简单的“语言”(类似于模板语言和简单的标记语言,如BBcode-基本上是带有一些变量,标签和类似功能的普通文本),我想强调其语法。

Here is the thing I am stuck with. 这就是我坚持的东西。

There are variables, they are enclosed with $ sign ( $var1$ ). 有变量,它们用$符号( $ var1 $ )括起来。 I highlight them with this rule: 我用以下规则突出显示它们:

<RuleSet name="VariableSet">
    <Rule color="Variable">
        \$\S+?\$
    </Rule>
</RuleSet>

Some area around a variable can be surrounded with { } characters. 变量周围的某些区域可以用{}字符包围。

In other words: some variables can have its "region", it starts from the first { before the variable and ends at the first } after the variable. 换句话说:某些变量可以具有其“区域”,它从变量之前的第一个{开始,到变量之后的第一个}结束。 Multiple variables can't be in one region, so in cases like { $var1$ $var2$ } there is no any regions, { } are treated like normal characters and ignored. 多个变量不能在一个区域中,因此在类似{ $var1$ $var2$ } ,没有任何区域,{}被视为普通字符并被忽略。 It is not a scope like function and local scopes in C-style languages. 它不像C样式语言中的函数和本地作用域那样。

Here is an example: 这是一个例子:

[b]lorem ipsum[/b] $var0$ dolor sit amet, consectetur adipisicing elit, sed do 
eiusmod tempor incididunt ut labore et dolore magna aliqua. 
{ // <— not nighlighted
{ // <— highlighted
ut enim ad minim veniam, quis nostrud 
$var1$
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
} // <— highlighted
} // <— not nighlighted

// all brackets below also should be not highlighted
duis aute { $50, 25$} irure { dolor } excepteur $var2$ sint occaecat cupidatat non
proident, sunt in culpa qui mollit anim id { est $var2$ laborum.
{ $var3$ $var4$ }

First I tried to solve this using two Rule regexps (for { and }, of course with this approach it is impossible to skip cases with unclosed brackets like { $var$ or $var$ } but that's not a big problem). 首先,我尝试使用两个Rule表达式解决这个问题(对于{和},当然,使用这种方法,不可能跳过括号中没有{ $var$$var$ }这样的情况,但这不是一个大问题)。 However I found out that Rule works only within one line. 但是我发现Rule仅在一行内起作用。

Then I tried Span like this: 然后我像这样尝试了Span

<Span color="VariableAreaDelimiter" multiline="true">
    <Begin>
        \{(?!\{.*?\$\S+?\$)(?=.*?\$\S+?\$)
    </Begin>
    <End>
        \}
    </End>

    <RuleSet>
        <Import ruleSet="VariableSet"/>
        <Rule foreground="Black" fontWeight="normal">
            .
        </Rule>
    </RuleSet>
</Span>

Some of the problems: 一些问题:

  • Although the multiline is true regexps in Begin and End don't work for multiple lines. 尽管multilinetrue ,但BeginEnd正则表达式不适用于多行。 So it doesn't match this: 因此,它与此不匹配:

     { $var$ 
  • If there is no closing bracket the span takes everything until end of document. 如果没有右括号,则跨度将使用所有内容,直到文档末尾。 That's why I added the . 这就是为什么我添加. rule. 规则。

This is fundamentally impossible with AvalonEdit's highlighting engine. 使用AvalonEdit的突出显示引擎根本上是不可能的。

The engine is line-based, you cannot perform any multi-line matches. 该引擎是基于行的,因此您无法执行任何多行匹配。 The only way to carry information from one line to the next is by opening a span -- the only state maintained by the highlighting engine is the stack of currently open spans. 从一条线到另一条线传送信息的唯一方法是打开一个跨度-高亮引擎保持的唯一状态是当前打开的跨度的堆栈。

The highlighting engine is designed this way to allow for incremental updates (which is critical for performance with large files). 突出显示引擎的设计方式允许进行增量更新(这对于大文件的性能至关重要)。 If you change text in a line, only that single line is updated. 如果更改一行中的文本,则仅更新该一行。 If this update leads to a change in the span stack at the end of the line, the following lines are updated as well (but only if they are in the visible portion of the text area - otherwise their update is delayed until the user scrolls down). 如果此更新导致行尾的跨度堆栈发生更改,则以下行也会被更新(但仅当它们位于文本区域的可见部分时,否则它们的更新将延迟到用户向下滚动时) )。

A possible solution is to implement your own IVisualLineTransformer instead of using the syntax highlighting engine. 一种可能的解决方案是实现自己的IVisualLineTransformer而不使用语法突出显示引擎。 Here is an example implementation that highlights all occurrences of the word 'AvalonEdit': 这是一个示例实现,突出显示单词“ AvalonEdit”的所有出现:

public class ColorizeAvalonEdit : DocumentColorizingTransformer
{
    protected override void ColorizeLine(DocumentLine line)
    {
        int lineStartOffset = line.Offset;
        string text = CurrentContext.Document.GetText(line);
        int start = 0;
        int index;
        while ((index = text.IndexOf("AvalonEdit", start, StringComparison.Ordinal)) >= 0) {
            base.ChangeLinePart(
                lineStartOffset + index, // startOffset
                lineStartOffset + index + 10, // endOffset
                (VisualLineElement element) => {
                    // This lambda gets called once for every VisualLineElement
                    // between the specified offsets.
                    Typeface tf = element.TextRunProperties.Typeface;
                    // Replace the typeface with a modified version of
                    // the same typeface
                    element.TextRunProperties.SetTypeface(new Typeface(
                        tf.FontFamily,
                        FontStyles.Italic,
                        FontWeights.Bold,
                        tf.Stretch
                    ));
                });
            start = index + 1; // search for next occurrence
        }
    }
}

// Usage:
textEditor.TextArea.TextView.LineTransformers.Add(new ColorizeAvalonEdit());

尝试将您的开始模式替换为:

\{(?=[^{}$]*\$[^{}$\s]+\$[^{}$]*\})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM