Bagaimana saya bisa menggunakan klien Emacs lokal saya sebagai $ EDITOR untuk mesin jarak jauh yang saya akses melalui TRAMP?

44

Saya sering menggunakan TRAMP untuk mengelola beberapa server jarak jauh, baik untuk mengedit file dan menjalankan shell jauh di shell-mode. Namun, ini tidak berfungsi ketika perintah menggunakan EDITORvariabel untuk mengedit file, seperti crontab -eterutama karena shell-modemerupakan terminal "bodoh" yang tidak mendukung menjalankan editor lain di dalamnya.

Secara lokal, saya melakukan ini dengan panggilan yang sesuai emacsclientyang membuka buffer baru dan membuat hidup sangat mudah. Sayangnya, ini tidak bekerja dari mesin jarak jauh.

Saya kira saya bisa menggunakan ed. (Hah!)

Bagaimana saya bisa mengatur remote EDITORyang memungkinkan saya mengedit file dengan instance Emacs lokal saya?

Tikhon Jelvis
sumber

Jawaban:

23

[CATATAN] jawaban ini sangat diedit untuk mengikuti pembaruan with-editorperkembangan. Sebagian besar komentar kemungkinan tidak masuk akal lagi. Ada beberapa komentar baru yang melakukan masuk akal.


Magit berisi perpustakaan bernama with-editortersedia di https://github.com/magit/with-editor yang memungkinkan Anda untuk menggunakan Emacs lokal Anda sebagai $ EDITOR pada mesin jarak jauh melalui TRAMP.

Alternatif lain adalah https://github.com/habnabit/remote-emacsclient , tetapi tampaknya lebih rumit & kurang generik.

Cara paling mudah untuk menginstal with-editoradalah melalui MELPA:

M-x package-install with-editor

Kalau tidak, ambil saja https://github.com/magit/with-editor/blob/master/with-editor.el di suatu tempat ke jalur muat Anda dan requireitu (itu juga tergantung pada tanda hubung).

Kemudian, cukup mulai shell, eshellatau ansi-termdan lakukan hal berikut:

M-x with-editor-export-editor

Ini akan menanyakan $ EDITOR yang Anda minati, cukup tekan enter untuk EDITORvariabel default . Kemudian di dalam shell Anda dapat mengetik crontab -edan mengedit crontab Anda di dalam emacs. Tekan C-c C-cuntuk menyimpan crontab atau C-c C-kuntuk membatalkan pengeditan.

Jika Anda menginginkan pengaturan yang lebih permanen:

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

Atau, Anda dapat menggunakan M-x with-editor-async-shell-command crontab -e RETuntuk perintah cepat.

Silex
sumber
Bisakah Anda menguraikan bagaimana with-editorperpustakaan ini berhubungan dengan pertanyaan? Kedengarannya bermanfaat
Malabarba
@ Silex: Apakah saya perlu mengatur $EDITORvariabel ke sesuatu di mesin remote agar ini berfungsi? Apakah itu hanya terhubung emacsclient?
Tikhon Jelvis
Tapi ya, ini persis seperti yang saya inginkan. Saya harus mencobanya, entah bagaimana — saya berasumsi itu bisa dipasang sendiri, tanpa cabang lainnya?
Tikhon Jelvis
1
@TikhonJelvi: itu pasti akan dapat diinstal dengan sendirinya, tetapi untuk saat ini hanya sebagian saja git-modes. Saya mengikuti lib ini dengan seksama dan hanya saja pengarangnya (@tarsius) sibuk merilis magit, tapi akhirnya itu akan menjadi paket tersendiri. Tentang $ EDITOR, Anda tidak perlu mengaturnya sendiri, itu dilakukan saat diperlukan saat Anda menjalankan perintah apa pun yang menggunakannya. Magit menggunakan lib ini dengan $ GIT_EDITOR.
Silex
1
Catatan ini akan berhenti bekerja setelah sshing untuk remote dari dalam yang ada shell-mode/ term-modepenyangga. Ini dapat diatasi dengan beberapa konfigurasi tambahan, lihat emacs.stackexchange.com/questions/5589/… . Jika Anda berhasil, silakan laporkan temuan Anda di github.com/magit/magit/issues/1638 .
tarsius
1

Penafian: Saya belum mencoba ini.

Anda bisa mendapatkan sebagian dari caranya dengan memiliki perintah keluaran fungsi perintah untuk perintah untuk membuka file menggunakan TRAMP. Lubang keamanan? Iya. Fungsional? Mungkin.

Gunakan shell-modekait untuk menambahkan kait untuk after-change-hookdi shell-mode. Hook ini memperhatikan urutan tertentu. Contoh:

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

Ini kemudian digunakan tramp-find-fileuntuk membuka file. Ini relatif aman karena HANYA HANYA yang dapat dilakukan oleh remote adalah memicu a tramp-find-file. Konfirmasi pertama akan baik tetapi opsional.

