0

I have this snippet of code:

(async-shell-command
 (concat "perl myscript.pl " (buffer-name))
 (read-string "RETURN: ")
 (with-temp-file "file.new"
   (insert-file-contents "file.new")
   (perform-replace "REGEXP" 
            "REPLACEMENT" 
            nil nil nil 1 nil (point-min) (point-max))))

This makes my perl script run on the file visited by buffer and returns a file file.new. I can see the stdout displayed dynamically in the buffer \*Async Shell Command\*, step by step. Then I need to perform some replacements in file.new. Because of the asyncronicity of the process I need to put a read-string to pause my elisp program.

I'd like to sobstitute the async-shell-command with a synchronous command but keeping the dynamically diplayed buffer.

Addedum. Here's another little example of what I mean:

(async-shell-command "echo \"bye\"; sleep 3; echo \"bye\"")

this code will display the first "bye" string in the *Async Shell Command* buffer, than the second "bye" string will be displayed after 3 seconds.

I'd like to have shell-command behaving the same, e.g.:

(shell-command "echo \"bye\"; sleep 3; echo \"bye\"")

I tried to modify the async-shell-command this way:

(defun my-sync-shell-command (command &optional output-buffer error-buffer)
  "DocString"
  (interactive
   (list
    (read-shell-command "Sync shell command: " nil nil
            (let ((filename
                   (cond
                (buffer-file-name)
                ((eq major-mode 'dired-mode)
                 (dired-get-filename nil t)))))
              (and filename (file-relative-name filename))))
    current-prefix-arg
    shell-command-default-error-buffer))
  ;; I commented these lines to remove the ending "&" sign:
  ;; (unless (string-match "&[ \t]*\\'" command)
  ;;   (setq command (concat command)))
  (shell-command command output-buffer error-buffer))

but it didn't work.

1 Answer 1

1

Since you know what the output buffer is, you can hack around this issue by getting the process object from the output buffer and then waiting for it to finish.

(defun run-kinda-async-shell-command (command &optional output-buffer)
  "Run `command' and send results to `output-buffer', blocking until the command finishes."
  (interactive "sCommand: \nsBuffer: ")
  (async-shell-command command output-buffer)
  (let ((process (get-buffer-process output-buffer)))
    (while (process-live-p process)
      (sit-for 0.2))))

Example Usage:

(progn
  (message "prints before")
  (run-kinda-async-shell-command "echo 1 && sleep 2 && echo 1" "output-test")
  (message "prints after"))
1
  • (while (process-live-p (get-buffer-process "*Async Shell Command*")) (sit-for 0.2)) does the job. I'll wait a couple of days before accept your answer. Oct 25, 2018 at 20:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.