我有一个实用功能:
(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)))
Run Code Online (Sandbox Code Playgroud)
这让我可以做的事情(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))
Run Code Online (Sandbox Code Playgroud)
我希望能够同步调用,因此下一个命令仅在前一个命令完成后运行.但是,我希望在运行时看到命令的输出.我该怎么做?
(示例代码仅用于展示,我很乐意将其放弃以支持其他内容.)
使用同步过程
如果您想坚持使用同步进程(例如使用call-process),则需要(redisplay)在每次调用后调用以execute-in-buffer更新显示并使输出可见(有关更多详细信息,请参阅此问题).但是,在进程终止之前,每个命令的输出都不可见,并且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 /")
Run Code Online (Sandbox Code Playgroud)
这对我有用:
(async-shell-command "echo 1; sleep 10; echo 2; sleep 10; ls /" "*abcd*")
Run Code Online (Sandbox Code Playgroud)
这可以适应你需要的吗?