如果我在emacs lisp中异步执行shell命令,如下所示:
(shell-command“mycommand&”)
有没有办法在继续之前等待命令生成输出?对于我当前的应用程序,可能需要等到命令生成任何输出,但理想情况下我想捕获输出以进行其他处理。这可能吗?
答案 0 :(得分:4)
也许您需要注册一个进程过滤器来为您提供所需的回调时间?请参阅37.9 Receiving Output from Processes in the Elisp manual(我在Emacs 22.3的副本中看到了这一点。)
以下是获取第一个进程输出并将其存储到“关联缓冲区”时运行回调的示例。将其复制到*scratch*
缓冲区并eval-region
,但请确保拆分窗口并显示*Messages*
缓冲区,以便您可以看到正在发生的事情。
;; this is emacs lisp (and a comment line)
(defvar my-callback-got-some-already nil)
(defun my-callback ()
(message "callback ran at %s" (current-time-string)))
(defun my-filter-waits-for-first-time-input (proc string)
(unless my-callback-got-some-already
(setq my-callback-got-some-already t)
;; do your one-time thing
(my-callback))
;; insert into the associated buffer as if no process filter was
;; registered
(with-current-buffer (process-buffer proc)
(let ((moving (= (point) (process-mark proc))))
(save-excursion
;; Insert the text, advancing the process marker.
(goto-char (process-mark proc))
(insert string)
(set-marker (process-mark proc) (point)))
(if moving (goto-char (process-mark proc))))))
(defun async-callback-test-harness ()
(interactive)
(let ((process-handle "async-callback-test")
(associated-process-buffer "*async-callback-test*")
(command "ls")
(busy-loop-var ""))
(setq my-callback-got-some-already nil)
(message "start test %s" (current-time-string))
(start-process process-handle associated-process-buffer command)
;; Supposedly async but Emacs doesn't get the input until
;; "Emacs is waiting" so the following set-process-filter
;; can be registered in time.
;; To prove the point, make emacs busy loop to show that the
;; emacs doesn't drop its input and
;; the callback will get the unskipped input.
(switch-to-buffer associated-process-buffer)
(dotimes (k 2000) ; about two seconds on my machine
(setq busy-loop-var (concat busy-loop-var "busy looping...")))
(message "done busy waiting %s" (current-time-string))
(set-process-filter (get-process process-handle)
'my-filter-waits-for-first-time-input)
nil))
;; run it!
(async-callback-test-harness)
答案 1 :(得分:3)
在输出插入缓冲区后,您应该使用包含函数的comint-output-filter-functions
变量。
例如,你可以这样做:
(add-hook 'comint-output-filter-functions '(lambda (txt) (message "hello")))
N.B。 :从Emacs 23.2开始,你有了新命令async-shell-command
,全局绑定到 M-& 。
这将异步执行您的命令,而不需要&符号。命令的输出发送到缓冲区
*Async Shell Command*
。