20
votes

My ~/.emacs contains the following settings for opening certain files with certain applications (Ubuntu 12.10; Emacs 24):

(setq dired-guess-shell-alist-user
      '(("\\.pdf\\'" "okular ? &")
    ("\\.djvu\\'" "okular ? &")
        ("\\.mp3\\'" "vlc ? &")
    ("\\.mp4\\'" "vlc ? &")
    ))

When I navigate to a .pdf in dired-mode and hit !, it opens the .pdf in Okular, but the dired-buffer is split into two parts, the second one now being a useless *Async Shell Command* buffer containing content like

okular(25393)/kdecore (KConfigSkeleton) KCoreConfigSkeleton::writeConfig:
okular(25393)/kdecore (KConfigSkeleton) KCoreConfigSkeleton::writeConfig:
okular(25393)/kdecore (KConfigSkeleton) KCoreConfigSkeleton::writeConfig:
okular(25393)/kdecore (KConfigSkeleton) KCoreConfigSkeleton::writeConfig:

How can I prevent this buffer from being opened? (except for, maybe, if there was an error and this information is useful).

I found related questions here and here, but they seem to deal with specific commands executed asynchronously, instead of the *Async Shell Command* in general (if possible, I would like to change the behaviour in general for asynchronous processes, not only for certain file types)

8
Take a look at the actual functions inside the source of .../lisp/simple.el -- i.e., defun shell-command and defun async-shell-command. You can even create your own custom functions and/or use defalias. When using start-process, the second argument is the output buffer name -- using nil for the second argument prevents an output buffer from being created. You can use set-process-sentinel in conjunction with start-process. - lawlist
The doc string of async-shell-command states: ... In Elisp, you will often be better served by calling 'start-process' directly, since it offers more control and does not impose the use of a shell (with its need to quote arguments). - lawlist

8 Answers

24
votes

Found this here:

(call-process-shell-command "okular&" nil 0)

Works for me. No stderr gobbledygook.

11
votes

The question was asked in 2012, and at the time of my writing, the most recent answer is dated 2015. Now, in 2017, I can say that the answer is simple:

(add-to-list 'display-buffer-alist
  (cons "\\*Async Shell Command\\*.*" (cons #'display-buffer-no-window nil)))
6
votes

I am piggybacking off of user1404316's answer, but here is another generic way to achieve the desired outcome.

(defun async-shell-command-no-window
    (command)
  (interactive)
  (let
      ((display-buffer-alist
        (list
         (cons
          "\\*Async Shell Command\\*.*"
          (cons #'display-buffer-no-window nil)))))
    (async-shell-command
     command)))
1
votes

I'm not entirely sure about doing it for asynchronous processes in general, but for anything that goes through async-shell-command, this should work:

    (defadvice async-shell-command (around hide-async-windows activate)
       (save-window-excursion
          ad-do-it))
1
votes

Sadly there is no good way to avoid this buffer as it's called directly by 'shell-command' function ('async-shell-command' is just a wrapper).

So, a much better way is to replace 'async-shell-command' with 'start-process'. You should start process with 'set-process-sentinel' to detect the moment when process emits 'exit signal. Then kill process.

0
votes

A slightly more complicated incantation should get you what you want. Just use a shell command like: (okular ? >& /dev/null &).

I haven't tested this with okular, but I can do M-! ((echo foo; sleep 10; echo bar) >& /dev/null &) and Emacs returns immediately without creating a new buffer.

0
votes

I solved the problem, using this method:

;list of programs, corresponding to extensions
(setq alist-programs
      '(("pdf" ."okular")
        ("djvu" . "okular")
        ("mp3" . "xmms")))

(defun my-run-async-command (command file)
  "Run a command COMMAND on the file asynchronously.
   No buffers are created"
  (interactive
   (let ((file (car (dired-get-marked-files t current-prefix-arg))))
     (list
      ;last element of alist-programs, contains COMMAND
      (cdr
       (assoc
        (file-name-extension file)
        alist-programs))
      file)))
  ;begin of function body
  (if command ;command if not nil?
      (start-process "command" nil command file)
    )
)

;attach function to <f2> key
(add-hook 'dired-mode-hook
      (lambda ()
    (define-key dired-mode-map (kbd "<f2>") 'my-run-async-command)))
0
votes

The suggestions to use start-process are ok if he is running a distinct program on the path of course. But if you want run some shell command in a specific directory (eg your project directory) then simply quell the popup - you frequently want the buffer but just dont want it jumping up in your face. eg I run a webserver and I want to see the output, just not now...

  (use-package php-mode
    :config
    (add-to-list 'display-buffer-alist
    (cons "\\*Symfony Web Server\\*.*" (cons #'display-buffer-no-window nil)))
    (defun php-mode-webserver-hook ()
      (if (projectile-project-root) (let ((default-directory (projectile-project-root)))
        (unless (get-buffer "*Symfony Web Server*" )
          (async-shell-command "bin/console server:run" "*Symfony Web Server*")))))
    :hook (php-mode . php-mode-webserver-hook))