我有一个效用函数:
(defun execute-in-buffer (command-with-args buffer)
"Execute a string COMMAND-WITH-ARGS representing a shell command with arguments,
inserting the results in BUFFER."
(switch-to-buffer buffer)
(insert (format ">>> %s\n" command-with-args))
(let* ((command-args-list (s-split " " command-with-args))
(command (car command-args-list))
(args (cdr command-args-list)))
(apply 'call-process command nil buffer t args)))
这允许我做类似
(execute-in-buffer "ls /" (get-buffer-create "*my-output*")
的事情。但是,它不太适合慢速命令。如果我调用一系列缓慢的命令,直到最后我才得到任何输出:(let ((buf (get-buffer-create "*my-output")))
(execute-in-buffer "sleep 10" buf)
(execute-in-buffer "ls /" buf))
我希望能够同步调用,所以下一个命令只在上一个命令完成后运行。但是,我想在命令运行时查看它们的输出。我该怎么做?
(示例代码仅用于展示,我很高兴放弃它以支持其他东西。)
最佳答案
使用同步进程
如果您想坚持同步进程(例如使用 call-process
),您需要在每次调用 (redisplay)
后调用 execute-in-buffer
以更新显示和可见输出(有关更多详细信息,另请参阅 this question )。但是,每个命令的输出在进程终止之前是不可见的,并且 emacs 将在外部进程运行时挂起。
使用异步进程
使用异步进程有点复杂,但避免了在命令运行时挂起 Emacs,这也解决了重新显示的问题。这里棘手的部分是顺序链接所有命令。这是一个应该可以解决问题的elisp:
(defun execute-commands (buffer &rest commands)
"Execute a list of shell commands sequentially"
(with-current-buffer buffer
(set (make-local-variable 'commands-list) commands)
(start-next-command)))
(defun start-next-command ()
"Run the first command in the list"
(if (null commands-list)
(insert "\nDone.")
(let ((command (car commands-list)))
(setq commands-list (cdr commands-list))
(insert (format ">>> %s\n" command))
(let ((process (start-process-shell-command command (current-buffer) command)))
(set-process-sentinel process 'sentinel)))))
(defun sentinel (p e)
"After a process exited, call `start-next-command' again"
(let ((buffer (process-buffer p)))
(when (not (null buffer))
(with-current-buffer buffer
;(insert (format "Command `%s' %s" p e) )
(start-next-command)))))
;; Example use
(with-current-buffer (get-buffer-create "*output*") (erase-buffer))
(execute-commands "*output*"
"echo 1"
"sleep 1"
"echo 2; sleep 1; echo 3"
"ls /")
关于emacs - 在 Emacs 中异步运行命令,但以增量方式显示输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16815598/