It is possible to customize the behavior of cindent in Vim by writing a wrapper function. All you need is to find out which indentifiers Vim uses for calculating the new indent, and then find an appropriate regular expression.
Suppose we do not want to indent stuff in namespace declarations. I found out that it is enough to adjust the indentation of the first definition (except for a special case when using inheritance (“: public …“), see the code):
setlocal nolisp
setlocal noautoindent
setlocal indentexpr=GetCppIndent(v:lnum)
if exists("*GetCppIndent")
finish
endif
function! GetCppIndent(lnum)
let cindent = cindent(a:lnum)
if a:lnum == 1 | return cindent | endif
let pattern1 = 'namespaces+S+s*{s*%$'
" pattern2 is used to match this case:
" class c : public b
" { <-- cursor
let clspat = 'classs+S+s*:s*[^{]*'
let pattern2 = 'namespaces+S+s*{s*'.clspat.'%$'
let lines = join(getline(max([ a:lnum - 10, 1]) , a:lnum-1), ' ')
if lines =~ pattern1
return indent(CppFindOccurence('namespace', a:lnum))
elseif lines =~ pattern2 && getline(a:lnum) =~ '^s*{'
return indent(CppFindOccurence('class', a:lnum))
else
return cindent
endif
endfunction
function! CppFindOccurence(pattern, lnum)
for line in range(a:lnum-1,a:lnum-10,-1)
if getline(line) =~ a:pattern
return line
endif
endfor
return -1
endfunction
Please note that this is a hack, and thus not perfect. For instance, it does not take comments or preprocessing directives into account, but that should be easy to implement if it is an issue for you…