2

I've found that indenting, with or without a selection, doesn't always work, and it seems to be because of these settings.
From what I can tell it's when the code is valid and correctly indented, but it doesn't happen everywhere. I have yet to find a pattern except for the examples below.

set filetype plugin indent on
set smartindent

Take for example this C++ code:

#include <iostream>
#include <sstream>

int main(void) {
    std::string move;
    int x, y;
    char c;

    while(true) {
        std::cout << "Enter move (x,y): ";
        std::getline(std::cin, move);

        std::stringstream ss(move);
        ss >> x; ss >> c; ss >> y;

        std::cout << "x: " << x << "\n";
        std::cout << "y: " << y << "\n" << std::endl;
    }
}

Indents:

  • Any correct code except #include, for example:
    • << or >> at std::getline(std::cin, move);
    • viB< at std::cout << "Enter move (x,y): ";, thus indenting the block
  • >> or >> if a #include is wrongfully indented
  • If # is removed from the include, making the code incorrect, >> works

Doesn't indent:

  • >> at #include <iostream>
  • vip> at :1, thus selecting the includes and trying to indent them

If the indentation fails, the file is still marked as changed, even though no characters were actually changed.

  1. Is this the correct behaviour?
  2. Why does Vim discriminate between correct code?
  3. I would like to keep the smartindent feature, but still be able to manually indent code even if Vim think it's correct.

My Vim configuration if needed.

timss
  • 9,982
  • 4
  • 34
  • 56
  • 1
    I'd suggest against Vim built-in means of code indentation for such a complex language as C++. It's rather better to integrate external formatting tools with Vim. For example, **[Uncrustify](https://github.com/bengardner/uncrustify)**, have a look at **[my other answer](http://stackoverflow.com/questions/12374200/using-uncrustify-with-vim/15513829#15513829)** to learn how to do it, if you're interested. – Alexander Shukaev May 06 '13 at 14:23
  • @Haroogan Thank you for the suggestion, but I'd rather not have to use some third party tool. I haven't faced any troubles with the way Vim handles C++ other than this. Out of curiosity, what problems have you faced? – timss May 06 '13 at 14:31
  • It's hard to remember from the top of my head. But as you'll use it more, you'll begin to notice some annoying quirks from time to time, fixing which is almost impossible, since Vim does not have a fully-featured C++ parser behind. The indentation is merely done by regular expressions, which works great for simple languages (like Python, for example), but not for C++. Furthermore, you'll certainly want to be able to tweak the formatting style to your taste (or your team's conventions), and that's not really possible with the built-in indenter, whereas Uncrustify, offers more than 1K options. – Alexander Shukaev May 06 '13 at 14:37
  • @Haroogan Thanks, I'll keep it in the back of my mind. As for now I'm happy with the default behaviour of Vim handling the code indentation (except for this issue, obvliously). Indenting variables/`=` is done with [Align](https://github.com/vim-scripts/Align) – timss May 06 '13 at 14:45

1 Answers1

2

According to the documentation for smartindent the behavior you are seeing is correct. Below is the relevant part about # indenting

When typing '#' as the first character in a new line, the indent for that line is removed, the '#' is put in the first column. The indent is restored for the next line. If you don't want this, use this mapping: ":inoremap # X^H#", where ^H is entered with CTRL-V CTRL-H. When using the ">>" command, lines starting with '#' are not shifted right.

One way to manually shift it is to change cinkeys. This option defaults to "0{,0},0),:,0#,!^F,o,O,e" where the fifth option is 0#. According to the help form here changes the behavior of # indenting. (NOTE: you need to scroll up a paragraph)

Vim puts a line in column 1 if: - It starts with '#' (preprocessor directives), if 'cinkeys' contains '#'.

To remove this from cinkeys you can put the following in your vimrc

set cinkeys-=0#

You should also probably remove it from indentkeys too.

set indentkeys-=0#
aymericbeaumet
  • 6,853
  • 2
  • 37
  • 50
FDinoff
  • 30,689
  • 5
  • 75
  • 96
  • It seems like removing `set smartindent` and adding `set cinkeys-=0#` is what I want. As far as I can tell, there's no big reason to add `smartindent` unless I need it, and everything works without it. Removing it also had the added bonus of fixing the erroneous autoindent of `#` in Python. Thanks! – timss May 06 '13 at 16:21
  • `smartindent` is not that smart AFAIK. `cindent` is a lot better (and enabled by default) for C and C++ and most mainstream languages either come with their own `indentexpr` (PHP, Python, Ruby…) or use `cindent` with various options (Java, JavaScript…). – romainl May 06 '13 at 18:30