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.

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

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.