Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
异步运行Emacs中的命令,但增量显示输出_Emacs_Elisp - Fatal编程技术网

异步运行Emacs中的命令,但增量显示输出

异步运行Emacs中的命令,但增量显示输出,emacs,elisp,Emacs,Elisp,我有一个实用功能: (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" comma

我有一个实用功能:

(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)))
这允许我执行类似于
(在缓冲区“ls/”(get buffer create“*my output*”)
)的操作。但是,它不太适合慢速命令。如果我调用一系列慢速命令,我直到最后才得到任何输出:

(let ((buf (get-buffer-create "*my-output")))
  (execute-in-buffer "sleep 10" buf)
  (execute-in-buffer "ls /" buf))
我希望能够同步调用,因此下一个命令只能在前一个命令完成后运行。但是,我希望在命令运行时看到它们的输出。我将如何做到这一点


(示例代码只是为了展示,我很乐意放弃它,转而支持其他内容。)

使用同步进程

如果您想坚持使用同步进程(例如使用
调用进程
),则需要在每次调用
执行缓冲区
后调用
(重新显示)
,以更新显示并显示输出(有关更多详细信息,请参阅)。但是,在进程终止之前,每个命令的输出都将不可见,并且在外部进程运行时,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 /")
这对我很有用:

(async-shell-command "echo 1; sleep 10; echo 2; sleep 10; ls /" "*abcd*")

这可以根据您的需要进行调整?

谢谢,这将大大改善问题。但是,理想情况下,我希望看到命令的输出实时进行,而不是等待命令终止。我添加了一个基于异步进程的解决方案,这将解决此问题。请参阅我编辑过的回答,也谢谢您:我想我要走了要在Ooh中使用这种技术,这是非常接近的。在我最初的
在缓冲区中执行
,我还显示了我正在运行的命令,然后再运行它们。除了
(异步shell命令“echo\”echo 1\“echo 1;)之外,我看不到任何简洁的方法来实现这一点
等。如果这是供个人使用的——相对于产品化功能——
(异步shell命令“set-xv;echo 1;sleep 10;echo 2;sleep 10;ls/”“*abcd*”)
可能对您有用。您不应该将
与当前缓冲区一起使用
设置缓冲区
而不是
切换到缓冲区
?这是出于设计——我希望我的输出缓冲区可见。在其他情况下,我肯定会将
与当前缓冲区一起使用
设置缓冲区
。在这种情况下,您需要使用
的et缓冲区
,然后
显示缓冲区