简体   繁体   中英

NavigateBackward in Vim?

So Ctrl-o works only with jumps and has a history, '' gets you back to your last position regardless of how you ended up there (jumping, navigating, etc) but there's no history for it.

What I'm looking for is the best of those two worlds, something like Visual studio's NavigateBackward . Ctrl-o is good but a lot of the times it takes me back to positions I wouldn't expect, jumping is not the only way I navigate...

  1. Is there a built-in command/way in vim that does this?
  2. if not, is there a plugin for it?
  3. if not, I have no problem writing a plugin myself, I know how to set/get the caret position, but I looked at the autocmd-events and couldn't find anything that fires when the caret changes position. How would I go about detecting the 'change' of the caret position?

Thanks.

Alright so thanks to @nodakai for CursorMoved I'm getting somewhere. It's not perfect yet - there's many areas to improve - it works only on one buffer and there's no forward navigation. Not bad for my first useful vimscript. Will improve

" Detect movement
augroup CursorChange
    autocmd!
    autocmd CursorMoved * call OnCursorMoved()
augroup END

" Does the navigation
nnoremap <silent><leader>nb :call NavigateBackward()<cr>

let CursorPositions  = []
let PrevJump = []

function! OnCursorMoved()
    "echo "Cursor moved to: " . line('.') . ':' . col('.')
    "echo g:CursorPositions
    let l:current = [line('.'), col('.')]
    if (l:current != g:PrevJump) " to prevent getting stuck in a circle
        let g:CursorPositions = add(g:CursorPositions, l:current)
    endif
endf

function! NavigateBackward()
    let l:toIndex = len(g:CursorPositions) - 2  " get target jump position index
    if (l:toIndex < 0) | return | endif         " make sure it's within range
    let l:to = g:CursorPositions[l:toIndex]     " jump target
    let g:PrevJump = l:to                       " set previous to target
    call remove(g:CursorPositions, -1)          " remove last position
    call cursor(l:to[0], l:to[1])               " jump to target
endf

function! ResetCursorPositions() " for debugging
    let g:CursorPositions = [[line('.'), col('.')]]
endf

I'm not sure if it's a good idea to bluntly record all horizontal movement. At least I don't see much use for being able to undo word-wise movements and such. Your script is nice, but you might also like a more "specialized" solution..

" Make j and k leave jump marks when used with counts
function! JKMarks(motion)
    execute 'normal! ' . (v:count1 > 1 ? "m'" . v:count1 : '') . a:motion
endfunction
nnoremap <silent> j :<c-u>call JKMarks("j")<cr>
nnoremap <silent> k :<c-u>call JKMarks("k")<cr>

" Make mouse clicks leave jump marks
nnoremap <LeftMouse> m'<LeftMouse>
inoremap <LeftMouse> <c-o>m'<LeftMouse>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM