In $VIMRUNTIME/ftplugin/vim.vim, some mappings are installed to move the cursor to the previous/next comment:

" Move around comments
nnoremap <silent><buffer> ]" :call search('^\(\s*".*\n\)\@<!\(\s*"\)', "W")<CR>
vnoremap <silent><buffer> ]" :<C-U>exe "normal! gv"<Bar>call search('^\(\s*".*\n\)\@<!\(\s*"\)', "W")<CR>
nnoremap <silent><buffer> [" :call search('\%(^\s*".*\n\)\%(^\s*"\)\@!', "bW")<CR>
vnoremap <silent><buffer> [" :<C-U>exe "normal! gv"<Bar>call search('\%(^\s*".*\n\)\%(^\s*"\)\@!', "bW")<CR>

They use the key sequences [" and ]".

Are there similar mappings for other filetypes, or can we modify these mappings so that they work not only in Vim files but in other filetypes (shell, python, …)?

1 Answer 1


There are similar mappings for other filetypes.

  1. For c-style block comments there exist built-in, ft-independent mappings [*/]* (and as a synonym [//]/)
This is the comment body.
Variation One.

This type of block comment is used in many languages:

ActionScript, AutoHotkey, C, C++, C#, D, Go, Java, JavaScript, kotlin, Objective-C, PHP, PL/I, Rust, Scala, SASS, SQL, Swift, Visual Prolog, CSS


  1. Other mappings for certain filetypes in $VIMRUNTIME/ftplugin/ exist:

    • sql.vim [", ]" (same as vim.vim)
    • eiffel.vim [-, ]-
    • hamster.vim [#, ]# (overwrite built-in motions to jump to c-preprocessor #ifdef which are not used anyway in languages which do not have a c-preprocessor)

You can reuse them for languages with identical commentstrings by copying the code to ~/.vim/after/ftplugin/<language>.vim. (https://en.wikipedia.org/wiki/Comparison_of_programming_languages_(syntax)#Inline_comments)

For example, consider the language lua which has the same commentstring as eiffel:

  1. :e $VIMRUNTIME/ftplugin/eiffel.vim
  2. :45,91w ~/.vim/after/ftplugin/lua.vim
  3. remove unneeded code and change g:no_eiffel_maps to g:no_lua_maps and you should get something like
if !exists("g:no_plugin_maps") && !exists("g:no_lua_maps")
  function! s:DoMotion(pattern, count, flags) abort
    normal! m'
    for i in range(a:count)
      call search(a:pattern, a:flags)

  let comment_block_start = '^\%(\s\+--.*\n\)\@<!\s\+--'
  let comment_block_end = '^\s\+--.*\n\%(\s\+--\)\@!'

  nnoremap <silent> <buffer> ]- :<C-U>call <SID>DoMotion(comment_block_start, 1, 'W')<CR>
  xnoremap <silent> <buffer> ]- :<C-U>exe "normal! gv"<Bar>call <SID>DoMotion(comment_block_start, 1, 'W')<CR>
  nnoremap <silent> <buffer> [- :<C-U>call <SID>DoMotion(comment_block_end, 1, 'Wb')<CR>
  xnoremap <silent> <buffer> [- :<C-U>exe "normal! gv"<Bar>call <SID>DoMotion(comment_block_end, 1, 'Wb')<CR>

  let b:undo_ftplugin = b:undo_ftplugin .
    \ "| silent! execute 'unmap <buffer> [-' | silent! execute 'unmap <buffer> ]-'"

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.