4

If I have a diff file open in vim (not vimdiff), is there a way to jump to the line under the cursor?

Something like this:

  • Detect the hunk of text under the cursor.
  • Open a buffer for the file containing the hunk
    (perhaps an existing buffer if one is already open, although this is a detail).
  • Move to the line which was under the cursor.

Is there a way to do this in vim?


I've seen this in other software.

  • QtCreator supports this by double-clicking on the line of the diff.
  • Emacs diff viewer has diff-goto-source.
ideasman42
  • 3,733
  • 3
  • 27
  • 34

1 Answers1

3

I'm a little surprised that gf doesn't already support this, but it doesn't. There's a plugin that does, though: gf-diff (GitHub mirror).

Someone also wrote a blog post with a more ad-hoc solution, reproduced below. Credit to the blog author, Kana Natsuno.

" git-diff-aware version of gf commands.
nnoremap <expr> gf  <SID>do_git_diff_aware_gf('gf')
nnoremap <expr> gF  <SID>do_git_diff_aware_gf('gF')
nnoremap <expr> <C-w>f  <SID>do_git_diff_aware_gf('<C-w>f')
nnoremap <expr> <C-w><C-f>  <SID>do_git_diff_aware_gf('<C-w><C-f>')
nnoremap <expr> <C-w>F  <SID>do_git_diff_aware_gf('<C-w>F')
nnoremap <expr> <C-w>gf  <SID>do_git_diff_aware_gf('<C-w>gf')
nnoremap <expr> <C-w>gF  <SID>do_git_diff_aware_gf('<C-w>gF')

function! s:do_git_diff_aware_gf(command)
  let target_path = expand('<cfile>')
  if target_path =~# '^[ab]/'  " with a peculiar prefix of git-diff(1)?
    if filereadable(target_path) || isdirectory(target_path)
      return a:command
    else
      " BUGS: Side effect - Cursor position is changed.
      let [_, c] = searchpos('\f\+', 'cenW')
      return c . '|' . 'v' . (len(target_path) - 2 - 1) . 'h' . a:command
    endif
  else
    return a:command
  endif
endfunction
Jim Stewart
  • 381
  • 1
  • 10