I don't believe it's possible to achieve this with 'cinoptions'
.
The correct solution is probably to write a new indentexpr
that applies C-indenting (accessible via the cindent()
function) only to lines that aren't within comments.
However, here's a couple of quick and dirty solutions:
Using a Macro
First, turn off 'wrapscan'
, so searches end when no more matches are found.
:set nows
Move the cursor to any position where it's not within a comment, and then record a recursive macro:
qqqqq=/\/\*\*\|\%$/-<CR>n/\*\//+<CR>@qq
Then you can jump to the start of the file and run the macro.
gg@q
(N.B. If the very first line of your file is a comment, you'll need to skip past this before running the macro, e.g. by doing this instead: gg/\*\/<CR>+@q
)
Broken down:
qqqqq
: Clear out the q
register and start recording a macro.
=/\/\*\*\|\%$/-<CR>
: Indent up to the beginning of the first comment or to the end of the file.
n/\*\/+<CR>
: Jump to the end of the comment.
@q
: Playback the q
macro. Currently this is empty (we cleared it in the first step) so nothing happens, but when we run this macro for the first time, this will cause the macro to repeat as many times as necessary.
q
: Complete the recording.
The first regular expression used is broken down thus:
/
: start of expression
\/\*\*
: the start of comment (literal /**
)
\|
: or
\%$
: the end of the file
/
: end of expression
-
: offset up one line (so the line itself is not indented).
Using a Function
function! IndentIgnoringComments()
let in_comment = 0
for i in range(1, line('$'))
if !in_comment
" Check if this line starts a comment
if getline(i) =~# '^\s*/\*\*'
let in_comment = 1
else
" Indent line 'i'
execute i . "normal =="
endif
else
" Check if this line ends the comment
if getline(i) =~# '\*\/\s*$'
let in_comment = 0
endif
endif
endfor
endfunction
You can run this with :call IndentIgnoringComments()
or you could set up a command or a mapping. e.g.:
nnoremap <leader>= :call IndentIgnoringComments()<CR>