【问题标题】:how to process the buffer character-by-character in elisp?如何在elisp中逐字符处理缓冲区?
【发布时间】:2014-07-26 00:26:04
【问题描述】:

我正在尝试编写一些 elisp 来处理当前缓冲区中的每个字符 (我知道这会有点慢,但认为这是最好的方法)。我不想使用正则表达式。如何做到这一点?

函数buffer-string 以字符串形式返回当前缓冲区。使用它可以迭代并引用/设置每个字符。但是,我不知道如何将结果放回缓冲区。
有人可以举个例子,只遍历每个字符,用一些简单的方式改变它,然后把结果放回缓冲区吗?

【问题讨论】:

    标签: emacs elisp


    【解决方案1】:

    使用while 循环和forward-char 遍历缓冲区中的所有字符:

    (goto-char (point-min))
    (while (not (eobp))
      (let* ((current-character (char-after))
             (new-character (do-something current-character)))
        (delete-char 1)
        (insert-char new-character))
      (forward-char 1))
    

    只要未到达缓冲区的末尾 (eobp),循环就会一次向前移动一个字符。

    char-after 为您提供当前位置的角色。 delete-char/insert-char 调用将旧字符替换为新字符,这是处理旧字符的结果。

    要用多个字符(即字符串)替换旧字符,只需将insert-char 替换为insertinsert 将点 放在 新插入的字符之后,因此循环将继续处理之后的下一个 未处理 字符。

    【讨论】:

    • 这假设您总是用单个字符替换当前字符。如果您需要在缓冲区中插入更多文本和/或插入其他位置,那么扩展代码来做到这一点应该不会太难。在我的脑海中,请查看save-excursion,但其他方法可能更有意义,具体取决于您的场景细节。
    • @tripleee 您不需要save-excursion 来插入多个字符。您只需insert,它隐式地将点放在新插入的字符串之后,因此循环将在之后继续处理下一个原始字符。我相应地更新了答案。
    • 对;感谢更新。我留下我的评论,因为它可能仍然对插入缓冲区中的其他地方有用。
    • 只想向 OP 明确指出(如您的解决方案所示)您确实想要使用 buffer-string,处理该字符串,然后替换使用结果字符串缓冲内容。您想在缓冲区中处理文本。在 Emacs 中,缓冲区的使用效率很高,通常使用它们比使用字符串更好。
    【解决方案2】:

    为@lunaryorn 所说的内容添加一些内容 - 可能是解决方案的一部分,具体取决于您的需要,而不仅仅是评论:

    当您逐个字符处理缓冲区时,很常见的情况是您不希望或不需要为 每个 字符做某事,而是需要为其中的特定字符做某事缓冲区。

    在这种情况下,您通常不需要检查每个字符。相反,您可以使用这些函数(请参阅他们的文档了解它们的作用):

    • search-forwardre-search-forward,如果针对特定字符

    • next-single-property-change,如果目标是一个或多个具有特定文本属性的字符(或者可能是next-single-char-property-change,如果涉及覆盖)

    • next-property-change,如果针对一个或多个字符,则任何文本属性更改都是目标(或者可能是next-char-property-change,如果涉及覆盖)

    在这种情况下,您会遍历缓冲区位置(因此,遍历这些位置的字符),就像@lunaryorn 的解决方案一样,但是您使用这样的函数来快速跳过您不感兴趣的字符。这是 比逐个检查每个字符更常见,IMO。但它是否适合您的用例,我不知道。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-02
      • 2016-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多