Emacs terminal 远程编辑文件方案

抱歉,我可能没有表述清楚。

我希望将 Emacs 当作terminal使用,但是在这个过程中没有办法快捷编辑某个文件。(可能有的时候只是希望更改某一行代码),所以希望问问大家有没有什么比较好的方式在使用Emacs作为terminal的过程中。

而C-f 是C+x C+f 抱歉 我表达错误。

谢谢你的方法,但是这里存在一个成本:你需要在你所有访问的host安装客户端,那如果是这样的话,我其实直接在远程机器上 emacs xx.file 。我的工作环境通常面临大量的虚拟机,这些虚拟机可能随时销毁,也可能随时创建多个,然而linux也不可能自带emacs。如果每次都去安装,或许有点浪费。

如果你用 eshell,在 ssh 链接以后 输入 find-file XXX 就可以打开远程的文件了。不需要任何额外配置。这个就是所谓的 Tramp。

你可以把这个命令 alias 成 vi 。

如果只编辑一行,就用 sed。awk grep sed 是 Linux 标配,建议你花时间学习一下。。

可以用服务器里编辑器,Emacs 里的 M-x term 虽然不能 100% 达到一般终端模拟器的效果,但好像也能运行 nano、Vim、Emacs 之类的程序。

另外就是用 Tramp 了,缺点就是即使你只想编辑一行,也得要把整个文件先下载下来。至于文件名字补全,你可以先用你的 Shell 把需要编辑的文件写好,然后写一个命令通知 Emacs 直接打开它,可以不用 Tramp 补全,Tramp 好像需要专门开一个 Shell 来补全文件名。

为什么不直接使用终端,独立于emacs. 远程编辑采用Shell 的sed, awk等,或者vim。

1 个赞

刚才在本地试了下,一台笔记本(mac)当作本机,一台台式机(pc)当作服务器,从 mac SSH 到 pc 之后,pc 也可以直接 SSH 到 mac。于是在 pc 中加入这样一条命令:

ec () { ssh mac "emacsclient --no-wait /ssh:pc:$(readlink -f $1)"; }

然后就可以用 ec ~/.bashrc 用 mac 上的 Emacs 打开 pc 上的 ~/.bashrc 了。


一个完整的工作流:

打开 Emacs,开启 Server (M-x server-start),打开终端 (M-x term)

