代码之家  ›  专栏  ›  技术社区  ›  JSBÕ±Õ¸Õ£Õ¹

VIM脚本:在函数调用中保留光标位置和屏幕视图

vim
  •  22
  • JSBÕ±Õ¸Õ£Õ¹  · 技术社区  · 15 年前

    我有一些VIM函数可以更改文档格式。当我调用此函数时,我当前使用如下方法保存和恢复光标位置:

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

    这样可以正确地保存光标位置,但有时会更改窗口位置,以便当前行从靠近屏幕顶部移动到靠近底部,反之亦然。有没有办法同时保留光标位置和行的屏幕位置?

    5 回复  |  直到 15 年前
        1
  •  26
  •   dash-tom-bang    12 年前
    let l:winview = winsaveview()
    " do stuff
    call winrestview(l:winview)
    

    这应该非常准确地执行您希望它执行的操作,可能除了光标上方的行数发生变化(我怀疑光标上方删除的行会产生向下移动光标的效果)。

        2
  •  6
  •   hcs42    15 年前

    您可以为窗口中显示的第一条屏幕行保存一个标记,并恢复该标记。执行 g? 对整个缓冲区发出命令并恢复两个位置:

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

    浏览命令:

    • mk 设定标记 k 对于当前位置
    • H :转到屏幕上的第一行
    • ml 设定标记 l 对于这个职位
    • ggg?G :执行命令
    • ‘L’ : jump to mark L’
    • zt :将此行设置为屏幕上的第一行
    • K 跳到马克 K’
        3
  •  6
  •   Maxim Kim    15 年前

    只是:h getpos()

    let save_cursor = getpos(".")
    " MoveTheCursorAround
    call setpos('.', save_cursor)
    
        4
  •  3
  •   JD Frias flyx    15 年前

    可以使用getline()保存当前缓冲区行,使用winline()保存当前窗口行。

    所以应该是这样的:

    • 用Winline()保存窗口行
    • 将光标移动到窗口顶部,用:normal!H
    • 使用getline()保存缓冲区行
    • 使用:exec“normal!”还原缓冲区行MyLay.“G”
    • 滚动至顶部:正常ZT
    • 然后用:exec“normal!”恢复原始窗口行。MyWiLin。‘H’

    可能会有一些特殊情况需要注意,例如位置靠近文件的结尾或开头,或者文件小于窗口大小。

        5
  •  0
  •   SergioAraujo    7 年前

    有一个 plugin 但是我使用一个这样的函数:

    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
    

    然后我叫它来清除尾随空格

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

    删除空白行

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

    并更改标题(上次修改)信息

    fun! ChangeHeader()
        call Preserve('1,5s/Last Change: \zs.*/\=strftime("%c")/e')
    endfun
    command! -nargs=0 CH :call ChangeHeader()
    au BufWritePost * :call ChangeHeader()