下等工序产生长线时,如何防止减速?


14

我将Emacs与Geiser结合使用以破解一些Scheme代码。当我在REPL中玩耍时,有时我会评估会产生大量输出的表达式,通常都是一行。

例如,我只是玩SRFI-41(流),并从一个大文件创建了一个字符流。然后我强制了流,Geiser将文件的全部内容作为字符流倒入了我的缓冲区。几乎立即,随着越来越多的字符附加到输出行,Emacs停顿了下来,无论我持续按下多长时间C-g还是C-c C-c无法使Emacs(或Geiser)停止。

这打断了我的整个Emacs会话,因为Emacs现在完全忽略了我的输入,认为它需要优先考虑将这一庞大的字符流全部打印到无响应的Geiser REPL缓冲区中。

有什么我可以保护我的Emacs会话免受破坏性好奇心的吗?(为什么在显示长的行时Emacs为什么会变得这么慢?)我可以设置长行的限制并告诉Emacs根本不尝试显示很长的行是可以的吗?



2
好吧,我的问题不是关于显示长行本身。我想知道如何一开始就避免这种情况(Emacs从劣等过程中读取该行,而不是从我可以修复的文件中读取);这是关于如何避免因Emacs对单个动态缓冲区的执着而导致的Emacs会话丢失。
rekado 2014年

“好吧,我的问题不是关于显示长行”,那么也许您应该更改标题。也许您想过滤劣质处理输出并在一定数量的字符后添加新行?
保姆

确实,这与行长无关。yesansi-term例如具有类似的(但不是那个可怕的)影响。确实,仅仅是文本的数量使emacs暂停了。
PythonNut 2014年

文本在缓冲区中的插入速度非常快,正是重新显示操作使它的显示速度比实际速度慢。老实说,yes在VTE终端仿真器中运行会使我的所有CPU内核最大化,因此我不以它为例。
wasamasa 2014年

Answers:


12

正如评论中已经回答的那样,Emacs重新显示长行变得非常缓慢,这是一个众所周知的问题。修复它会非常好,但是需要大量考虑才能正确实现。我有一个如何根据本文档 6.3节实现的想法 (基本上,将视线信息存储在当前缓冲区中,并在插入空白,显示属性,窗口更改等方面对其进行更新,然后在重新显示代码,以避免一直扫描),但对C内部结构并不熟悉,无法将其提取出来。

虽然有解决方法。最明显的是调整与显示相关的参数(例如,在图形Emacs实例中启用视线截断,使用非图形Emacs自动执行该操作,禁用Bidi功能等)并预处理文件内容。重新读入。不太明显的一种是自动对文件进行后处理,方法是通过实际截断它们的行或添加文本属性来使这些行看起来比实际的短。为了将其转化为更有趣的答案,我将介绍一个仅适用于comint-derived模式的前一个选项的丑陋技巧:

(defun my-comint-shorten-long-lines (text)
  (let* ((regexp "^\\(.\\{80\\}\\).*?$")
         (shortened-text (replace-regexp-in-string regexp "\\1" text)))
    (if (string= shortened-text text)
        text
      (propertize shortened-text 'help-echo text))))

(add-hook 'comint-preoutput-filter-functions 'my-comint-shorten-long-lines)

这定义my-comint-shorten-long-lines了一个函数,该函数采用可能由多行组成的字符串,并使用正则表达式的功能将长度在80个字符或更多字符中的任何行替换为缩短的版本,该版本在将鼠标悬停在其上时会显示原始文本。当用作钩子时, comint-preoutput-filter-functions它将comint在显示所有输出之前对其进行过滤。

但是,这种破解方法存在相当严重的缺陷。在具有基本字体化功能的模式下(如M-x ielm),它将很高兴地切断字符串的一部分行,并将所有内容字体化,直到下一个引号是字符串!那不是我们想要的,可以通过更多的正则表达式来解决(但可能会破坏像Python这样的语言的REPL内部)。当我们讨论它时,我们也要突出显示缩短的输出:

(defun my-comint-shorten-long-lines (text)
  (let* ((regexp "^\\(.\\{80\\}\\).*?\\(\"?\\)$")
         (shortened-text (replace-regexp-in-string regexp "\\1\\2" text)))
    (if (string= shortened-text text)
        text
      (propertize shortened-text 'font-lock-face 'shadow 'help-echo text))))

(add-hook 'comint-preoutput-filter-functions 'my-comint-shorten-long-lines)

更好一点,但仍然很丑。悬停在诸如find /in 之类的输出上M-x shell并不吸引人(理想情况下,我们只希望显示未缩短的行,而不是全部输出),字符串检测充其量是基本的,并且可以用省略号而不是将所有内容都字体化来更好地表示截断。最重要的是,它甚至不能保证输入的文本不会变成批处理。所有这些都要求在临时缓冲区中执行处理步骤,但是将留给读者作为练习(或者由作者作为潜在的博客文章)。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.