Ketika pengeditan selesai, kait lain dapat memicu keluar dari program dummy (misalnya dengan mengirim C-c).

Kasus terburuk (untuk keamanan) adalah mereka menemukan cara untuk menjalankan kode arbitrer. Jika Anda memiliki variabel penyangga yang disetel untuk selalu mengevaluasi, penyerang jahat dapat menimpa pengaturan penting tanpa sepengetahuan Anda. Mereka juga bisa meluncurkan serangan penolakan layanan dengan menyebabkan banyak buffer terbuka. Konfirmasi kemungkinan dapat mencegah semua hal di atas.

Program pada kendali jarak jauh dapat secara sepele diimplementasikan dalam C (atau bahasa lainnya).

J David Smith
sumber
1

https://stackoverflow.com/questions/2231902/originate-edit-of-remote-file-using-emacs-tramp-from-ssh-session memiliki jawaban yang diterima cukup sederhana yang berjumlah

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

dan kemudian gunakan

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

Ada juga https://stackoverflow.com/questions/12546722/using-emacs-server-and-emacsclient-on-other-machines-as-other-users yang lebih kompleks tetapi di mana jawabannya juga (kasar) menyentuh serupa pangkalan.

tripleee
sumber
1

Saya memiliki skrip kecil di jalur saya di host jarak jauh di ~/bin/ec, singkatan untuk 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[@]}"

Script ini lolos -ndan +args tidak berubah menjadi emacsclient, jika tidak args diperlakukan sebagai file untuk dibuka oleh Emacs lokal Anda. Setiap file diawali dengan protokol TRAMP dan host sehingga Emacs tahu cara membukanya. Anda mungkin dapat mengubah ssh:ke protokol TRAMP yang berbeda jika Anda mau.

Anda harus mengganti zdengan nama host mesin jarak jauh Anda. Ini digunakan oleh Emacs lokal untuk terhubung melalui TRAMP. (Anda mungkin dapat menggunakan di hostnamesini untuk umum. Saya lebih suka menggunakan entri kecil seperti zdi lokal saya ssh_configuntuk singkatnya, dan remote tidak tahu saya melakukan ini. Cobalah!)

Pemakaian:

  • ec file di shell jauh membuka file di Emacs lokal dan menunggu
  • ec -n file di shell jauh membuka file di Emacs lokal dan kembali
  • export EDITOR=~/bin/ecdi jarak jauh .bashrcmembuat keajaiban terjadi

Untuk memastikan serverfile saya bagus saya punya ini di lokal saya .emacs, lagi menggunakan nama host kecil 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)

Port 9999 adalah RemoteForward. Saya menempatkan ini di lokal saya ~/.ssh/ssh_configuntuk mengotomatiskan penerusan, ditambah hal-hal ControlMaster untuk kecepatan.

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

Akhirnya, pastikan TRAMP tahu tentang Anda ssh_configjika Anda menggunakannya:

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

Mungkin membutuhkan sedikit penyesuaian, tapi inilah idenya:

EDITOR="ssh artagnon@luneth \"emacsclient -n /`hostname`:$1\""
artagnon
sumber
1
Apakah maksud Anda ssh'ing kembali dari server jauh ke klien tempat Emacs berjalan? Itu seringkali tidak mungkin.
Gilles 'SO- stop being evil'
Nah, jika Anda tidak dapat menjangkau klien tempat Emacs berjalan, tidak mungkin untuk melakukan apa pun.
artagnon
2
Anda dapat meminta ssh, melalui ~/ .ssh / config untuk selalu meneruskan pendengar ssh lokal ke port di mesin jarak jauh. Anda mungkin juga ingin meneruskan ssh-agent Anda, meskipun pendapat berbeda-beda tentang seberapa aman itu. Ini memungkinkan Anda untuk kembali dengan melakukan EDITOR = "ssh $ user @ localhost: 1234 ..."
Ben Hyde
Pilihan lain mungkin akan menulis pembungkus kecil untuk memanggil edit-server.el
stsquad
0

Harold Abnabit datang dengan pendekatan 1 ini :

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

1 berdasarkan artikel sebelumnya oleh Ryan Barrett (yang ia tautkan).

FWIW ada juga https://stackoverflow.com/q/5154224/324105 di mana Petri Lehtinen datang dengan https://gist.github.com/akheron/850795 . Saya membayangkan solusi yang lebih kompleks lebih baik, tetapi pendekatan yang sangat sederhana mungkin masih menarik.

phils
sumber
0

Benar-benar terkejut belum ada yang menyebutkan sshfs. Inilah yang biasanya saya lakukan ketika saya pergi jauh:

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

Meskipun multi-termtidak menyinkronkan direktori kerja lokal dengan direktori jarak jauh, ini mengalahkan semua solusi lain yang telah saya coba. Meskipun pelacakan dir akan menjadi fitur sambutan pasti.

Benjamin Lindqvist
sumber