I know that plugin that can do it almost certainly exists. Or maybe I could use something like LSP for this. But I want to make my simple command, that will go to file with definition of component / function / class in JS. It's not difficult, because in JS all imports are explicitly, so I wrote this command in my .vimrc

autocmd FileType javascript nnoremap gd gd/from<CR>:noh<CR>5lgf
  1. gd = go to definition (first occurrence of symbol)

  2. /from = find from in this string (because string will be like import smth from 'filename')

  3. :noh = remove unnecessary highlighting

  4. 5l = skip from word to move to filename

  5. gf = go file

This works well; it goes to required file.

When I return to my old file, my cursor is on the line with import, but I want to remain in the line where I typed gd. I heard about :keepjump but I don't understand how can I use it here. How can I do this ?

  • 1
    Why reinvent the wheel? This is already built-in functionality. First use set include to add the patterns used for imports, check that vim is detecting them correctly (:checkpath!) and press [ CTRL-D or [D to display all the matches.
    – r_31415
    Commented Jul 28, 2022 at 4:38

2 Answers 2


Try this:

nnoremap gd m':keepjumps normal!gd$Bgf<CR>:noh<CR>

:keepjumps allows you to perform command-line commands without changing the jumplist, but your mapping uses normal-mode commands and searches. You can run normal-mode commands from the command-line with the :normal command, and then you can apply :keepjumps to this.

I replaced your search with the normal-mode commands: $B, which moves to the same position in a different way: Let me know if this doesn't work in all circumstances and I'll add a slightly more complicated version that preserves more exactly the behaviour of your original version.

Also, because you are using :keepjumps, the position immediately before running gd is not stored in the jumplist, so when returning with Ctrl-O you'd actually be at the jump before moving to the position you execute your mapping. To fix this, I use m' before running the :keepjumps normal command, to manually add the desired cursor position to the jumplist.

  • That looks almost perfect! Works with both ' and ". Thank you! Only one small problem = find highlighting isn't disabled after running gd command. Commented Jul 26, 2022 at 18:17
  • 1
    @moskalenco_a I forgot gd would set search highlighting. You should just be able to append :noh to the end of the mapping, I think. I’ll edit this into the answer once I’ve had a chance to test it.
    – Rich
    Commented Jul 27, 2022 at 21:59
  • I know about :noh, but can't find where to insert it. But now try this, and looks like it works. autocmd FileType javascript nnoremap gd m':keepjumps normal!gd$Blgf<CR> :noh<CR> Thank you! Commented Jul 27, 2022 at 23:21
  • Some imporovement. For cases when one import is splitted into multiple lines. autocmd FileType javascript nnoremap gd m':keepjumps normal!gd<CR>/from<CR>5lgf<CR> :noh<CR> Commented Jul 30, 2022 at 9:03
  1. Save cursor position into :h 'quote mark. For example,


nnoremap <buffer>gd <cmd>let w:curpos = getcurpos()[1:]->insert(bufnr())<CR>
    \<cmd>noh<bar>call setpos("'\"", remove(w:, 'curpos'))<CR>
  1. Make sure cursor position is restored as suggested in :h restore-cursor.

  2. Note that if option :set hidden? is TRUE then buffer contents is preserved in RAM and no BufRead event will be fired upon returning to old buffer. You can take this into account by catching BufWinEnter instead of BufRead:


augroup restore_cursor | au!
    autocmd BufWinEnter *
        \   if empty(&buftype)
        \ |     call getpos("'\"")->setpos('.')
        \ | endif
augroup end

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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