11 min read

Formatting code often depends on many different things. Each programming language has its own syntax, and some languages rely on formatting like indentation more than others. In some cases, the programmer is following style guidelines given by an employer so that code can follow the company-wide style.

So, how should Vim know how you want your code to be formatted? The short answer is that it shouldn’t! But by being flexible, Vim can let you set up exactly how you want your formatting done.

However, the fact is that even though formatting differs, most styles of formatting follow the same basic rules. This means that in reality, you only have to change the things that differ. In most cases, the changes can be handled by changing a range of settings in Vim. Among these, there are a few especially worth mentioning:

  • Formatoptions: This setting holds formatting-specific settings (see :help ‘fo’)
  • Comments: What are comments and how they should be formatted (see :help ‘co’)
  • (no)expandtab: Convert tabs to spaces (see :help ‘expandtab’)
  • Softtabstop: How many spaces a single tab is converted to (see :help ‘sts’)
  • Tabstop: How many spaces a tab looks like (see :help ‘ts’)

With these options, you can set nearly every aspect of how Vim will indent your code, and whether it should use spaces or tabs for indentation. But this is not enough because you still have to tell Vim if it should actually try to do the indentation for you, or if you want to do it manually. It you want Vim to do the indentation for you, you have the choice between four different ways for Vim to do it. In the following sections, we will look at the options you can set to interact with the way Vim indents code.

Autoindent

Autoindent is the simplest way of getting Vim to indent your code. It simply stays at the same indentation level as the previous line. So, if the current line is indented with four spaces, then the new line you add by pressing Enter will automatically be indented with four spaces too. It is then up to you as to how and when the indentation level needs to change again. This type of indentation is particularly good for languages where the indentation stays the same for several lines in a row. You get autoindent by using :set, autoindent, or :set ai.

Smartindent

Smartindent is the next step when you want a smarter indent than autoindent. It still gives you the indentation from the previous line, but you don’t have to change the indentation level yourself. Smartindent recognizes the most common structures from the C programming language and uses this as a marker for when to add / remove the indentation levels. As many languages are loosely based on the same syntax as C, this will work for those languages as well. You get smart indent by using any of the following commands:

  • :set smartindent
  • :set si

Cindent

Cindent is often called clever indent or configurable indent because it is more configurable than the previous two indentation methods. You have access to three different setup options:

cinkeys

This option contains a comma-separated list of keys that Vim should use to change the indentation level. An example could be: :set cinkeys=”0{,0},0#,:”, which means that it should reindent whenever it hits a {, a } or a # as the first character on the line, or if you use : as the last character on the line (as used in switch constructs in many languages).The default value for cinkeys is “0{, 0}, 0), :, 0#, !^F, o, O, and e”. See :help cinkeys for more information on what else you can set in this option.

cinoptions

This option contains all the special options you can set specifically for cindent. A large range of options can be set in this comma-separated list. An example could be:set cinoptions=”>2,{3,}3″, which means that we want Vim to add two extra spaces to the normal indent length, and we want to place { and } three spaces as compared to the previous line. So, if we have a normal indent to be four spaces, then the previous example could result in the code looking like this (dot marks represent a space):

if( a == b)

…{

……print “hello”;

…}

The default value for cinoptions is this quite long string: “>s,e0,n0,f0,{0,}0,^0,:s,=s,l0,b0,gs,hs,ps,ts,is,+s,c3,C0,/0,(2s,us,U0,w0,W0,m0,j0,)20,*30” . See :help ‘cinoptions’ for more information on all the options.

cinwords

This option contains all the special keywords that will make Vim add indentation on the next line. An example could be: :set cinwords=”if,else,do,while,for,switch”, which is also the default value for this option. See :help ‘cinwords’ for more information.

Indentexpr

Indentexpr is the most flexible indent option to use, but also the most complex. When used, indentexpr evaluates an expression to compute the indent of a line. Hence, you have to write an expression that Vim can evaluate. You can activate this option by simply setting it to a specific expression such as:

:set indentexpr=MyIndenter()

Here, MyIndenter() is a function that computes the indentation for the lines it is executed on.

A very simple example could be a function that emulates the autoindent option:

function! MyIndenter()
" Find previous line and get its indentation
let prev_lineno = s:prevnonblank(v:lnum)
let ind = indent( prev_lineno )
return ind
endfunction

Adding just a bit more functionality than this, the complexity increases quite fast. Vim comes with a lot of different indent expressions for many programming languages. These can serve as inspiration if you want to write your own indent expression. You can find them in the indent folder in your VIMHOME.

You can read more about how to use indentexpr in :help ‘indentexpr’ and :help ‘indent-expression’.

Fast code-block formatting

After you have configured your code formatting, you might want to update your code to follow these settings. To do so, you simply have to tell Vim that it should reindent every single line in the file from the first line to the last. This can be done with the following Vim command:

