7

I have content stored in a variable (out) which I want to replace with the current buffer. I'm 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)

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

However setline() here causes slowness on some machines and https://github.com/fatih/vim-go/issues/459. I've profilde it myself but for me setline was not a problem. Anyway, I need a solution which is more faster. So I've come up with several other solutions.

First one is, which puts the output to a register, deletes all lines and then puts it back:

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

Second solution would be using append() (which was used previously 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 they both also causes a side effect which I'm still couldn't solve and is also written in the title. The problem is described as:

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

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

Is there a way, to replace the content of a buffer, which is fast and doesn't break the layout? Or how can I prevent it with one of the procedures above?

Thanks.

Fatih Arslan
  • 16,499
  • 9
  • 54
  • 55

3 Answers3

0

Did you try winsaveview() and winrestview()?

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

However I don't know anything about pasting text in a quicker way

yolenoyer
  • 8,797
  • 2
  • 27
  • 61
  • Yes I'm already using them, but they don't have affect for the two options above. Here is how I use it: https://github.com/fatih/vim-go/blob/master/autoload/go/fmt.vim#L58 Also there is no problem with the current buffer/view, the problem is it's affecting the other windows cursor position, where I don't have any control. – Fatih Arslan Jul 11 '15 at 13:19
  • Oops, I missed this about your issue: "in *another view*", sorry – yolenoyer Jul 11 '15 at 13:45
  • Yeah, also please watch the GIF, I've showed it in action too :) – Fatih Arslan Jul 11 '15 at 13:47
0

Try using the redraw command.

I have faced similar issues of strange delays a few times, where profiling doesn't shows anything suspicious. But the redraw command solved it in most cases and it doesn't disrupt the window layout (the last time I found this problem was in vim-addon-qf-layout plugin).

If the problem still happens you could try using the following approach, which is slight different from your first example; I've been using it for quite some time without any delays:

function! s:setCurrentLine(content)
   silent put =a:content 
   " delete original line
   silent '[-1delete _
endfunction
mMontu
  • 8,983
  • 4
  • 38
  • 53
  • Unfortunately, both approached doesn't work. Using `redraw`, still doesn't prevent the second view to be changed. The other change messes up the whole buffer as it doesn't fully replace the content. Instead it still `prepend` it. – Fatih Arslan Jul 15 '15 at 21:33
0

What about this? It saves the view for each window with the current buffer opened inside, then restores all the views after the modifications. 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
yolenoyer
  • 8,797
  • 2
  • 27
  • 61