【问题标题】:Text editor theory [closed]文本编辑器理论
【发布时间】:2011-03-11 07:29:12
【问题描述】:

因为我总是对现有的编辑器不满意,所以我一直想开始的一个项目是我自己的文本编辑器。然而,进行文本编辑是一项严肃的工作。

除了分析现有文本编辑器的源代码之外,是否有任何关于此主题的书籍或其他资源(如学术工作)?我特别感兴趣的是教如何处理内存和如何管理文本插入的东西(如果你有一个 100 MB 的文件并想在 x 位置添加一个字符,你不能只是 @ 987654322@巨大的文本块...)。

【问题讨论】:

  • 文本编辑器有什么用?桌面、网络、....控制台?
  • 不确定一般的问题,但是对于插入的具体问题,很多编辑把文字当成绳子处理:en.wikipedia.org/wiki/Rope_%28computer_science%29
  • @Bart:一个简单的无格式文本编辑器,但是我猜文本编辑器的基本规则即使对于富文本文字处理器也很好。我的目标是非基于 Web 的编辑器,但是我再次认为,即使对于基于 Web 的编辑器和任何语言(尽管我会用 C++ 编写代码),相同的核心理论也是有效的。
  • Kernighan 和 Plauger 所著的古老的“Pascal 软件工具”用一种既没有真正的字符串也没有指针的语言实现了ed 编辑器。它包含对任何文本编辑器背后的设计注意事项的一个很好的概述。
  • @msw:谢谢,请考虑将其添加为回复,以便对其进行投票!

标签: data-structures editor text-editor theory


【解决方案1】:

一种仍然有效的旧方法称为间隙缓冲区。基本思想是将文本放入缓冲区,但不是将它们全部放在一个块中,而是在光标处创建一个“间隙”,将光标之前的所有文本放在缓冲区的开头,所有的缓冲区末尾光标后的文本。大多数插入发生在光标处,您可以在不移动任何内容的情况下执行此操作(直到或除非您溢出缓冲区)。当用户移动光标时,您将相应的文本从拆分的一侧移动到另一侧。

给定典型的控件(光标向左、向右、向上、向下、向上翻页、向下翻页),您通常处理的最大移动是一次一页,这通常很容易处理比键盘重复快很多。当然,如果你有一个非常大的文件和一个“goto line”命令,或者按照这个顺序,它可能会慢一点。如果你要做很多这样的事情,毫无疑问有更好的结构可以使用......

【讨论】:

  • 它实际上被称为“间隙缓冲区”。快速搜索后找不到任何对“拆分缓冲区”的引用。
  • @sh1ftst0rm:哎呀——我又一次知道我不应该相信我的记忆。现在,只要我的记忆力足够好,我就能记住它……:-)
  • Crowley 的论文中称为“The Gap Method”,第九页底部提到它也可以称为“split buffer 方法”。 (c.f.cs.unm.edu/~crowley/papers/sds.pdf)
【解决方案2】:

以下是微软“专业人士”的做法:

MS Word 使用块表数据结构。字符位置的升序数组与包含指向原始文件(文件加载时加载的文本)或新添加字符的仅追加缓冲区的指针的较大结构数组并行维护。

在 Windows 中随处使用的 EDIT 控件根本不使用数据结构。记事本仅使用多行 EDIT 控件。用堆查看器检查一下。 EDIT 控件只维护一个换行符和制表位的缓冲区。

如果您要在 Windows 中创建一个简单的非格式化文本编辑器,您可以轻松地将 EDIT 控件子类化以添加功能。

