Как ожидать / захватить вывод команды aysnchronous shell в emacs lisp? - PullRequest
4 голосов
/ 26 августа 2010

Если я выполняю команду оболочки асинхронно в emacs lisp, вот так:

(команда оболочки "mycommand &")

Есть ли способ дождаться, пока команда сгенерирует вывод, прежде чем продолжить? Для моего текущего приложения, вероятно, достаточно подождать, пока команда вообще не сгенерирует какие-либо выходные данные, но в идеале я хотел бы захватить выходные данные для дополнительной обработки. Возможно ли это?

Ответы [ 2 ]

4 голосов
/ 26 августа 2010

Возможно, вам нужно зарегистрировать Фильтр Процесса, чтобы дать вам необходимое время обратного вызова? См. 37.9 Получение вывода из процессов в руководстве по Elisp (я вижу это в своей копии для 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)
3 голосов
/ 26 августа 2010

Вы должны использовать comint-output-filter-functions переменную, которая содержит функцию для вызова после вставки вывода в буфер.

Например, вы можете сделать:

(add-hook 'comint-output-filter-functions '(lambda (txt) (message "hello")))

NB: Из Emacs 23.2, у вас есть новая команда async-shell-command, связанная глобально с M - & .Это выполняет вашу команду асинхронно, не требуя амперсанда.Вывод вашей команды отправляется в буфер *Async Shell Command*.

...