8

Is it possible to run a shell command silently (in background)? When I use async-shell-command, emacs split the windows. I would like that an specific shell command to be totally in background (without any visual effect).

As an explicit example, I have the following code (borrowed from https://emacs.stackexchange.com/a/7932). It opens the pdf version of the tex-file I working on. When running it, it splits the window, I would like to prevent it from this behavior in this particular situation.

 (defun my-view-pdf ()
  (interactive)
  (async-shell-command
    (concat "SumatraPDF " (file-name-base (buffer-file-name)) ".pdf")))
  • 3
    Not about the abstract question, but the specific use case: Are you using AUCTeX? Any particular reason you're not using TeX-view (C-c C-v)? – Dan Jul 3 '15 at 15:29
  • @Dan the problem is that when I do C-c C-v nothing happens. I don't understand why. If you know a simple customization in the .emacs which makes C-c C-v works , I would be happy to use it. My OS is Windows and my pdf viewer is located at C:\Program Files\SumatraPDF\sumatrapdf.exe. In that link lawlist has provided a comprehensive link. I am only interested to make TeX-viewer works. – Name Jul 3 '15 at 19:26
  • Not on Windows, so can't say why you're having problems. You might try working with TeX-view-program-list. – Dan Jul 3 '15 at 19:31
  • This question has very good answers so I will hate for this to get closed. But this is a duplicate of this question: emacs.stackexchange.com/q/5553/115 – Kaushal Modi Jul 6 '15 at 13:52
  • 4
8

save-window-excursion is a macro for running a piece of code without altering the window configuration. Something like this should work:

 (defun my-view-pdf ()
  (interactive)
  (save-window-excursion
   (async-shell-command
     (concat "SumatraPDF " (file-name-base (buffer-file-name)) ".pdf"))))
  • Nice macro, I confirm that your solution works. – Name Jul 3 '15 at 15:19
  • 2
    @legoscia You were looking for save-window-excursion, which is nearly identical to your implementation. – bmag Jul 4 '15 at 6:50
  • @bmag I am interested to know about the difference between save-window-excursion and save-window-configuration. It seems that both work in this situation. – Name Jul 7 '15 at 9:21
  • 1
    @Name No difference, except that save-window-excursion uses some macro best practices to avoid introducing variables into the environment of the body. Also, save-window-excursion is built-in to Emacs. I was looking for that macro, but didn't find it, so I wrote my own version. Fortunately bmag knew the real one. – legoscia Jul 7 '15 at 9:29
8

If you just would like to spawn a process in the background you don't need all the bells an whistles that shell command functions provide.

Instead, you can use the function call-process. For example:

(call-process
 "a_command"
 nil
 0                                  ; <- Discard and don't wait
 nil
 "arg1"
 "arg2")

Concretely, this mean that you can implement you command as:

(defun my-view-pdf ()
    (interactive)
    (call-process "SumatraPDF" nil 0 nil
                  (concat (file-name-base (buffer-file-name)) ".pdf")))
  • I tried to apply your suggestion for my specific example (defun my-pdf-viewer () (interactive) (call-process (async-shell-command (concat "SumatraPDF " (file-name-base (buffer-file-name)) ".pdf")) nil 0 ; <- Discard and don't wait nil "arg1" "arg2") ) I get the error ` Wrong type argument: stringp, comint-output-filter`. I am not sure if the syntax I used is correct. – Name Jul 3 '15 at 20:52
  • You should drop async-shell-command all together. It should be something like (defun my-pdf-viewer () (interactive) (call-process "SumatraPDF" nil 0 nil (concat (file-name-base (buffer-file-name)) ".pdf")). – Lindydancer Jul 3 '15 at 20:58
  • 1
    Thank you, your solution works perfectly, there was only a missing brace, so the correct code should be : (defun my-view-pdf () (interactive) (call-process "SumatraPDF" nil 0 nil (concat (file-name-base (buffer-file-name)) ".pdf"))) . – Name Jul 3 '15 at 21:05
  • @Name, thanks, I've updated the answer to include the concrete function. – Lindydancer Jul 6 '15 at 9:01
7

Use display-buffer-alist with the display-buffer-no-window if you're on Emacs 24.4 or later.

(setq display-buffer-alist '(("\\`\\*Async Shell Command\\*\\'" display-buffer-no-window)))

Alternatively, use shackle:

(setq shackle-rules '(("*Async Shell Command*" :ignore t)))
  • Using (setq display-buffer-alist '(("\`\\*Async Shell Command\\*\\'" display-buffer-no-window))) I get the error apply: Wrong type argument: sequencep, display-buffer-no-window. – Name Jul 3 '15 at 15:35
  • Oh right, display-buffer-no-window was introduced in Emacs 24.4, so that won't work. My package on the other hand should work on 24.3. – wasamasa Jul 3 '15 at 15:38
  • Backporting display-buffer-no-window is a third option, just insert (defun display-buffer-no-window (_buffer alist) (when (cdr (assq 'allow-no-window alist)) 'fail)) in your Emacs configuration. – wasamasa Jul 3 '15 at 20:32
  • I tried to apply your last comment by putting the things all together (defun display-buffer-no-window (_buffer alist) (when (cdr (assq 'allow-no-window alist)) 'fail)) (setq display-buffer-alist '(("\`\\*Async Shell Command\\*\\'" display-buffer-no-window))) (defun my-view-pdf () (interactive) (progn (async-shell-command (concat "SumatraPDF " (file-name-base (buffer-file-name)) ".pdf")))) . But after executing my-view-pdf, emacs splits the window and *Async Shell Command* is shown. – Name Jul 3 '15 at 21:38
  • I confirm that your solution perfectly works for the version 24.4 or later. – Name Jul 4 '15 at 11:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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