¿Cómo puedo ejecutar un proceso asíncrono en segundo plano sin abrir un búfer?

23

He definido algunas funciones para ejecutar el proceso de fondo asíncrono usando async-shell-commandmis .emacs, pero cada vez que ejecuto los comandos se crea una nueva ventana (no marco) y el búfer del proceso se muestra allí. ¿Cómo podría ejecutar el comando sin el búfer "emergente"?

rlazo
fuente

Respuestas:

21

Puede iniciar procesos en segundo plano con start-process, que no deberían abrir un búfer:

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

Los nombres de los procesos se modifican para evitar la duplicación según sea necesario, así que no se preocupe por eso. ¡Solo dale un nombre útil para la depuración en el futuro!

Si le das un "buffer-name", se creará un búfer pero no se mostrará de inmediato. Esto puede ser conveniente para administrar procesos y mirar la salida. Si no desea que se cree un búfer, póngalo nilcomo el nombre del búfer:

(start-process "process-name" nil "program")
Tikhon Jelvis
fuente
¿Es posible usarlo start-processpara un comando sudo? He intentado envolver mi llamada a start-processen (let ((default-directory "/sudo::")) ... ), pero no funcionó para mí.
sid-kap
@ sid-kap: no lo sé. Probablemente deberías hacer eso como una pregunta independiente.
Tikhon Jelvis
1
"program"en este caso es solo el nombre del programa (por ejemplo, nautilus, caja, firefox) y "arg1 arg2 ..."debe estar en el cuarto argumento posicional de start-process. Lo descubrí leyendo la documentación :)
biocyberman
8

Como mencionó Tikhon, (start-process)es el camino a seguir. En caso de que no desee crear un búfer pero aún así quiera reaccionar al estado del proceso en segundo plano, también puede emplearlo (set-process-sentinel). Aquí hay un ejemplo modificado que estoy tomando de mi projectorpaquete:

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

De la descripción de la función Emacs:

(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.

Las páginas del manual de GNU sobre Procesos son bastante buenas para obtener más información.

waymondo
fuente
¿Podría describir qué set-process-sentinelhace un poco más exactamente? Tengo la idea general de tener una función que gestione el proceso, pero no entiendo completamente todos los detalles. ¡Gracias!
Tikhon Jelvis
Si lo hace M-x describe-functione ingresa set-process-sentinel, obtendrá la respuesta breve de la documentación de Emacs: (set-process-sentinel PROCESS SENTINEL) Proporcione a PROCESS el centinela SENTINEL; nulo por defecto. Se llama al centinela como una función cuando el proceso cambia de estado. Obtiene dos argumentos: el proceso y una cadena que describe el cambio.
waymondo
1
Las páginas del manual de GNU Emacs sobre Sentinels and Processes son bastante buenas para obtener información más detallada.
waymondo
Guay. ¿Quizás podría editar los enlaces en su respuesta? Supongo que uno también podría aprender más simplemente usando C-h f...
Tikhon Jelvis
2

No es necesario cambiar la forma en que ejecuta un comando asincrónico. Emacs tiene una capacidad genérica para permitirle controlar dónde o si aparecerá algún búfer, modificando una sola estructura de datos, el display-buffer-alist.

En la solución a continuación, puede ver que la función de acción display-buffer-no-window(es decir, sin ventanas emergentes) está configurada para asociarse con cualquier búfer con un nombre que comience *Asynchronous Shell Command*(emacs agrega un sufijo incremental cuando se le pide que cree más de uno).

Para ver la lista de otras opciones de visualización disponibles, escriba C-h f display-buffery busque la lista de "funciones de acción".

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