10

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")))
5
  • 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, 2015 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, 2015 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, 2015 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 Jul 6, 2015 at 13:52
  • 4

3 Answers 3

10

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"))))

Note the warning in the docstring of save-window-excursion:

BEWARE: Most uses of this macro introduce bugs.
E.g. it should not be used to try and prevent some code from opening a new window, since that window may sometimes appear in another frame, in which case save-window-excursion cannot help.

In this case I think it should be fine, though, as it is an interactive function that doesn't really interact with any other code.

4
  • Nice macro, I confirm that your solution works.
    – Name
    Jul 3, 2015 at 15:19
  • 2
    @legoscia You were looking for save-window-excursion, which is nearly identical to your implementation.
    – bmag
    Jul 4, 2015 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, 2015 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, 2015 at 9:29
10

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")))
4
  • 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, 2015 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")). Jul 3, 2015 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, 2015 at 21:05
  • @Name, thanks, I've updated the answer to include the concrete function. Jul 6, 2015 at 9:01
8

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)))
6
  • 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, 2015 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, 2015 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, 2015 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, 2015 at 21:38
  • I confirm that your solution perfectly works for the version 24.4 or later.
    – Name
    Jul 4, 2015 at 11:40

Your Answer

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

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