1G=G

If we split it up, it simply says:

1G: Go to the first line of the file (alternatively you can use gg)

=: Equalize lines; in other words, indent according to formatting configuration

G: Go to the last line in the file (tells Vim where to end indenting)

You could easily map this command to a key in order to make it easily accessible:

:nmap <F11> 1G=G
:imap <F11> <ESC>1G=Ga

The last a is to get back into the insert mode as this was where we originally were. So, now you can just press the F11key in order to reindent the entire buffer correctly.

Note that if you have a programmatic error, for example, missing a semicolon at the end of a line in a C program, the file will not be correctly indented from that point on in the buffer. This can sometimes be useful to identify where a scope is not closed correctly (for example, a { not closed with a } ).

Sometimes, you might just want to format smaller blocks of code. In those cases, you typically have two options—use the natural scope blocks in the code, or select a block of code in the visual mode and indent it.

The last one is simple. Go into the visual mode with, for example,Shift+v and then press = to reindent the lines.

When it comes to using code blocks on the other hand, there are several different ways to do it. In Vim, there are multiple ways to select a block of code. So in order to combine a command that indents a code block, we need to look at the different types and the commands to select them:

i{

Inner block, which means everything between { and } excluding the brackets. This can also be selected with i} and iB.

a{

A block, which means all the code between { and } including the brackets. This can also be selected with a} and aB.

i(

Inner parenthesis, meaning everything between ( and ) excluding the parentheses. Can also be selected with i) and ib.

a(

A parentheses, meaning everything between ( and ) including the parenthesis. Can also be selected with a) and ab.

i<

Inner < > block, meaning everything between < and > excluding the brackets. Can also be selected with i>.

a<

A < > block, meaning everything between < and > including the brackets. Can also be selected with a>.

i[

Inner [ ] block, meaning everything between [ and ] excluding the square brackets. Can also be selected with i].

a[

A [ ] block, meaning everything between [ and ], including the square brackets. This can also be selected with a].

So, we have defined what Vim sees a block of code as; now, we simply have to tell it what to do with the block. In our case, we want to reindent the code. We already know that = can do this. So, an example of a code block reindentation could look like this:

=i{

Let’s execute the code block reindentation in the following code (| being the place where the cursor is):

 
if( a == b )
{
print |"a equals b";
}

This would produce the following code (with default C format settings):

if( a == b )
{
print |"a equals b";
}

If, on the other hand, we choose to use a { as the block we are working on, then the resulting code would look like this:


if( a == b )
{
print "a equals b";
}

As you can see in the last piece of code, the =a{ command corrects the indentation of both the brackets and the print line.

In some cases where you work in a code block with multiple levels of code blocks, you might want to reindent the current block and maybe the surrounding one. No worries, Vim has a fast way to do this. If, for instance, you want to reindent the current code block and besides that want to reindent the block that surrounds it, you simply have to execute the following command while the cursor is placed in the innermost block:

=2i{

This simply tells Vim that you will equalize / reindent two levels of inner blocks counting from the “active” block and out. You can replace the number 2 with any number of levels of code blocks you want to reindent. Of course, you can also swap the inner block command with any of the other block commands, and that way select exactly what you want to reindent.

So, this is really all it takes to get your code to indent according to the setup you have.

Auto format pasted code

The trend among programmers tells us that we tend to reuse parts of our code, or so-called patterns. This could mean that you have to do a lot of copying and pasting of code.

Most users of Vim have experienced what is often referred to as the stair effect when pasting code into a file. This effect occurs when Vim tries to indent the code as it inserts it. This often results in each new line to be indented to another level, and you ending up with a stair:

code line 1
code line 2
codeline 3
code line 4
...

The normal workaround for this is to go into the paste-mode in Vim, which is done by using:

:set paste

After pasting your code, you can now go back to your normal insert mode again:

:set nopaste

But what if there was another workaround? What if Vim could automatically indent the pasted code such that it is indented according to the rest of the code in the file? Vim can do that for you with a simple paste command.

p=`]

This command simply combines the normal paste command (p) with a command that indents the previously inserted lines (=`]). It actually relies on the fact that when you paste with p (lowercase), the cursor stays on the first character of the pasted text. This is combined with `], which takes you to the last character of the latest inserted text and gives you a motion across the pasted text from the first line to the last.

So, all you have to do now is map this command to a key and then use this key whenever you paste a piece of code into your file.

Using external formatting tools

Even though experienced Vim users often say that Vim can do everything, this is of course not the truth—but is close. For those things that Vim can’t do, it is smart enough to be able to use external tools.

In the following sections, we will take a look at some of the most used external tools that can be used for formatting your code, and how to use them.

LEAVE A REPLY

Please enter your comment!
Please enter your name here