我正在编写一个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命令的缓冲区在插入输出时自动滚动到底部,或者至少在命令执行完毕时自动滚动到底部.我怎样才能做到这一点?
您可以使用进程筛选器功能执行此操作.
过程过滤器功能是接收来自关联过程的标准输出的功能.如果进程具有过滤器,则该进程的所有输出都将传递给过滤器.仅当没有过滤器时,过程缓冲区才直接用于进程的输出.
[...]
许多过滤器函数有时(或总是)将输出插入进程的缓冲区,在没有过滤器时模仿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)