No namespace indent for C++ with Vim
(NOTE: There’s a more up to date version of this in the General C++ Settings section.)
Finally! Vim’s decision to add a ‘shiftwidth‘ to everything I type when I’m inside a namespace is thoroughly annoying and there appears to be no “standard” way to fix this in Vim aside from writing your own function for use in the ‘indentexpr‘ option.
Well I finally got around to writing this up and, while extremely crude, it appears to work alright. You’ll find the function definition below as well as in the General C++ Settings section.
" Fix up indent issues - I can't stand wasting an indent because
" I'm in a namespace. If you don't like this then just comment
" this line out.
setlocal indentexpr=GetCppIndentNoNamespace(v:lnum)
"
" GetCppIndentNoNamespace()
"
" This little function calculates the indent level for C++ and
" treats the namespace differently than usual - we ignore it. The
" indent level is the for a given line is the same as it would
" be were the namespace not event there.
"
" This function is rather crude but it works.
"
function! GetCppIndentNoNamespace(lnum)
let nsLineNum = search('^\s*\
if nsLineNum == 0
return cindent(a:lnum)
else
let incomment = 0
for n in range(nsLineNum + 1, a:lnum - 1)
let cline = getline(n)
if cline =~ '^\s*/\*'
let incomment = 1
elseif cline =~ '^.*\*/'
let incomment = 0
elseif incomment == 0
if cline =~ '^\s*\S\+'
return cindent(a:lnum)
endif
endif
endfor
return cindent(nsLineNum)
endif
endfunction
Mike Jarvis:
October 16th, 2009 at 12:06 pm
This is great. Thanks!
The other C++ thing that I think vim gets wrong is indenting the line after template. I’d like the intent to look like:
template <typename T>
T foo(T x);
But vim indents the second line. The only workaround I had found was to add +0 to cinoptions, but that has other undesirable side effects.
Your function for (not) indenting namespace blocks might give me enough of a starting point to extend it to get the indent right for these lines as well.
Peace,
Mike
Leandro:
March 30th, 2010 at 2:46 pm
This is exactly what I need, but unfortunately it is not working here. :-(
Analyzing your code, I couldn’t figure out what does ‘^\s*\\s\+\S\+’ match after the beginning of the line (‘^’) and blanks (‘\s*’). Apparently the next 5 chars (‘\\s\+’) evaluates to another regex (‘\s+’) but I don’t see the point. The tail of the string then matches one non blank char (‘\S+’) and the last part escapes a plus sign. If I’m right, the string on the next line would match (ignoring the ‘^’ which indicates the beginning of the line):
^ \s+a+
Like I said before, I don’t see where it takes. Could you give me a light?
Thanks in advance for your attention.
Regards,
Leandro