Vim indentations demystified January 13, 2025 on Kenneth Dodrill's blog

I should really write a blog post about this so I don’t forget. - Me, recently

Vim has a lot of indentation settings, and this can cause a lot of headaches. There are guides about this, but I thought it proper to give a list, explain them, and then describe some problems I have had and how to fix them.

Basic Settings

Choose Tabs or Spaces

expandtab - This option lets you insert spaces when pressing Tab. This is the option that you are likely looking for when getting into Vim for the first time!

Settings that effect Tabs

tabstop - This is the number of spaces that a <Tab> (the Tab key) counts for. So, if you press the Tab key, it will move the cursor X spaces. However, these are not actual spaces. It is still the Tab character, this just tells Vim how many spaces a Tab is equal to.

Settings that effect Tabs and Spaces

softtabstop - Number of spaces that a <Tab> counts for while performing editing operations, like inserting a <Tab> or using <BS>.

shiftwidth - This is the number of spaces to use for each step of (auto)indent. It is used for cindent, >>, <<, etc. If set to 0, the value of tabstop will be used. Note that without set expandtab, the Tab character will still be used.


Hmm, softtabstop and shiftwidth seem similar! How are they different?

I’m glad you asked! softtabstop is like shiftwidth, but is for any editing operation. shiftwidth is just for (auto)indents.

Okay, so what about auto indentation?

I’m getting there.


Auto Indentation

There are two types of auto indentation settings for Vim: manual and plugin / filetype.

Manual Settings

autoindent - Copies the indentation of the previous line.

smartindent - Automatically inserts one extra level of indentation in some cases, and works for C-like files.

cindent - Enables automatic indenting according to the C programming language indentation rules. This is good for many programming languages as they are similar to how C works.

Generally, smartindent or cindent should only be set manually if you’re not satisfied with how file type based indentation works - vim.fandom.com

Plugin / Filetype Settings

Most IDEs and editors update indentation settings on the fly, and Vim is no exception, but you must enable this feature.

filetype plugin indent on - This command will use indentation scripts located in the indent folder of your Vim installation. Notably, many plugin managers enable this by default (vim-plug is one such example).

Here’s where things get tricky. You need to understand that these indentation scripts are not always perfect. You can file bug reports or try to help fix them if you’re up to it! Typically, they work pretty well.

These scripts can set options for Vim for specific file types. So if you enable this setting, a .c file will have cindent enabled for it. Cool!


Okay, I have auto indentation working, but the default spaces aren’t what I want.

Onward!


Local File Type Settings

You can place default settings in $MY_VIM_CONF/after/ftplugin/some_filetype.vim.

For example, if I wanted 2 spaces for Javascript, I can make ~/.vim/after/javascript.vim and inside I can write:

" not needed for javascript if the filetype plugin is on
setlocal expandtab

setlocal softtabstop=2
setlocal shiftwidth=2

See more examples here

Editorconfig

Indentation is complicated in Vim. It makes sense because it’s so customizable, but I think many people just want to rock some settings for a project and forget about it.

You can use a .editorconfig file and the editorconfig-vim plugin to do this. You’ll need to learn how to write .editorconfig files, but it’s not complicated. You’ll also need one for each project you want to use specific settings for.

Neovim and Treesitter

One last thing that I’m sure people will run into is using Treesitter with Neovim. This was my setup for awhile, and I ended up switching back to Vim because of how complicated things got (and I just got tired of Lua).

Treesitter in Neovim is still experimental, and rightly so. I often had many settings just completely broken. This involved turning off various indentation settings, sometimes with Neovim, sometimes with the filetype plugin script, sometimes just regular settings. Then you can’t use the specific settings from the filetype script because you need that disabled to use Treesitter…it’s kind of a mess.

I would recommend just turning off indents altogether in Treesitter, but you will likely still experience some issues and possibly consider switching back to plain ole’ Vim.