How to save in vim a remote file asynchronously?
Asked Answered
T

3

9

Edit a remote file with

 vim scp://remote/file

Saving the file with :w blocks the editor till the file changes are saved to the remote.

I was trying to use :Dispatch :write to avoid being blocked but that does not work (using tmux or iterm strategy). :Dispatch is provided by the plugin vim-dispatch.

Relevant internet search results suggest:

The solutions are helpful but require setup of vcs, config files, etc.

I'd prefer

  • to work locally
  • no configuration for each file (configuring the editor once and for all is ok)
  • Not every write should be a commit.

Keeping an ssh tunnel open didn't improve it either.

Update I'd like to know whether there is a solution to run the save process asynchronously. The save process means here, as netrw is showing in the commandline, a scp call to copy the temp file to the remote which can take some time. I'd like to return to my editing in the meanwhile and don't be blocked. I hope this makes my question clearer.

Alternatives to tpope/dispatch are: Shougo/vimproc, idbrii/AsyncCommand, which I haven't tried yet.

Tellurate answered 1/3, 2015 at 16:6 Comment(9)
So… what are you looking for?Johppa
@romainl: An answer to my question obviously. Mentioning dispatch.vim is just to indicate what I have in mind. It does not seem to work. Do you still don't know what I mean?Tellurate
There is, thankfully, nothing asynchronous in Vim, so you'll need a third-party solution any way you look at it. You have obviously researched your subject but "That's fine but not what I am looking for." doesn't tell us in what way all those options didn't work for you. Or why you don't use Vim directly on your server. Or why you don't use a VCS or anything instead of cowboy editing.Johppa
First of all, I didn't want to ask about things I already know. Using vim directly on the server is laggy compared to running vim locally. I really appreciate vims responsiveness. I would lose it when I'd run vim on the server. Can you explain to me why you say 'thankfully nothing asynchronous in vim'. Afaik neovim is all about asynchronous extension to vim (Job control (work with processes asynchronously)). They are investing a significant amount of time in this.Tellurate
Now you'd might say, you already know the answer. That's not true. Dispatch.vim extends :make and there could be something also for :write.Tellurate
My usual solution to this problem is not to use Vim's scp, but to sshmount the remote; async write is then handled by the filesystem, while Vim happily ignores the fact that the file is not actually on my machine. It has its limitations, but nothing that is not also the problem for the scp method (i.e. can't edit files that require sudo)Many
@Amadan: I have tried osxfuse with sshfs. But I was totally surprised that vim became slower editing mounted files via sshfs than editing local files. Is there something I could have done wrong?Tellurate
I'm sorry, I have no idea. Not saying you're wrong, but I never noticed any slowdown, and I've been doing this on two macs.Many
@amadan: Thanks for letting me know. It is strange. Some search results suggest to set directory and backupdir to a central local directory. In the meanwhile I run vim -u NONE. It appears that one of my settings or more likely one of the plugins causes the slowdown when using sshfs.Tellurate
S
2

It was an old question, yet I encountered the same problem of how to work with remote files efficiently.

My solution is to use unison to sync files on the fly. A command is defined to call the sync function within vim.

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

command! Sync :call <SID>Sync()

The speed of sync files using unison is so fast that I don't have much motivation to make it run asynchronously.

Sweetscented answered 28/9, 2017 at 0:16 Comment(1)
Thanks for this answer. It seems to be that unison is now managed on github: github.com/bcpierce00/unison.Tellurate
T
0

SSHFS: My Problem with sshfs was the vim plugin lightline.vim using fugitive.vim function.

The statusline is updated quite often when you scroll (line number changes) and therefore the fugitive function to show the current branch was evaluated all the time.

This slowed the scrolling significantly down. Removing fugitive status from statusline alleviated the slow down.

There is another plugin https://github.com/seletskiy/vim-refugi which reports that

git through sshfs is slow as hell.

I also installed this plugin for fugitive and applied their tip

Because this script uses ssh multiplexing, it is good to configure your ssh to automatically open master connections.

E.g. you need this in your ~/.ssh/config:

host *
    controlmaster auto
    controlpath   ~/.ssh/connections/%r_%h_%p
Tellurate answered 19/3, 2015 at 14:7 Comment(0)
T
0

Plugin AsyncRun for vim8/neovim

describes on following wiki page how to get netrw using this plugin when saving to remote:

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

Copy of the patch:

Following diff to $VIMRUNTIME/autoload/netrw.vim (version 156) saves asynchronously with AsyncRun when you put into your vimrc let g:netrw_write_AsyncRun = 1:

❯ 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:")
Tellurate answered 20/12, 2016 at 16:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.