编辑器核心缓冲区类型和语法突出显示

时间:2009-02-10 11:37:47

标签: c++ vim editor syntax-highlighting buffer

我一直在考虑将编辑器核心功能明智地与vim兼容,类似于yzis。

最大的问题是要使用的缓冲区类型。

要求是:

  • 可以实现快速语法高亮,正则表达式。
  • 在单个文件中实现多个语法突出显示的可能性。类似于文字范围
  • 删除插页上的正确移动标记。这样他们就可以适当调整列。与vim不同。
  • 处理并突出显示至少100 MB的文件,没有太大的问题和内存开销。

可能的缓冲区类型:

  • gap buffers
  • 基于行的编辑

我读到间隙缓冲区在长时间运行时会导致相当大的内存碎片。 emacs语法高亮引擎也非常慢。(不知道为什么,可能与缓冲区类型没有关系)

所以问题:

  1. 哪种缓冲区类型最适合快速编程编辑器?
  2. 什么是快速/完整的正则表达式引擎? (也许这包括下一点)。 TextMate使用oniguruma,这是明智的选择吗?
  3. 什么是快速语法高亮引擎?
  4. 关于标记和语法突出显示。 emacs覆盖如何工作,他们会帮忙吗?
  5. 谢谢, 礼

2 个答案:

答案 0 :(得分:4)

一个好的文本编辑器应该对程序员可能做的各种工作很有用,包括打开有时可能是几千兆字节的文件。因此,我不建议将所有内容缓存在RAM中的思维方式。

我建议设置一个代表文件的切片搜索树,其中一个切片可能是:

  1. 对磁盘上实际文件中的字节范围的引用,或
  2. 对已编辑的“页面”的引用。
  3. 当您打开文件时,首先将单个项目插入树中,这只是表示整个文件的范围,例如:对于10-MiB文件:

    std::map<size_t, slice_info> slices;
    slices[0].size = 10*1024*1024;
    

    当用户编辑文件时,在编辑点周围创建一个合理大小的“页面”,例如4 KiB。树在那一点被拼接。在该示例中,编辑点位于5 MiB:

    size_t const PAGE_SIZE = 4*1024;
    slices[0].size = 5*1024*1024;
    slices[5*1024*1024].size = PAGE_SIZE;
    slices[5*1024*1024].buffer = create_buffer(file, 5*1024*1024, PAGE_SIZE);
    slices[5*1024*1024 + PAGE_SIZE].size = 5*1024*1024 - PAGE_SIZE
    

    您可以将内存映射文件用于只读缓冲区(源文件)和复制的可编辑缓冲区(后者将放在临时目录中)。如果编辑器崩溃,这也允许恢复。

    使用固定大小的页面将大大减少内存堆的碎片,因为所有块都具有相同的大小,插入文本永远不需要在您之前移动超过4 KiB的数据。

    这是一个简化的描述,给出了一般的想法,而没有涉及太多的细节。一个真正的实现很可能需要更复杂,例如允许页面中的可变数量的数据来处理溢出的页面,并将许多小切片合并在一起,以便在大文件中运行正则表达式替换不会创建太多的小缓冲区。可能需要同时对树中应该具有的切片数量进行限制,但关键是当您开始插入某处时,应该确保使用的切片不是太大。< / p>

    对于正则表达式,只要整个编辑器在运行时没有挂起,我认为性能不是很大的问题。试试Boost.Regex,它很可能足够快,满足您的需求,而且它也足以插入您需要的任何缓冲策略。

    这同样适用于语法高亮,如果你在后台运行它,它在打字时不会打扰用户这么多。您可以在此处使用切片方法获益:

    • 每个切片都可以有一个可以在编辑操作期间锁定的互斥锁,允许语法突出显示或“intellisense”类型分析在后台线程中运行。
    • 您可以存储语法高亮引擎的状态,这样无论何时在切片中进行编辑,您都可以从该切片的开头重新开始语法高亮显示,而不是从文件的开头重新开始。

    我不知道有任何独立的语法突出显示引擎,但它们通常基于正则表达式替换(参见例如vim中的语法突出显示文件)。

答案 1 :(得分:0)

您可以使用Scintilla类。您的视图可以从Scintilla View派生,它提供语法突出显示。