Prevent the cursor from jumping from below when replacing the buffer

I have content stored in a variable ( out ) that I want to replace with the current buffer. I am currently doing it like this (simplified version):

 let splitted = split(out, '\n') if line('$') > len(splitted) execute len(splitted) .',$delete' endif call setline(1, splitted) 

(Details: https://github.com/fatih/vim-go/blob/master/autoload/go/fmt.vim#L130 )

However, setline() here causes a slowdown on some machines and https://github.com/fatih/vim-go/issues/459 . I myself profiled it, but for me setting was not a problem. Anyway, I need a solution that is faster. Therefore, I came up with several other solutions.

The first, which places the output in a register, deletes all lines and then returns it:

 let @a = out % delete _ put! a $ delete _ 

The second solution will use append() (previously used in vim-go https://github.com/fatih/vim-go/commit/99a1732e40e3f064300d544eebd4153dbc3c60c7 ):

 let splitted = split(out, '\n') %delete _ call append(0, splitted) $delete _ 

They both work! However, both of them also cause a side effect, which I still can’t solve, and it is also written in the title. The problem is described as:

If the buffer is opened in another view (say, next), and we call one of the two solutions listed above, it breaks the cursor into another view and jumps to the bottom

Here is a GIF showing it better (when I call :w one of the above procedures is called): http://d.pr/i/1buDZ

Is there a way to replace the contents of a buffer that is fast and does not break the layout? Or how can I prevent this with one of the above procedures?

Thanks.

+7
vim vim plugin
source share
3 answers

Have you tried winsaveview() and winrestview() ?

 :let old_view=winsaveview() :% delete _ :put! =out :$ delete _ :call winrestview(old_view) 

However, I don't know anything about pasting text faster

0
source share

Try using the redraw command.

I have encountered similar problems of strange delays several times when profiling does not show anything suspicious. But the redraw team resolved it in most cases and did not violate the window layout (the last time I discovered that this problem was in the vim-addon-qf -layout plugin ).

If the problem still occurs, you can try using the following approach, which is slightly different from your first example; I used it for a long time without any delay :

 function! s:setCurrentLine(content) silent put =a:content " delete original line silent '[-1delete _ endfunction 
0
source share

How about this? It saves the view for each window with the current buffer open inside, and then restores all the views after the changes. It seems to work for me.

 function! BufListSave() let cur_buf = winbufnr(0) let cur_tab = tabpagenr() let buflist = [] for i in range(tabpagenr('$')) let tab_array = [] let tab_buflist = tabpagebuflist(i+1) for j in range(len(tab_buflist)) if tab_buflist[j] == cur_buf exe "tabn ".(i+1) let cur_win = winnr() exe (j+1)."wincmd w" call add(tab_array, {"win":j+1, "view":winsaveview()}) exe cur_win."wincmd w" endif endfor call add(buflist, tab_array) endfor exe "tabn ".cur_tab return buflist endfunction function! BufListRest(buflist) let cur_tab = tabpagenr() for i in range(len(a:buflist)) let tab_array = a:buflist[i] if len(tab_array) == 0 continue endif exe "tabn ".(i+1) let cur_win = winnr() for wi in tab_array exe "".wi['win']."wincmd w" call winrestview(wi['view']) endfor exe cur_win."wincmd w" endfor exe "tabn ".cur_tab endfunction function! Do_It() let buf_list = BufListSave() %delete _ put! =out $delete _ call BufListRest(buf_list) endfunction function! Do_It_Silently() silent call Do_It() endfunction 
0
source share

All Articles