简体   繁体   English

语法仅在一行中突出显示C#中的richtextbox

[英]Syntax highlighting richtextbox in C# on a single line only

I'm working on my own syntax highlighter using a Richtextbox. 我正在使用Richtextbox开发自己的语法荧光笔。 It's already working, but I've noticed that the typing slows down a lot when there's to many lines of code. 它已经在工作,但是我注意到,当有许多行代码时,键入速度会大大降低。 This is because my syntax highlight function is coloring all the words in the entire Richtextbox on every change made to it. 这是因为我的语法高亮功能是对每次Richtextbox中的所有更改进行着色。 Here's a minimal example of the function to see how it works: 下面是该函数的最小示例,以了解其工作原理:

private void colorCode()
{
    // getting keywords/functions
    string keywords = @"\b(class|function)\b";
    MatchCollection keywordMatches = Regex.Matches(codeBox.Text, keywords);

    // saving the original caret position + forecolor
    int originalIndex = codeBox.SelectionStart;
    int originalLength = codeBox.SelectionLength;
    Color originalColor = Color.Black

    // focuses a label before highlighting (avoids blinking)
    titleLabel.Focus();;

    // removes any previous highlighting (so modified words won't remain highlighted)
    codeBox.SelectionStart = 0;
    codeBox.SelectionLength = codeBox.Text.Length;
    codeBox.SelectionColor = originalColor;

    foreach (Match m in keywordMatches)
    {
        codeBox.SelectionStart = m.Index;
        codeBox.SelectionLength = m.Length;
        codeBox.SelectionColor = Color.Blue;
    }

    // restoring the original colors, for further writing
    codeBox.SelectionStart = originalIndex;
    codeBox.SelectionLength = originalLength;
    codeBox.SelectionColor = originalColor;

    // giving back the focus
    codeBox.Focus();
}

To solve the problem, I want to write a function that doesn't change the entire Richtextbox, but just the line of the cursor position instead. 为了解决该问题,我想编写一个不会更改整个Richtextbox的函数,而只是更改光标位置的行。 I realise this will still cause the same issue on minified code, but that's not a problem for me. 我意识到这仍然会在最小化代码上引起相同的问题,但这对我来说不是问题。 The problem is, I can't seem to get it working. 问题是,我似乎无法正常工作。 This is what I've got so far: 到目前为止,这是我得到的:

void changeLine(RichTextBox RTB, int line, Color clr, int curPos){
    string testWords = @"\b(test1|test2)\b";
    MatchCollection testwordMatches = Regex.Matches(RTB.Lines[line], testWords);

    foreach (Match m in testwordMatches)
    {
        //RTB.SelectionStart = m.Index;
        //RTB.SelectionLength = m.Length;
        RTB.SelectionColor = Color.Blue;
    }

    RTB.SelectionStart = curPos;
    RTB.SelectionColor = Color.Black;
}

The problem is that it does the coloring when a word in testWords is found, but it colors the entire line instead of just the word. 问题是,当在testWords中找到一个单词时,它会进行着色,但是会为整个行着色,而不仅仅是单词。 This is because I can't figure out a way of doing the selections right. 这是因为我无法找出正确选择的方法。 So I'm hoping you guys can help me out with this. 所以我希望你们可以帮助我。

Edit: 编辑:

I'd like to add that I did thought about other solutions, like putting the lines in a List, or using a Stringbuilder. 我想补充一点,我确实考虑过其他解决方案,例如将行放入列表中或使用Stringbuilder。 But those will turn the lines into strings and don't allow me to do color formatting like the Richtextbox does. 但是这些会将行变成字符串,并且不允许我像Richtextbox那样进行颜色格式化。

Well, you obviously need language lexer and parser. 好吧,您显然需要语言词法分析器和解析器。 This task is not solvable by using Regex. 使用正则表达式无法解决此任务。 It's just doesn't capable to accomplish this because of some fundamental grammar rules (or "power levels" of grammars) (read about Thomsky hierarchy of grammars). 由于某些基本的语法规则(或语法的“功率等级”)(只是了解Thomsky语法层次结构),它无法完成此任务。

What you need is to use some grammar toolkit. 您需要使用一些语法工具包。 For example ANTLR4 provide grammar lexer/parser generator and set of already predefined grammars. 例如,ANTLR4提供语法词法分析器/解析器生成器和一组预定义的语法。

For example, you can find a lot of user-written grammars in here (including latest C# syntax): https://github.com/antlr/grammars-v4 例如,您可以在此处找到很多用户编写的语法(包括最新的C#语法): https : //github.com/antlr/grammars-v4

Then just generate parser/lexer by it and feed it your string. 然后仅通过它生成解析器/词法分析器,并将其作为字符串输入。 It will output full hierarchy with indexes and lengths of each token, and you can colorize them without jumping across entire rich box. 它将输出具有每个令牌的索引和长度的完整层次结构,您可以为它们着色而无需跳过整个丰富框。

Also, consider to use some timeout between user input, so you don't colorize your output every symbol (just save color from previous token, and use it for some time, until you recolorize output, then refresh). 另外,请考虑在用户输入之间使用一些超时,这样就不会为每个符号着色输出(只需保存先前标记的颜色,并使用一段时间,直到重新着色输出然后刷新即可)。 This way it will go as smoothly as it is in Visual Studio. 这样,它将像在Visual Studio中一样顺利进行。

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

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