26

I have defined some functions to run async background process using async-shell-command in my .emacs, but everytime I run the commands a new window (not frame) is created and the process' buffer is shown there. How could I run the command without the "pop up" buffer?

4 Answers 4

22

You can start background processes with start-process, which shouldn't pop up a buffer:

(start-process "process-name" "buffer-name" "program")

Process names are modified to avoid duplication as necessary, so don't worry about that. Just give it a name useful for debugging in the future!

If you give a "buffer-name", a buffer will be created but not shown immediately. This can be convenient for managing processes and looking at output. If you don't want a buffer to be created at all, pass nil as the buffer name:

(start-process "process-name" nil "program")
3
  • Is it possible to use start-process for a sudo command? I tried wrapping my call to start-process in (let ((default-directory "/sudo::")) ... ) but it didn't work for me.
    – sid-kap
    Dec 29, 2016 at 2:00
  • @sid-kap: I don't know. You should probably ask that as a standalone question. Dec 30, 2016 at 0:38
  • 1
    "program" in this case is only program name (e.g nautilus, caja, firefox) and "arg1 arg2 ..." should be in the fourth positional argument of start-process. I figured that out by reading the documentation :) Aug 15, 2018 at 20:40
8

Like Tikhon mentioned, (start-process) is the way to go. In case you don't want to create a buffer but would still like to react to the background process status, you can also employ (set-process-sentinel). Here's a modified example I'm taking from my projector package:

(set-process-sentinel (start-process "process-name" nil "command") #'output-message-sentinel)

(defun output-message-sentinel (process msg)
  (when (memq (process-status process) '(exit signal))
    (message (concat (process-name process) " - " msg))))

From the Emacs function description:

(set-process-sentinel PROCESS SENTINEL)

Give PROCESS the sentinel SENTINEL; nil for default.
The sentinel is called as a function when the process changes state.
It gets two arguments: the process, and a string describing the change.

The GNU manual pages on Processes is pretty good for more info.

4
  • Could you describe what set-process-sentinel does a bit more accurately? I get the general idea of having a function that manages the process, but I don't fully understand all the details. Thanks! Sep 26, 2014 at 19:21
  • If you do M-x describe-function and enter set-process-sentinel you'll get the short answer from Emacs documentation: (set-process-sentinel PROCESS SENTINEL) Give PROCESS the sentinel SENTINEL; nil for default. The sentinel is called as a function when the process changes state. It gets two arguments: the process, and a string describing the change.
    – waymondo
    Sep 26, 2014 at 19:42
  • 1
    The GNU Emacs manual pages on Sentinels and Processes are actually pretty good for more detailed information.
    – waymondo
    Sep 26, 2014 at 19:43
  • Cool. Perhaps you could edit the links into your answer? I guess one could also learn more just using C-h f... Sep 26, 2014 at 20:04
4

There's no need to change how you run an asynchronous command. Emacs has a generic ability to allow you to control where or whether any buffer will pop-up, by modifying a single data structure, the display-buffer-alist.

In the solution below, you can see that the action function display-buffer-no-window (ie. no pop-up) is set to be associated with any buffer with a name beginning *Asynchronous Shell Command* (emacs adds an incremental suffix when it's asked to create more than one).

To see the list of other available display options, type C-h f display-buffer and look for the list of "action functions".

;; Buffers that I don't want popping up by default
(add-to-list 'display-buffer-alist
  '("\\*Async Shell Command\\*.*" display-buffer-no-window))
0
0

You might also want to check out async-start-process (from emacs-async):

(async-start-process "name" "cmd" nil "arg1" "arg2)

That nil argument is the place for a function to run when it's done.

Whilst emacs-async is an external package it's highly likely you have it as a dependency if you've installed much from MELPA and it makes what you want very easy.

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.