Llame a emacsclient desde un programa llamado por Emacs

9

Me he encontrado con un problema al ver los archivos de documentación en pdf con AucTex. Utilizo pdf-toolspara ver archivos PDF desde Emacs, y lo configuré emacsclient -ncomo mi visor de PDF predeterminado (a través de xdg-mime en Debian Linux). Esto funciona bien en la mayoría de las circunstancias, pero rompe la (Tex-documentation-texdoc ...)función de Auctex ( C-c ?).

He reducido el problema a una sola línea de código. Cuando intento ver la documentación del listingspaquete, lo TeX-documentation-texdocconvierto en el siguiente sexp:

(shell-command-to-string "texdoc --view  listings")

texdoca su vez llama emacsclienta abrir realmente el archivo (según cómo configuré mi escritorio a través de xdg). Sin embargo, en este punto, el Emacs se cuelga y necesito salir ( C-g) para recuperar el control. Después de eso, no se abre un nuevo pdf. Lo mismo sucede si intento llamar a emacsclient directamente:

(shell-command-to-string "emacsclient -n tmp.pdf")

Ambos comandos funcionan en la línea de comando (es decir, emacsclient -n tmp.pdfy texdoc --view listings.

Mi pregunta es, en un caso como este, ¿cómo llamo a emacsclient desde Emacs? (y sé que podría abrir el archivo pdf con find-file; esa no es una opción aquí, ya que necesito llamar a un proceso externo (texdoc) para encontrar el archivo, y ese proceso invoca a emacsclient).

Tyler
fuente
¿Por qué no solo usar texdoc -M --list listingspara encontrar el archivo y luego usar find-file?
Quarky
@suvayu Solo conveniencia. Otra alternativa es cambiar a un terminal para llamar texdoc --viewy luego volver a Emacs cuando abre el archivo. Pero creo que debería haber una manera de hacer esto en un solo paso desde Emacs.
Tyler
1
Puede (async-shell-command "emacsclient -n tmp.pdf")resolver el problema?
Nombre
1
@Nombre interesante: (async-shell-command "emacsclient -n tmp.pdf")funciona, pero no (async-shell-command "texdoc --view listings")no. Esa es una pista útil.
Tyler
1
Funciona C-u C-c ?? Primero muestra la lista de documentos relacionados con el paquete, luego abre el visor con (call-process "texdoc" nil 0 nil "--just-view" doc).
giordano

Respuestas:

5

La solución es ejecutarse texdocdentro de un proceso asincrónico.

Probablemente, la mejor manera de hacerlo es usarlo en start-file-processlugar de shell-command-to-string(que es una función práctica para el código rápido y sucio cuando es más conveniente escribir un pequeño script de shell que el código Elisp correspondiente, pero por lo demás es mejor evitarlo en mi experiencia).

Pero requerirá cambios sustanciales en el código circundante, ya start-file-processque no devuelve la salida del proceso directamente, sino que le permite indicar en qué búfer colocar la salida y luego debe usar set-process-sentineluna función de devolución de llamada que recupere la salida de ese búfer y hace "lo que sea necesario hacer con él" cuando finaliza el comando.

Stefan
fuente
En el caso específico de ejecutar texdocen AUCTeX, considero que el uso de un centinela es una exageración, ya que esta no es una característica fundamental (como es la apertura del visor para el documento de salida, en cuyo caso utilizamos el centinela).
giordano
No tengo idea de por qué se utilizó la función "-to-string", por lo que no sé qué se hace con la salida del comando. Si se necesita esta salida (como sugiere el uso de ...-to-string), una solución asíncrona necesitará un filtro de proceso o un centinela de proceso. Si no, entonces el código puede usar algo como (shell-command "texdoc --view listings &").
Stefan
Se explica en los comentarios a TeX-documentation-texdoc: la ...-to-stringvariante se utiliza para mostrar a los usuarios posibles mensajes de error (por ejemplo, cuando no se encuentra documentación). Además, texdoc nonexistingpackagedevuelve 0, pero el centinela puede usarse para analizar la salida.
giordano
Entonces un centinela parece ser la mejor opción.
Stefan
No puedo encontrar una invocación de start-file-processeso realmente funciona aquí. (start-file-process "texdoc" "*texdoc*" "texdoc" "--view" "listings")crea el búfer *texdoc*, en el que se inserta "Proceso texdoc terminado", y el pdf nunca se abre. Lo mismo sucede cuando configuro el visor de pdf xdg-mime para que también lo muestre.
Tyler
1

Si solo necesita retroalimentar una solicitud a Emacs, sin esperar una respuesta, puede ejecutarla emacsclienten segundo plano. En sistemas operativos de estilo Unix (Linux, macOS, Cygwin, ...):

emacsclient … &

Bajo Windows nativo:

start emacsclient …
Gilles 'SO- deja de ser malvado'
fuente
Claro, pero en este caso particular necesito llamar a un programa (texdoc) que luego llama (emacsclient). El nivel adicional de redireccionamiento está causando problemas.
Tyler
@Tyler texdoces asíncrono (es decir, no estás esperando que se complete), ¿no? Entonces podría aplicar el mismo principio: ejecutar texdoc … &como el comando de shell.
Gilles 'SO- deja de ser malvado'
Lo intentamos en los comentarios bajo mi pregunta; funciona cuando se llama emacsclientdirectamente, pero no cuando se llama texdoc.
Tyler