Appelez emacsclient à partir d'un programme appelé par Emacs

9

J'ai rencontré un problème lors de l'affichage des fichiers de documentation pdf avec AucTex. J'utilise pdf-toolspour afficher les fichiers PDF à partir d'Emacs, et j'ai défini emacsclient -ncomme visionneuse pdf par défaut (via xdg-mime sur Debian Linux). Cela fonctionne très bien dans la plupart des cas, mais cela casse la (Tex-documentation-texdoc ...)fonction d'Auctex ( C-c ?).

J'ai réduit le problème à une seule ligne de code. Lorsque j'essaie d'afficher la documentation du listingspackage, TeX-documentation-texdoccela se transforme en sexp suivant:

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

texdocà son tour, appelle emacsclientà ouvrir réellement le fichier (basé sur la façon dont j'ai configuré mon bureau via xdg). Cependant, à ce stade, Emacs se bloque et je dois quitter ( C-g) pour reprendre le contrôle. Après cela, aucun nouveau pdf n'est ouvert. La même chose se produit si j'essaie d'appeler directement emacsclient:

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

Les deux commandes fonctionnent sur la ligne de commande (c'est-à-dire, emacsclient -n tmp.pdfet texdoc --view listings.

Ma question est, dans un cas comme celui-ci, comment appeler emacsclient depuis Emacs? (et je sais que je pourrais simplement ouvrir le fichier pdf avec find-file; ce n'est pas une option ici car j'ai besoin d'appeler un processus externe (texdoc) pour trouver le fichier, et ce processus appelle ensuite emacsclient).

Tyler
la source
Pourquoi ne pas simplement utiliser texdoc -M --list listingspour rechercher le fichier, puis l'utiliser find-file?
Quarky
@suvayu Juste la commodité. Une autre alternative consiste à basculer vers un terminal pour appeler texdoc --view, puis à revenir à Emacs lorsqu'il ouvre le fichier. Mais je pense qu'il devrait y avoir un moyen de le faire en une seule étape depuis Emacs?
Tyler
1
Peut (async-shell-command "emacsclient -n tmp.pdf")résoudre le problème?
Nom du
1
@Name intéressant - (async-shell-command "emacsclient -n tmp.pdf")fonctionne, mais pas (async-shell-command "texdoc --view listings")non. Voilà donc un indice utile.
Tyler
1
Ça C-u C-c ?marche? Il affiche d'abord la liste des documents liés au package, puis ouvre la visionneuse avec (call-process "texdoc" nil 0 nil "--just-view" doc).
giordano

Réponses:

5

La solution consiste à s'exécuter texdocdans un processus asynchrone.

La meilleure façon de le faire est probablement d'utiliser à la start-file-processplace de shell-command-to-string(ce qui est une fonction pratique pour le code rapide et sale quand il est plus opportun d'écrire un petit script shell que le code Elisp correspondant, mais il vaut mieux éviter autrement dans mon expérience).

Mais cela nécessitera des modifications substantielles du code environnant, car start-file-processil ne renvoie pas directement la sortie du processus, il vous permet plutôt d'indiquer dans quel tampon placer la sortie et vous devez ensuite utiliser set-process-sentinelune fonction de rappel qui récupère la sortie de ce tampon et fait "tout ce qui doit être fait" lorsque la commande se termine.

Stefan
la source
Dans le cas spécifique de l'exécution texdocdans AUCTeX, je trouve l'utilisation d'une sentinelle un peu exagérée, car ce n'est pas une caractéristique fondamentale (comme c'est l'ouverture de la visionneuse pour le document de sortie, auquel cas nous utilisons le sentinelle).
giordano
Je n'ai aucune idée pourquoi la fonction "-to-string" a été utilisée, donc je ne sais pas ce qui est fait avec la sortie de la commande. Si cette sortie est nécessaire (comme suggéré par l'utilisation de ...-to-string), une solution asynchrone aura besoin d'un filtre de processus ou d'une sentinelle de processus. Sinon, le code peut peut-être utiliser quelque chose comme (shell-command "texdoc --view listings &").
Stefan
Il est expliqué dans les commentaires à TeX-documentation-texdoc: la ...-to-stringvariante est utilisée pour montrer aux utilisateurs d'éventuels messages d'erreur (par exemple lorsqu'aucune documentation n'est trouvée). En outre, texdoc nonexistingpackagerenvoie 0, mais la sentinelle peut être utilisée pour analyser la sortie.
giordano
Une sentinelle semble alors être la meilleure option.
Stefan
Je ne trouve pas d'invocation start-file-processqui fonctionne réellement ici. (start-file-process "texdoc" "*texdoc*" "texdoc" "--view" "listings")crée le tampon *texdoc*, dans lequel est inséré "Process texdoc terminé", et le pdf ne s'ouvre jamais. La même chose se produit lorsque je configure également la visionneuse PDF xdg-mime.
Tyler
1

Si vous avez seulement besoin de renvoyer une demande à Emacs, sans attendre de réponse, vous pouvez exécuter emacsclienten arrière-plan. Sous OS de style Unix (Linux, macOS, Cygwin,…):

emacsclient … &

Sous Windows natif:

start emacsclient …
Gilles 'SO- arrête d'être méchant'
la source
Bien sûr, mais dans ce cas particulier, j'ai besoin d'appeler un programme (texdoc) qui appelle ensuite (emacsclient). Le niveau supplémentaire de redirection cause des problèmes.
Tyler
@Tyler texdocest asynchrone (c'est-à-dire que vous n'attendez pas qu'il se termine), n'est-ce pas? Vous pouvez donc appliquer le même principe: exécuter en texdoc … &tant que commande shell.
Gilles 'SO- arrête d'être méchant'
Nous avons essayé cela dans les commentaires sous ma question; cela fonctionne en appelant emacsclientdirectement, mais pas en appelant texdoc.
Tyler