When I'm editing a cmake file in (neo)vim I'm getting bad behavior block inserting comment characters.

Given this section of text

        PACKAGE tomcrypt
        TARGET tomcrypt::tomcrypt
        VERSION "1.18"
        TYPE "PD"
        FILE "/usr/share/doc/libtomcrypt1/copyright"

If I put the cursor at the start of install_license_file and then do this sequence

  1. ctrl-v
  2. 6j
  3. I
  4. #

I end up with this

        PACKAGE tomcrypt
        TARGET tomcrypt::tomcrypt
        VERSION "1.18"
        TYPE "PD"
        FILE "/usr/share/doc/libtomcrypt1/copyright"

but I'm trying to get this

   #    PACKAGE tomcrypt
   #    TARGET tomcrypt::tomcrypt
   #    VERSION "1.18"
   #    TYPE "PD"
   #    FILE "/usr/share/doc/libtomcrypt1/copyright"

What's causing the unexpected behavior?

** UPDATE **

  • if I completely clear out my init.vim and the system level sysinit.vim (Arch Linux) it works as expected but then if I do set shiftwidth=2 I get the bad behavior.
  • if I start with nvim -u NONE I get the expected behavior even after set shiftwidth=2
  • 2
    What's causing the unexpected behavior? probably a bad configuration, see how do I debug my vimrc – statox Aug 11 '20 at 14:28
  • Check output of :verbose xmap I to see if you have a mapping for I in visual mode that might be affecting this behavior? Since removing init.vim doesn't seem to solve it by itself, then it's probably some plug-in or package that you installed or that was shipped with your Vim? – filbranden Aug 11 '20 at 19:26
  • @filbranden It says no mapping for I. Note that this set of keystrokes works fine if I take the same file and rename to file.py instead of file.cmake (or even just do set filetype=python) – ryan0270 Aug 12 '20 at 1:07
  • @ryan0270 Then maybe :verbose imap #? I'm trying to figure out which part specifically is causing the issue, it looks like a mapping is what would do that, so maybe it's one for inserting the #? Yeah it's definitely something associated with the filetype... – filbranden Aug 12 '20 at 2:14
  • 1
    I don't think it's a mapping; even after clearing all mappings (impac,vmapc,etc) I still get the same bad behavior – ryan0270 Aug 12 '20 at 12:45

You can reproduce this behavior in stock Vim with no extra plug-ins.

The reason why this issue happens is that 'indentkeys' includes 0#, which triggers automatic reindentation of a line when you type # as the first character of the line.

(Note that this is mostly meant for the C/C++ language, for directives such as #define or #include which are meant to appear on the first column even when they appear in the middle of an indented block.)

It appears that the change in indentation is enough to break the visual block insert that repeats the insertion on every line of the block, probably because the insertion is meant to happen on a specific column, but the change of indentation messes up with the column where text in inserted in the first line, so Vim probably just gives up and keeps the insertion to that line alone.

The reason why this issue doesn't happen in vim -u NONE is that, even though 'indentkeys' includes 0# in that case (it's part of the default), the 'indentexpr' option isn't set in that case, and 'indentkeys' only does something when 'indentexpr' is set. (You can easily reproduce this issue under vim -u NONE by using :set indentexpr=0.)

The reason why this issue doesn't happen in a Python script is that the ftplugin for python explicitly removes 0# from 'indentkeys'. (You could argue that the ftplugin for cmake should do the same, since both languages use # to mark comments.)

The workaround I would recommend is that you add an ftplugin script for cmake that will remove 0# from 'indentkeys'.

You can do so by creating a file ~/.config/nvim/after/ftplugin/cmake.vim (that's on NeoVim, or ~/.vim/after/ftplugin/cmake.vim on Vim for Linux/Unix, or %HOME%\vimfiles\after\ftplugin\cmake.vim on Vim for Windows), with the following command in it:

setlocal indentkeys-=0#

This file will be loaded after the ftplugin from Vim runtimes is loaded and will update 'indentkeys' to remove the setting that is breaking your particular use case.

  • 1
    wow, that ended up way more complex than I expected. Thanks for the answer and background explanation! – ryan0270 Aug 12 '20 at 18:15
  • @ryan0270 Ditto! I was expecting this was going to be a rogue plug-in. Surprised me that this was actually behavior of the option defaults and stock runtime. (BTW, I think this should be fixed upstream, I'll try to send a pull request to have the default cmake.vim drop 0# from 'indentkeys' since that seems to make sense there.) Cheers! – filbranden Aug 12 '20 at 18:45

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.