Vim scripting: Preserve cursor position and screen view in function call

前端 未结 5 898
庸人自扰
庸人自扰 2021-02-02 11:11

I have some Vim functions that make changes to the document format. When I call this function, I currently use something like the following to save and restore my cursor positio

相关标签:
5条回答
  • 2021-02-02 11:27

    You can save a mark for the first on-screen line that is displayed in the window and restore that as well. An example that executes a g? command on the whole buffer and restores both positions:

    :noremap <F11> mkHmlggg?G`lzt`k
    

    Walking through the command:

    • mk: set mark k for the current position
    • H: go to the first on-screen line
    • ml: set mark l for the this position
    • ggg?G: execute the command
    • ``l: jump to markl`
    • zt: set this line the first on-screen line
    • ``k: jump to markk`
    0 讨论(0)
  • 2021-02-02 11:30

    you can use getline() to save the current buffer line and winline() to save the current window line.

    So it would go something like this:

    • save window line with winline()
    • move the cursor to the top of the window with :normal! H
    • save buffer line with getline()
    • ...
    • restore the buffer line with :exec 'normal! '.myline.'G'
    • scroll to the top with :normal zt
    • then restore the original window line with :exec 'normal! '.mywinline.'H'

    There might be a few special cases you will have to take care of such as if the position is near the end or beginning of the file or if the file is smaller then the window size.

    0 讨论(0)
  • 2021-02-02 11:32
    let l:winview = winsaveview()
    " do stuff
    call winrestview(l:winview)
    

    This should pretty much do exactly what you want it to do, possibly excepting the line count changing above the cursor (I suspect that deleted lines above the cursor would have the effect of moving the cursor down).

    0 讨论(0)
  • 2021-02-02 11:32

    Just :h getpos()

    let save_cursor = getpos(".")
    " MoveTheCursorAround
    call setpos('.', save_cursor)
    
    0 讨论(0)
  • 2021-02-02 11:36

    There is a plugin but I use a single function like this:

    if !exists('*Preserve')
        function! Preserve(command)
            try
                " Preparation: save last search, and cursor position.
                let l:win_view = winsaveview()
                let l:old_query = getreg('/')
                silent! execute 'keepjumps ' . a:command
             finally
                " Clean up: restore previous search history, and cursor position
                call winrestview(l:win_view)
                call setreg('/', l:old_query)
             endtry
        endfunction
    endif
    

    then I call it to clean trailing spaces

    fun! CleanExtraSpaces()
        call Preserve(':%s/\s\+$//ge')
    endfun
    com! Cls :call CleanExtraSpaces()
    au! BufwritePre * :call CleanExtraSpaces()
    

    del blank lines

    fun! DelBlankLines()
        call Preserve(':%s/^\n\{2,}/\r/ge')
    endfun
    command! -nargs=0 DelBlank :call DelBlankLines()
    

    and change Header (Last Modified) information

    fun! ChangeHeader()
        call Preserve(':1,5s/Last Change: \zs.*/\=strftime("%c")/e')
    endfun
    command! -nargs=0 CH :call ChangeHeader()
    au BufWritePost * :call ChangeHeader()
    
    0 讨论(0)
提交回复
热议问题