10

我正在编写一个 Emacs 次要模式,其中包含一些调用 shell 命令的 Emacs 命令。我正在使用以下代码:

    (let ((output (get-buffer-create "*Foo Output*")))
      (start-process "Foo Process" output argv0)
      (display-buffer output))

我希望包含这些 shell 命令的缓冲区在任何时候插入输出时自动滚动到底部,或者至少在命令完成执行时自动滚动到底部。我怎样才能做到这一点?

4

1 回答 1

9

您可以通过使用流程过滤器功能来做到这一点。

进程过滤器函数是从相关进程接收标准输出的函数。如果一个进程有一个过滤器,那么该进程的所有输出都会传递给过滤器。只有在没有过滤器的情况下,进程缓冲区才直接用于进程的输出。

[...]

许多过滤器函数有时(或总是)将输出插入进程的缓冲区,在没有过滤器时模仿 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)))))

用于set-process-filter将该过滤器功能分配给您的流程。

(set-process-filter proc 'my-insertion-filter)

或者,如果仅在进程终止后跳转到缓冲区的末尾就足够了,您可能需要使用sentinel

进程哨兵是一个函数,每当相关进程因任何原因改变状态时都会调用该函数,包括终止、停止或继续进程的信号(无论是由 Emacs 发送还是由进程自己的操作引起)。如果进程退出,也会调用进程哨兵。

(defun my-sentinel (proc event)
  (when (buffer-live-p (process-buffer proc))
    (with-current-buffer (process-buffer proc)
      (end-of-buffer))))

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

用于set-process-sentinel将该哨兵分配给您的进程。

(set-process-sentinel proc 'my-sentinel)
于 2013-05-20T03:01:12.940 回答