如何使Emacs shell命令输出缓冲区始终跟在底部?

9 emacs elisp

我正在编写一个Emacs次要模式,它有一些调用shell命令的Emacs命令.我正在使用以下代码:

    (let ((output (get-buffer-create "*Foo Output*")))
      (start-process "Foo Process" output argv0)
      (display-buffer output))
Run Code Online (Sandbox Code Playgroud)

我想包含那些shell命令的缓冲区在插入输出时自动滚动到底部,或者至少在命令执行完毕时自动滚动到底部.我怎样才能做到这一点?

Tho*_*mas 8

您可以使用进程筛选器功能执行此操作.

过程过滤器功能是接收来自关联过程的标准输出的功能.如果进程具有过滤器,则该进程的所有输出都将传递给过滤器.仅当没有过滤器时,过程缓冲区才直接用于进程的输出.

[...]

许多过滤器函数有时(或总是)将输出插入进程的缓冲区,在没有过滤器时模仿Emacs的操作.

start-process返回一个进程对象,它代表Lisp中的新子进程,你可以将它存储在一个变量中proc.您可以编写一个简单的过滤器函数,只将过程的输出插入到关联的输出缓冲区中,从而移动point到缓冲区的末尾.

(defun my-insertion-filter (proc string)
  (when (buffer-live-p (process-buffer proc))
    (with-current-buffer (process-buffer proc)
      ;; Insert the text, advancing the process marker.
      (goto-char (process-mark proc))
      (insert string)
      (set-marker (process-mark proc) (point)))))
Run Code Online (Sandbox Code Playgroud)

使用set-process-filter该过滤功能分配给你的进程.

(set-process-filter proc 'my-insertion-filter)
Run Code Online (Sandbox Code Playgroud)

或者,如果只有在进程终止后才跳转到缓冲区的末尾就足够了,您可能需要使用标记.

进程sentinel是一个函数,只要关联进程因任何原因改变状态,就会调用该函数,包括终止,停止或继续进程的信号(由Emacs发送或由进程自己的操作引起).如果进程退出,也会调用进程sentinel.

(defun my-sentinel (proc event)
  (when (buffer-live-p (process-buffer proc))
    (with-current-buffer (process-buffer proc)
      (end-of-buffer))))
Run Code Online (Sandbox Code Playgroud)

(请注意,每次调用此函数时,此函数都会滚动到进程缓冲区的末尾,这可能不仅发生在进程结束时.如果您真的只希望它在进程终止时执行此操作,请检查event字符串是否为字符串"finished\n".)

使用set-process-sentinel该定点分配给你的进程.

(set-process-sentinel proc 'my-sentinel)
Run Code Online (Sandbox Code Playgroud)