~$ ssh pc
Welcome to Ubuntu 17.04 (GNU/Linux 4.10.0-22-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

 * Ubuntu 12.04 LTS ('precise') end-of-life was April 28, 2017
   ongoing security updates for 12.04 are available with Ubuntu Advantage
   - https://ubu.one/U1204esm
 * Aaron Honeycutt from the Kubuntu Council on art and design in Kubuntu
   - https://ubu.one/kubuart
 * The Ubuntu Desktop team wants your feedback on the move to Gnome
   - https://ubu.one/2GNome

4 packages can be updated.
0 updates are security updates.

Last login: Tue Jun 13 13:01:21 2017 from 192.168.0.101
xcy@pc:~$ ssh mac 'uname -a'
Darwin Chunyangs-MacBook-Air.local 16.6.0 Darwin Kernel Version 16.6.0: Fri Apr 14 16:21:16 PDT 2017; root:xnu-3789.60.24~6/RELEASE_X86_64 x86_64
xcy@pc:~$ ec () { ssh mac "emacsclient --no-wait /ssh:pc:$(readlink -f $1)"; }
xcy@pc:~$ ec .bashrc 
xcy@pc:~$

Emacs 就会自动打开 /ssh:pc:.bashrc 了。

6 个赞

谢谢 分享 办法不错。

既然使用Emacs, 而Emacs也提供terminal的功能,所以希望看看能不能只用它,虽然我现在也是mac terminal+Emacs 的模式

这个办法是不错 谢谢分享!学习了!

helm这个工具很有意思,操作思路蛮有意思!

Emacs 编辑远程体验非常非常非常不好

  1. 楼主说的一遍遍输入完整路径的问题应该是不存在的,例如打开 /ssh [email protected]:~/foo.file 之后,并且当前正在编辑 foo.file 的时候,按 C-x C-f 实际上不需要再次输入 /ssh [email protected]:~/ 一大串前缀,只要输入相对路径就可以了。

    真正的问题是路径补全很慢,不管是 TAB 还是 helm,都受限制于网速。

  2. 另一个问题是保存,不知道有多少人跟我一样,每写两行就习惯性按保存,紧接着执行后续的操作,比如:

     |顺序| 按键(evil)  |
     |----|-------------|---------
     |  1 |   :w        | 保存
     |  2 |   j         | 下一行
     |  n |   ...       | ...
    

    如果编辑本地文件,这些动作一气呵成。但是远程文件就不一样了,按下保存键的这一刻,emacs 开始以极低极低极低的效率上传文件,在结束之前按键是无法响应的。

所以,如果文件大/多的时候,还不如登录到远程去使用编辑器。

远程没有安装编辑器的情况下,我用 Forklift.app (其它支持 sftp 的 app 应该也行) 登录服务器,找到文件,然后右键 Open With 选择 Emacs,虽然这一部分操作不那么 Emacs,但是之后的编辑就很流畅了。把文件同步的工作交给其它 app,不要难为单线程的 Emacs

sshfs 我没试过,不知道它能不能解决 C-x C-f 和文件同步的问题。

1 个赞

关于你说的第一点:我的意思是当你在Emacs的eshell或者term的模式下,ssh到远程服务端,这个时候你如果想要编辑文件使用 C-x C-f 会需要你重新输入username@ip_add:xxx。

至于补全,或者保存问题,确实如果是自己简单搭的环境确实网络响应很慢,常常会被阻塞,就像如果不关闭自动保存,会更不舒服。

或许 Emacs 作为一个仍然有这么大的使用群体的编辑器,需要一次革新。

谢谢你的发言!

如果只是想避免输入完整 ssh 路径,可以用别名(ssh key 登录)的方式:

$ cat ~/.ssh/config
Host vps01
    Hostname {IP}
    Port 22
    User root
    IdentityFile ~/.ssh/key-of-vps01

在 Emacs 中 C-x C-f 之后输入: /ssh:vps01:~/file,也不要密码了

如何配置 ssh key 登录: https://www.google.com/search?safe=off&q=setup+ssh+keys&oq=setup+ssh+keys&gs_l=serp.3..0l7j0i30k1l3.87441.94022.0.94231.24.19.5.0.0.0.349.2604.0j8j2j2.12.0....0...1.1.64.serp..7.17.2631...0i12k1j0i12i10k1.pjNs2foLhJk

3 个赞

知道文件名的话,尽量自己输入(手动或者自动),可以不用让 Tramp 去补全。补全是个 Feature,不是非用不可的。

如果本机和服务器之间连接本身就非常慢的话,用什么方法都会慢。

的确,但这应该是意料之中的,因为是你要求保存的,如果 Emacs 不卡出的话,异步把文件同步回去的话(可以用异步的 subprocess 做到),会有可能出现版本冲突(?)。如果你担心版本冲突的话,用别的方法都是如此,Emacs 不是例外。

不了解 Tramp 是怎么上传文件的,但是按照常理来讲,跟 scp、ftp、rsync 之类的工具的效率差不多,因为 tramp 应该用的就是它们。

如果反正就不想用 Tramp 的话,可以把文件拷贝下来、本地编辑、最后再上传,比如:

(defun tom-edit-remote-file (remote-file)
  (interactive "sRemote file: ")
  (let ((local-file
         (concat "/tmp/" (replace-regexp-in-string "/" "-" remote-file))))
    (shell-command (format "scp %s %s" remote-file local-file))
    (find-file local-file)
    (setq-local tom-remote-file remote-file)
    (setq-local tom-local-file local-file)))

(defun tom-upload-remote-file ()
  (interactive)
  (shell-command (format "scp %s %s" tom-local-file tom-remote-file)))
1 个赞

补全似乎是可以缓存的 (tramp-completion-reread-directory-timeout),默认每 10 秒钟刷新一次,设置成 nil 可以一直用缓存,如果你的文件树基本不变的话,改成 nil 之后除了第一次补全,后续的补全应该就会快很多了。

tramp-completion-reread-directory-timeout is a variable defined in ‘tramp.el’.
Its value is 10

Documentation:
Defines seconds since last remote command before rereading a directory.
A remote directory might have changed its contents.  In order to
make it visible during file name completion in the minibuffer,
Tramp flushes its cache and rereads the directory contents when
more than ‘tramp-completion-reread-directory-timeout’ seconds
have been gone since last remote command execution.  A value of t
would require an immediate reread during filename completion, nil
means to use always cached values for the directory contents.
1 个赞

TRAMP 是支持多种协议的,我用的就是 ssh(scp),这是连接和传输层面的协议,内容上还要进行 base64,小文件这一步好像也没太大问题。

我在两台 vps 上做测试(vps1:墙外,看 youtube 高清流畅,vps2:墙内,微软云),获取远程目录/文件列表和保存不到1k的文本文件都能感觉到明显的阻塞。

可能时间消耗在连接&握手这些步骤上了,Emacs 的单线程使得感受更明显。

2 个赞

Win+plink+msys或者msys,几乎和Linux下差不多了。linux下没见过比SSH更好用的了

如果本地没有外网ip,ssh mac回来是不是就不行了…

如果有auto-save,保存会更慢。我也是习惯性保存,每次都要卡好久

我又来安利 GitHub - akermu/emacs-libvterm: Emacs libvterm integration

配合 GitHub - jixiuf/vterm-toggle: toggles between the vterm buffer and whatever buffer you are editing. 两种用法,

1.假如你此时在使用tramp打开了远程的文件 ,那么 调用vterm-toggle-cd 则自动打开一相terminal 并自动ssh到这台服务器 并cd到此文件所在的目录

  1. 反过来也可以.

关于terminal里cd时自动更新default-directory可以参照

emacs-libvterm目前的状态基本已经可用了,尤其对evil-mode的用户。

非evil-mode用户 使用还有一些不便,就是在term buffer中search 等操作目前还需要自定义keybinding来解决。类似于term.el的 term-line-mode term-char-mode https://github.com/akermu/emacs-libvterm/issues/75

1 个赞