Getting Vim to stop indenting C++ namespace blocks.

January 19th, 2009

I searched around quit a bit when trying to solve this one and didn’t ever come across a solution. I ended up coding one up and thought I might as well post it in case someone else comes across the same need. I needed Vim’s cindent to do the following:

namespace foo {

typedef struct _Bo {
    int a;
    int b;
} Bo;

class Bar {
public:
    Bar();
    virtual ~Bar();
...
}

void baz() {
}

}

The thing of note here is the namespace block doesn’t doesn’t cause an indent shift. Everything inside is backed up against column 0. There’s no quick and easy cinoption for it so far as I could tell or find and I was able to get all of the other formatting options to match our needs. I did find indentexpr and was able to code up something that gets the desired behavior, it is as follows:

function FixCppNamespaceIndent(lnum)
    " cursor set to lnum
    call cursor(a:lnum, 1)
    " search backwards for opening {
    let p = searchpair('{', '', '}', 'bW')
    if p > 0
        " we're in a { }
        let pl = getline(p)
        " get the line with the opening of our block
        if pl =~ 'namespace'
            " it contains the word namespace so we're shifted 0
            return 0
        else
            " doesn't contain the word namespace so we're normal
            return cindent(a:lnum)
        end
    endif
endfunction

set indentexpr=FixCppNamespaceIndent(v:ln

Won’t guarantee there aren’t a few bugs in cases I haven’t yet run across, but I haven’t seen any problems out of it. One thing I’m not sure about is what will happen with nested namespace, I guess it will depend on what the desired behavior is. Anyway, I’ll solve that if and when I come across it.

Interesting Posts