25

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?

paprika
  • 1,944
  • 19
  • 26
rlazo
  • 983
  • 8
  • 13

4 Answers4

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")
Scott Weldon
  • 2,695
  • 1
  • 17
  • 31
Tikhon Jelvis
  • 6,152
  • 2
  • 27
  • 40
  • 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 '16 at 02:00
  • @sid-kap: I don't know. You should probably ask that as a standalone question. – Tikhon Jelvis Dec 30 '16 at 00: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 :) – biocyberman Aug 15 '18 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.

Scott Weldon
  • 2,695
  • 1
  • 17
  • 31
waymondo
  • 1,384
  • 11
  • 16
  • 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! – Tikhon Jelvis Sep 26 '14 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 '14 at 19:42
  • 1
    The [GNU Emacs manual pages on Sentinels](http://www.gnu.org/software/emacs/manual/html_node/elisp/Sentinels.html) and [Processes](http://www.gnu.org/software/emacs/manual/html_node/elisp/Processes.html#Processes) are actually pretty good for more detailed information. – waymondo Sep 26 '14 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`... – Tikhon Jelvis Sep 26 '14 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))
user1404316
  • 769
  • 5
  • 12
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.

draxil
  • 141
  • 1
  • 4