I'm wondering, if there's a way to move with % in CMakeLists.txt files between foreach and endforeach, if and endif, function and endfunction, …

googeling I only found plugins that allow calling cmake from within vim, but not for editing CMakeLists.txt files.


You can achieve this easily using either the plugin matchit (distributed with vim, just use packadd! matchit) or match-up (external plugin). The latter provides enhanced text objects and also enables highlighting of the words.

To define the matches for cmake, create a file .vim/after/ftplugin/cmake.vim containing:

if exists('loaded_matchit')
    let b:match_words = '\<if\>:\<elseif\>\|\<else\>:\<endif\>'
      \ . ',\<foreach\>\|\<while\>:\<break\>:\<endforeach\>\|\<endwhile\>'
      \ . ',\<macro\>:\<endmacro\>'
      \ . ',\<function\>:\<endfunction\>'
    let b:match_ignorecase = 1

    let b:undo_ftplugin .= "| unlet b:match_words"

This should work with either plugin.

| improve this answer | |

I didn't find an existing solution, but the way to implement that doesn't seem too hard. One needs the matchit plugin (cf https://vi.stackexchange.com/a/784/6044)

" in .vimrc
runtime macros/matchit.vim

And can then define b:match_words e.g. in .vim/ftplugin/cmake.vim

if exists("loaded_matchit")
  let b:match_words =  '^[^#]*\<if\>\s*(:^[^#]*\<else\>\s*(:^[^#]*\<elseif\>\s*(:^[^#]*\<endif\>\s*(\c'
  let b:match_words .= ',^[^#]*\<function\>\s*(:^[^#]*\<endfunction\>\s*(\c'
  let b:match_words .= ',^[^#]*\<foreach\>\s*(:^[^#]*\<endforeach\>\s*(\c'
  let b:match_words .= ',^[^#]*\<macro\>\s*(:^[^#]*\<endmacro\>\s*(\c'
  let b:match_words .= ',^[^#]*\<while\>\s*(:^[^#]*\<endwhile\>\s*(\c'

to be honest I bodged this quickly and didn't go through the entire matchit documentation, but so far it seems to do the job.

| improve this answer | |
  • 1
    I added an answer which is a bit more up to date and includes an alternative plugn. Note you should not need ^[^#]* because comments are already excluded (I'm also not totally sure if you need the \s*(). You can use b:match_ignorecase instead of \c. packadd! matchit is the new style of enabling matchit. – Mass Aug 29 '18 at 16:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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