如何在 Vim 中异步保存远程文件?

9

使用以下方法编辑远程文件:

 vim scp://remote/file

使用:w保存文件会阻塞编辑器,直到文件更改被保存到远程位置。我曾尝试使用:Dispatch :write来避免被阻塞,但这并不起作用(使用tmux或iterm策略)。:Dispatch是由插件vim-dispatch提供的。相关的互联网搜索结果建议采取以下措施: 这些解决方案都很有帮助,但需要设置版本控制系统、配置文件等。

我希望:

  • 本地工作
  • 每个文件无需配置(只需一次性配置编辑器即可)
  • 不是每次写操作都需要提交。

保持ssh隧道打开也没有改善。

更新: 我想知道是否有异步运行保存进程的解决方案。这里的保存过程指的是,如netrw在命令行中显示的那样,一个scp调用来将临时文件复制到远程主机,这可能需要一些时间。我希望在此期间能够返回到编辑状态,而不被阻塞。希望这样我的问题更清晰了。

替代tpope/dispatch的选择包括: Shougo/vimprocidbrii/AsyncCommand,但我还没有尝试过。


1
那么...你在寻找什么? - romainl
@romainl:显然是回答我的问题。提到dispatch.vim只是为了表明我的想法。它似乎不起作用。你还是不知道我在说什么吗? - Hotschke
现在你可能会说,你已经知道答案了。但事实并非如此。Dispatch.vim 扩展了 :make 命令,而对于 :write 命令也可能有类似的扩展。 - Hotschke
我通常解决这个问题的方法不是使用Vim的scp,而是通过sshmount远程文件系统;异步写入由文件系统处理,而Vim则忽略了文件实际上并不在我的机器上的事实。它有其局限性,但这也是scp方法所面临的问题(即无法编辑需要sudo权限的文件)。 - Amadan
抱歉,我不知道。并不是说你错了,但我从来没有注意到任何减速情况,并且我已经在两台Mac上进行这个操作了。 - Amadan
显示剩余4条评论
3个回答

2

这是一个老问题,但我遇到了如何高效处理远程文件的相同问题。

我的解决方案是使用unison实时同步文件。定义了一个命令在vim中调用同步函数。

function! s:Sync()
  call system("unison -batch /home/user ssh://user@server//home/user")
endfunction

command! Sync :call <SID>Sync()

使用Unison同步文件的速度非常快,以至于我没有太多动力使其异步运行。

感谢您的回答。看起来unison现在在github上进行管理:https://github.com/bcpierce00/unison。 - Hotschke

0

SSHFS:我的问题是vim插件lightline.vim使用了fugitive.vim函数。

当您滚动时(行号更改),状态栏会经常更新,因此fugitive函数会一直评估以显示当前分支。

这显着减慢了滚动速度。从状态栏中删除fugitive状态可以缓解减速问题。

还有另一个插件https://github.com/seletskiy/vim-refugi报告说

通过sshfs使用git非常缓慢

我还安装了这个插件来处理fugitive,并应用了他们的提示

因为此脚本使用ssh多路复用,所以最好配置您的ssh自动打开主连接。

例如,您需要在~/.ssh/config中添加以下内容:

host *
    controlmaster auto
    controlpath   ~/.ssh/connections/%r_%h_%p

0

针对vim8/neovim的插件AsyncRun

在以下维基页面中描述了如何使用此插件在保存到远程时获取netrw:

https://github.com/skywind3000/asyncrun.vim/wiki/Get-netrw-using-asyncrun-to-save-remote-files

补丁的副本:

将以下差异复制到 $VIMRUNTIME/autoload/netrw.vim(版本 156),当你将 let g:netrw_write_AsyncRun 放入 vimrc 时,异步保存使用 AsyncRun:

❯ git diff netrw-156.vim netrw.vim
diff --git a/netrw-156.vim b/netrw.vim
index 76485c2..183fc96 100644
--- a/netrw-156.vim
+++ b/netrw.vim
@@ -510,6 +510,7 @@ call s:NetrwInit("g:NetrwTopLvlMenu","Netrw.")
 call s:NetrwInit("g:netrw_win95ftp",1)
 call s:NetrwInit("g:netrw_winsize",50)
 call s:NetrwInit("g:netrw_wiw",1)
+call s:NetrwInit("g:netrw_write_AsyncRun",0)
 if g:netrw_winsize > 100|let g:netrw_winsize= 100|endif
 " ---------------------------------------------------------------------
 " Default values for netrw's script variables: {{{2
@@ -2377,6 +2378,14 @@ fun! netrw#NetWrite(...) range
 "    call Decho("(netrw) Processing your write request...",'~'.expand("<slnum>"))
    endif
+   " NetWrite: Perform AsyncRun Write {{{3
+   " ============================
+   if exists("g:netrw_write_AsyncRun") && g:netrw_write_AsyncRun == 1
+       let bang_cmd = 'AsyncRun -post=call\ delete('.s:ShellEscape(tmpfile,1).')\ |\ echo\ "(netrw)\ Your\ write\ request\ has\ finished." '
+    else
+        let bang_cmd ="!"
+   endif
+
    ".........................................
    " NetWrite: (rcp) NetWrite Method #1 {{{3
    if  b:netrw_method == 1
@@ -2515,7 +2524,7 @@ fun! netrw#NetWrite(...) range
     else
      let useport= ""
     endif
-    call s:NetrwExe(s:netrw_silentxfer."!".g:netrw_scp_cmd.useport." ".s:ShellEscape(tmpfile,1)." ".s:ShellEscape(g:netrw_machine.":".b:netrw_fname,1))
+    call s:NetrwExe(s:netrw_silentxfer.bang_cmd.g:netrw_scp_cmd.useport." ".s:ShellEscape(tmpfile,1)." ".s:ShellEscape(g:netrw_machine.":".b:netrw_fname,1))
     let b:netrw_lastfile = choice

    ".........................................
@@ -2612,9 +2621,11 @@ fun! netrw#NetWrite(...) range

   " NetWrite: Cleanup: {{{3
 "  call Decho("cleanup",'~'.expand("<slnum>"))
-  if s:FileReadable(tmpfile)
-"   call Decho("tmpfile<".tmpfile."> readable, will now delete it",'~'.expand("<slnum>"))
-   call s:NetrwDelete(tmpfile)
+  if !exists("g:netrw_write_AsyncRun") || g:netrw_write_AsyncRun == 0
+    if s:FileReadable(tmpfile)
+"     call Decho("tmpfile<".tmpfile."> readable, will now delete it",'~'.expand("<slnum>"))
+      call s:NetrwDelete(tmpfile)
+    endif
   endif
   call s:NetrwOptionRestore("w:")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接