Nvim: Improved Automatic Indentation
I am still surprised by hidden gems in nvim
. The Zig plugin improves
indentation support for the language. Learning from the included script
revealed nvim
s indentation options. You might want to adjust those to
your own taste.
Contents
Indentation Options
Firstly, make sure to set cindent
as the following options depend on it.
Then, refine cinoptions
according your desires regarding indentation. My
current options are the following.
setlocal cinoptions=(0,w1,j1,J1,l1,Ls
Let us go over them.
- (0
-
In open parenthesis, align the next line with the open parenthesis. You can refine the exact position with the next option. The default is doubled indentation, which always needs adjustment according to my coding style.
- w1
-
Adjusts (0 to point the cursor one position after
(
. This is exactly the right place to start typing my next parameter. - l1
-
Align next line with case label instead of the statement after it. This is useful if you start
case
blocks on the same line. - Ls
-
Place jump labels aligned with current code block.
- j1
-
Use correct indentation for anonymous classes in Java.
- J1
-
Use correct indentation for JavaScript object declarations.
This is my current configuration for quick reference. You might want to go
over all options in :help cinoptions-values
. Additionally, you might want
to check whether they are triggered in the right places. Consult
:help cinkeys
accordingly.
Indentation Function
Predefined options are not the end of the road. Infinite possibilities can be defined via a custom function. If you are using a programming language not quite aligned with C syntax, this equips you with the right tool to adjust your indentation.
I demonstrate the usage on the example provided by the Zig plugin. Let us
assume you want alignment of next line to =>
on the previous line.
function GetZigIndent(lnum) let curretLineNum = a:lnum let currentLine = getline(a:lnum) let prevLineNum = prevnonblank(a:lnum-1) let prevLine = getline(prevLineNum) " switch (1): { " 1 => true, " ~ " ^---- indents to here if prevLine =~ '.*=>.*,$' && currentLine !~ '.*}$' return indent(prevLineNum) endif return cindent(a:lnum) endfunction
The function expects the current line number. We determine the previous
non-empty line using prevnonblank()
. Corresponding contents are available
through getline()
.
For the previous line, we use =~
to check the presence of =>
and ,
being last. For the current line, we use !~
to check the absence of last
}
. If those conditions are met, we return the indentation of previous
line. That is, we align the current line to the previous. The default consists
of cindent()
.
Finally, we put our function into use setting indentexpr
.
setlocal indentexpr=GetZigIndent(v:lnum)
You might find matchstrpos()
handy for your own implementation. It takes
a string and a regex to match. It then returns a list consisting of the match
and both, the starting and ending position of it. Take a look at
:help matchstrpos
for the function’s usage. The returned positions can be
used to adjust the line’s indentation.
Have fun with those improvements to your nvim
configuration and write code
more fluently.