You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义Lexer下ScintillaNET代码折叠失效的解决求助(.NET7 WinForms C#)

基于{}实现Scintilla自定义Lexer的代码折叠方案
  • 启用折叠基础配置
    先开启Scintilla控件的折叠相关核心属性:

    // 启用折叠功能
    scintilla1.Folding.Enabled = true;
    // 设置折叠标记样式(可选,使用树状箭头样式)
    scintilla1.Folding.MarkerStyle = MarkerStyle.BoxPlusMinus;
    // 预留折叠边栏宽度
    scintilla1.Margins[2].Width = 20;
    
  • 在自定义Lexer中计算{}的折叠层级
    自定义Lexer需要逐行扫描文本,基于{}的嵌套关系维护折叠层级,并设置每行的折叠标记:

    1. 初始化currentLevel变量记录当前折叠深度,初始值为0。
    2. 遍历每一行文本,统计该行中{和}的数量。
    3. 先减少闭合括号对应的层级(避免层级为负),再设置当前行的折叠层级:
      • 包含{的行标记为折叠头部(可展开/折叠)
      • 包含}的行标记为折叠结束
    4. 最后增加开启括号对应的层级,用于下一行计算。
      示例代码:
    private void UpdateFoldingLevels(Scintilla scintilla)
    {
        int currentLevel = 0;
        for (int line = 0; line < scintilla.Lines.Count; line++)
        {
            var lineText = scintilla.Lines[line].Text;
            int openCount = lineText.Count(c => c == '{');
            int closeCount = lineText.Count(c => c == '}');
            
            // 先处理闭合括号,修正当前层级
            currentLevel -= closeCount;
            if (currentLevel < 0) currentLevel = 0;
            
            // 设置当前行的折叠层级
            int level = currentLevel;
            if (openCount > 0)
            {
                level |= (int)SC_FOLDLEVEL.HEADERFLAG; // 标记为可折叠头部
            }
            level |= (int)SC_FOLDLEVEL.NUMBERMASK; // 应用层级掩码
            
            scintilla.Folding.SetLevel(line, level);
            
            // 更新层级用于下一行
            currentLevel += openCount;
        }
    }
    
  • 绑定文本变更事件实现实时折叠
    为了在用户编辑文本时自动更新折叠状态,绑定TextChanged事件,触发层级重新计算:

    scintilla1.TextChanged += (sender, e) => UpdateFoldingLevels(scintilla1);
    
  • 额外注意点

    • 如果你的语法中有字符串、注释,需要在扫描时跳过这些区域,避免把字符串/注释内的{}算入折叠层级。
    • 确保层级计算顺序:先处理}再处理{,避免单行同时包含两种括号时出现折叠逻辑错误。

内容的提问来源于stack exchange,提问作者Filipe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 04:32:32