Comment utiliser mon client Emacs local en tant que $ EDITOR pour les machines distantes auxquelles j'accède via TRAMP?

44

J'utilise souvent TRAMP pour gérer plusieurs serveurs distants, à la fois pour l'édition de fichiers et pour l'exécution de shells distants shell-mode. Toutefois, cela ne fonctionne pas lorsqu'une commande utilise la EDITORvariable pour éditer un fichier, crontab -enotamment parce qu'il shell-modes'agit d'un terminal "stupide" qui ne prend pas en charge l'exécution d'un autre éditeur à l'intérieur de celui-ci.

Localement, je le fais avec un appel approprié emacsclientqui ouvre un nouveau tampon et rend la vie très facile. Malheureusement, cela ne fonctionne pas à partir de la machine distante.

Je suppose que je pourrais utiliser ed. (Hah!)

Comment puis-je configurer une télécommande EDITORqui me permettrait de modifier des fichiers avec mon instance Emacs locale?

Tikhon Jelvis
la source

Réponses:

23

[NOTE] cette réponse a été fortement modifiée pour suivre les mises à jour des with-editordéveloppements. La plupart des commentaires n'auront probablement plus beaucoup de sens. Il y a quelques nouveaux commentaires qui font du sens.


Magit contient une bibliothèque nommée with-editordisponible à l’ adresse https://github.com/magit/with-editor qui vous permet d’utiliser votre Emacs local en tant que $ EDITOR sur des machines distantes via TRAMP.

Une autre alternative est https://github.com/habnabit/remote-emacsclient , mais cela semble plus compliqué et moins générique.

Le moyen le plus simple d'installer with-editorest via MELPA:

M-x package-install with-editor

Sinon, il suffit de saisir https://github.com/magit/with-editor/blob/master/with-editor.el quelque part sur votre chemin de chargement et requirecela (cela dépend également du tiret).

Ensuite, il suffit de commencer shell, eshellou ansi-termet procédez comme suit:

M-x with-editor-export-editor

Il vous demandera quel $ EDITOR vous êtes intéressé, appuyez simplement sur Entrée pour la EDITORvariable par défaut . Ensuite, à l'intérieur du shell, vous pouvez taper crontab -eet éditer votre crontab dans emacs. Appuyez sur C-c C-cpour enregistrer la crontab ou sur C-c C-kpour annuler la modification.

Si vous voulez une configuration plus permanente:

(add-hook 'shell-mode-hook  'with-editor-export-editor)
(add-hook 'term-mode-hook   'with-editor-export-editor)
(add-hook 'eshell-mode-hook 'with-editor-export-editor)

Alternativement, vous pouvez utiliser M-x with-editor-async-shell-command crontab -e RETpour les commandes rapides.

Silex
la source
Pourriez-vous préciser le lien entre cette with-editorbibliothèque et la question? Cela semble utile
Malabarba
@ Silex: Aurais-je besoin de définir la $EDITORvariable sur quelque chose sur la machine distante pour que cela fonctionne? Est-ce juste accrocher emacsclient?
Tikhon Jelvis
Mais oui, cela ressemble exactement à ce que je veux. Je vais devoir essayer - je suppose qu'il peut être installé par lui-même, sans le reste de la branche?
Tikhon Jelvis
1
@TikhonJelvi: il sera certainement installable par lui-même, mais pour l'instant cela en fait partie git-modes. Je suis cette librairie de près et c'est juste que son auteur (@tarsius) est occupé à publier magit, mais ce serait finalement un paquet à part. À propos de $ EDITOR, vous n’avez pas besoin de le configurer vous-même, c’est fait quand cela est nécessaire lorsque vous exécutez les commandes qui les utilisent. Magit utilise cette lib avec $ GIT_EDITOR.
Silex
1
Notez que cela cessera de fonctionner après l'envoi d'une commande à une personne distante depuis un tampon shell-mode/ existant term-mode. Cela peut être résolu avec une configuration supplémentaire, voir emacs.stackexchange.com/questions/5589/… . Si vous y arrivez, signalez vos découvertes à github.com/magit/magit/issues/1638 .
Tarsius
1

Disclaimer: Je n'ai pas essayé cela.

Vous pourriez obtenir une partie du chemin en ayant une sortie de commande de surveillance de fonction pour une commande permettant d'ouvrir le fichier à l'aide de TRAMP. Trou de sécurité? Oui. Fonctionnel? Probablement.

Utilisez un shell-modecrochet pour ajouter un crochet after-change-hookdans shell-mode. Ce crochet surveille une séquence spécifique. Exemple:

;; RemoteTRAMP token: <authentication token maybe?>
;; RemoteTRAMP edit: /path/to/my/file

Il utilise ensuite tramp-find-filepour ouvrir le fichier. Ceci est relativement sécurisé parce que la SEULE CHOSE que la télécommande peut faire est de déclencher un tramp-find-file. Une confirmation en premier serait utile mais facultative.

Lorsque l'édition est terminée, un autre hook peut déclencher la sortie du programme factice (par exemple en envoyant C-c).

Le pire des cas (pour la sécurité) est qu'ils trouvent un moyen d'exécuter du code arbitraire. Si vous avez toujours défini des variables de tampon à évaluer, un attaquant malveillant pourrait écraser des paramètres importants à votre insu. Ils pourraient également lancer une attaque par déni de service en provoquant l’ouverture de nombreux tampons. Les confirmations pourraient probablement empêcher tout ce qui précède.

