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

人走茶凉 提交于 2020-05-09 19:05:53

问题


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 position:

func! Foo()
  :norm mz
  ...
  :norm `z
endf

This properly saves the cursor position, but it sometimes changes the window position, so that the current line moves from being near the top of the screen to being near the bottom or vice versa. Is there a way to preserve both cursor position and the on-screen position of the line?


回答1:


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).




回答2:


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`



回答3:


Just :h getpos()

let save_cursor = getpos(".")
" MoveTheCursorAround
call setpos('.', save_cursor)



回答4:


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.




回答5:


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()


来源:https://stackoverflow.com/questions/954273/vim-scripting-preserve-cursor-position-and-screen-view-in-function-call

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!