【讨论】:

    【解决方案3】:

    This paper 比较了许多可用于文本编辑器的数据结构,包括这里已经提到的一些(例如,间隙缓冲区)以及其他一些(例如,片段表)。这篇文章很旧,但我相信它仍然涵盖了所有主要选择,并且在性能、复杂性和空间开销方面很好地比较了它们。

    我知道 Stack Overflow 的答案不应该只是链接,但这仍然是我为所请求的信息找到的最佳信息来源,在这里总结答案太长了。如果链接失效,请搜索新墨西哥大学的 Charles Crowley 的“Data Structures for Text Sequences”。

    【讨论】:

      【解决方案4】:

      这里有一个很好的教程,涵盖了更现代背景下的许多相关主题:

      此问题的其他答案包括间隙缓冲区。

      另一个现代报道是对 AvalonEdit 的描述

      和更多细节来自:

      书中有大量的细节/内容(关于 SharpDevelop):

      【讨论】:

      • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会失效。
      • 虽然我很欣赏链接确实会过时,但该问题要求提供需要许多解释页面的信息,更多信息可以明智地包含在 Stack Overflow 答案中。我给出许多选项的部分原因是为了涵盖一些逐渐消失的场景。但是,Wayback Machine 通常也可以提供帮助 (archive.org/web)
      【解决方案5】:

      The Craft of Text Editing 由 Craig Finseth 撰写,基于他的硕士论文,涵盖了这些主题。它在网络上是免费的。 OTOH,它已经很老了,并且没有提到一些像绳索这样的想法,这些想法在过去的微型计算机上不太实用。

      【讨论】:

        【解决方案6】:

        Scintilla 组件使用拆分缓冲区,其理论在其Scintilla and SciTE Related Sites 页面中链接的文本中进行了解释。
        链接页面是Data Structures in a Bit-Mapped Text Editor
        拆分缓冲区证明它即使处理兆字节文件也能很好地工作。使用二级结构(例如,行首列表)也有帮助。

        【讨论】:

          【解决方案7】:

          建议按要求回答:

          Kernighan 和 Plauger 的古董“Software Tools in Pascal”用一种既没有真正的字符串也没有指针的语言实现了ed 编辑器。它包含对任何文本编辑器背后的设计注意事项的一个很好的概述。

          【讨论】:

          • 可能在此期间理论有所改进,但绝对值得一读!
          【解决方案8】:

          看看 Rob Pike 对他的Sam text editor 的描述。请务必浏览高级概述和命令语言。他将在本文后面介绍解析、内存管理和数据结构。

          另外,看看 Russ Cox 的simple regular expression implementation。它很容易理解,并且可能会在现有的正则表达式库之外打开一些大门。

          【讨论】:

            【解决方案9】:

            好吧,如果您知道通常人们的插入点相对较少,您可以将一组指针保存到原始文本缓冲区中,当用户尝试在其中插入时,您可以通过生成另一个指针来“拆分”缓冲区到缓冲区的其余部分,使第一个指针的长度停止在插入点处,并为要插入的文本添加第三个指针,有点像:

            long original text la la la
            ^                *^
            |                 2nd part
            1st part
            

            星号指向一个新的文本缓冲区,您开始添加要插入的文本。

            当您渲染(或一般解析)您的文本文件时,您会遍历指针数组,然后在每个缓冲区上执行您的工作。当然,如果缓冲区足够小,您可以跳过添加新缓冲区的部分,但这只是启发式方法,请尝试每一个,然后感受哪个效果最好。

            您还可以考虑将加载时的文本文件拆分为多个缓冲区,例如每 1MB 左右,因为如果您将文件加载到单个缓冲区中,您将需要为插入的文本创建一个新缓冲区,因为它的大小。同样,这是一种启发式优化。

            【讨论】:

            • 将文本分成块实际上是我的第一个想法。我考虑过使用内存页面大小的块来避免内存碎片。然而这似乎太微不足道了。没有更强大的方法来处理大型文本移动等情况吗?
            • 如果你这样做,你不需要移动任何东西。这就是您要避免的事情,在内存中移动内容(当然,除非用户将文本拖到另一个位置,但这种情况很少见)。对于正常插入,您只需将文本添加到缓冲区的末尾。
            【解决方案10】:

            多年来,我编写了许多不同的文本编辑器。当然,最简单的方法是管理一长串字符,在其中复制所有内容以插入任何字符。我使用的其他技术包括:

            • 将文本文件表示为文本行的双向链表。
            • 构造一个树状数据结构(有时称为"rope"),它以实心字符串开始,但能够拆分、插入和删除文本块,而无需移动所有其余部分周围的文字。

            许多旧 Borland 示例书籍都使用文本编辑器作为教程示例。您偶尔仍然可以在旧书店几乎免费找到这些副本。

            【讨论】:

              【解决方案11】:

              如何管理文本插入(如果你有一个 100 MB 的文件并想在 x 位置添加一个字符,你不能只删除巨大的文本块......)。

              使文本文件成为一个链表,其中每一行都是一个条目。

              【讨论】:

              • 这很好,除非你有很长的行:P
              • @Earlz:然后拆分这些行,使每一行都有自己的链表、树或其他适当的集合。
              • 不,如果您有 2 MB 的文本行...甚至是没有结束行的单个大文本行...
              • @Lorenzo 查看我之前的评论
              • 实际上,Software Tools(或者可能是 In Pascal 版本)谈到了这个想法,并指出他们尝试过但发现它不可行。
              猜你喜欢
              • 2011-08-05
              • 1970-01-01
              • 1970-01-01
              • 2011-06-18
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多