Le programme de la télécommande pourrait être implémenté de manière triviale en C (ou dans tout autre langage).

J David Smith
la source
1

https://stackoverflow.com/questions/2231902/originate-edit-of-remote-file-using-emacs-tramp-from-ssh-session a une réponse acceptée assez simple qui équivaut à

(setq server-use-tcp t)
(setq server-host "name_of_local_machine")
(server-start)
;; Maybe also muck with `server-auth-dir`

et ensuite utiliser

emacsclient -f ~/.emacs.d/server/server /`hostname`:/path/to/local/file

Il y a aussi https://stackoverflow.com/questions/12546722/using-emacs-server-and-emacsclient-on-other-machines-as-other-users qui est plus complexe mais où les réponses aussi (à peu près) ressemblent bases.

triple
la source
1

J'ai un petit script sur mon chemin sur l'hôte distant à ~/bin/ec, raccourci pour emacsclient.

#!/bin/bash

params=()
for p in "$@"; do
  if [ "$p" == "-n" ]; then
    params+=( "$p" )
  elif [ "${p:0:1}" == "+" ]; then
    params+=( "$p" )
  else
    params+=( "/ssh:z:"$(readlink -f $p) )
  fi
done
emacsclient --server-file=$HOME/.emacs.d/server/server "${params[@]}"

Ce script passe -net +args inchangé à emacsclient, sinon les args sont traités comme des fichiers que votre Emacs local peut ouvrir. Chaque fichier est préfixé avec le protocole TRAMP et l’hôte afin que Emacs sache l’ouvrir. Vous pourrez peut-être changer ssh:de protocole TRAMP si vous préférez.

Vous devez remplacer zpar le nom d'hôte de votre ordinateur distant. Emacs local utilise cette méthode pour se connecter via TRAMP. (Vous pourriez peut-être utiliser hostnameici pour la généralité. Je préfère utiliser des entrées minuscules comme zdans mon local ssh_configpour la brièveté, et la télécommande n'a aucune idée de ce que je suis en train de faire. Essayez-le!)

Usage:

  • ec file dans le shell distant ouvre le fichier dans Emacs local et attend
  • ec -n file dans le shell distant ouvre le fichier dans Emacs local et retourne
  • export EDITOR=~/bin/ecà distance .bashrcrend la magie arriver

Pour m'assurer que mon serverfichier est bon, j'ai ceci dans mon local .emacs, en utilisant à nouveau le petit nom d'hôte z:

(setq server-use-tcp t
      server-port    9999)
(defun server-start-and-copy ()
  "Start server and copy server file to remote box."
  (interactive)
  (server-start)
  (copy-file "~/.emacs.d/server/server" "/z:.emacs.d/server/server" t)
  (chmod "/z:.emacs.d/server/server" (string-to-number "644" 8))
  )
(add-hook 'emacs-startup-hook 'server-start-and-copy)

Le port 9999 est une RemoteForward. Je mets cela dans mon local ~/.ssh/ssh_configpour automatiser le transfert, ainsi que le logiciel ControlMaster pour plus de rapidité.

Host z
HostName dev.example.com
User dev
ControlMaster auto
ControlPath ~/.ssh/z.sock
RemoteForward 9999 localhost:9999

Enfin, assurez-vous que TRAMP sait ssh_configsi vous l'utilisez:

(require 'tramp)
(tramp-set-completion-function "ssh"
  '((tramp-parse-sconfig "~/.ssh/config")))
Andy
la source
0

Cela nécessitera peut-être un peu de peaufinage, mais voici l’idée:

EDITOR="ssh artagnon@luneth \"emacsclient -n /`hostname`:$1\""
artagnon
la source
1
Voulez-vous dire ssh'ing back du serveur distant au client où Emacs est en cours d'exécution? C'est souvent impossible.
Gilles, arrête d'être méchant
Eh bien, si vous ne pouvez pas atteindre le client sur lequel Emacs est exécuté, il est impossible de faire quoi que ce soit.
artagnon
2
Vous pouvez demander à ssh, via le fichier ~ / .ssh / config, de toujours renvoyer l’auditeur ssh local à un port de la machine distante. Vous voudrez probablement également transférer votre agent ssh, bien que les opinions varient quant à son degré de sécurité. Cela vous permettra de revenir en faisant EDITOR = "ssh $ user @ localhost: 1234 ..."
Ben Hyde
Une autre option serait peut-être d'écrire un petit wrapper pour appeler edit-server.el
stsquad le
0

Harold Abnabit a proposé cette approche 1 :

http://blog.habnab.it/blog/2013/06/25/emacsclient-and-tramp/

1 d' après un précédent article de Ryan Barrett (auquel il renvoie).

FWIW, il y a aussi https://stackoverflow.com/q/5154224/324105 dans lequel Petri Lehtinen a créé https://gist.github.com/akheron/850795 . J'imagine que les solutions plus complexes sont préférables, mais une approche très simple pourrait tout de même être intéressante.

phils
la source
0

Vraiment surpris, personne n'a sshfsencore mentionné . C'est ce que je fais habituellement quand je vais à distance:

1) multi-term; sshfs user@host:/dir/i/want/ /mnt/point/on/my/machine
2) open whatever I want to edit in my local emacs
3) get-term; ssh user@host to launch executables etc

Bien multi-termque ne synchronise pas le répertoire de travail local avec le répertoire distant, il bat de loin toutes les autres solutions que j'ai essayées. Bien que le suivi de dir serait une fonctionnalité bienvenue à coup sûr.

Benjamin Lindqvist
la source