Skip to content

Instantly share code, notes, and snippets.

@LunarLambda
Created September 30, 2019 22:43
Show Gist options
  • Save LunarLambda/4c444238fb364509b72cfb891979f1dd to your computer and use it in GitHub Desktop.
Save LunarLambda/4c444238fb364509b72cfb891979f1dd to your computer and use it in GitHub Desktop.
A Best Effort Guide to Vim's Indentation Settings.

Vim 'Indentation Hell': A Best Effort Guide

I love Vim. But it isn't perfect, unfortunately.
And one part that is particularly confusing when setting up for the first time is indentation.
This guide strives to cover what options are relevant, what they do, how they interact, and how to set them up for most popular indentation styles.

Meet The Cast

Vim has 5 options relating to (manual) indentation:

Name Shorthand Default Value
expandtab et off
tabstop ts 8
shiftwidth sw 8
softtabstop sts 0
smarttab sta off (Neovim: on)

You can find the documentation for each in Vim with :help 'option'.
For how to set options, see :help set-option.

Expandtab

expandtab is simple: If it is set, indentation is always done with spaces.
No tabs are inserted unless typed with <Ctrl-V>.

Tabstop

tabstop is similarly simple: It defines the width of a <Tab> character.

Shiftwidth

shiftwidth determines how many blanks are inserted when using the > and < commands, and when automatic indentation is used.
If set to 0, it uses the value of tabstop.

Softtabstop

Here's where things become slightly more complex.
When softtabstop is not 0, <Tab> and <Backspace> insert and delete this many spaces.
If expandtab is not set, tabstop many spaces will be replaced by a <Tab>.

For example, with :set noexpandtab tabstop=8 softtabstop=2,
Pressing <Tab> four times gives you the following:

2 Spaces
4 Spaces
6 Spaces
1 Tab (8 spaces wide)

This allows tabstop to be left at the default value of 8, which is the most compatible.

If softtabstop is set to a negative value, the value of shiftwidth will be used.

Smarttab

When smarttab is set, pressing <Tab> at the start of a line (i.e. when using <Tab> for indentation), will always use the value of shiftwidth. Anywhere else, softtabstop (if set) and tabstop are used.

Opinion: I heavily recommend always setting smarttab (the default if you use Neovim!), and use shiftwidth as the one true indentation width.

Common Indentation Styles

In this section I'll cover several indentation styles, and what combination of options to use for them.

Tabs Only

Where N is your desired indentation size:

set noexpandtab   " Default
set tabstop=N
set shiftwidth=0  " Use value of tabstop
set softtabstop=0 " Default
set smarttab      " Optional

Spaces Only

Where N is your desired indentation size:

set expandtab
set tabstop=N      " Optional, if you want files with tabs to look the same too.
set shiftwidth=N
set softtabstop=-1 " Use value of shiftwidth
set smarttab       " Always use shiftwidth

Tabs and Spaces Mixed

This style can be used if you want to leave tabstop at its default of 8, but want <Tab> to behave as if it was a different value.
Where N is your desired indentation size:

set noexpandtab    " Default
set shiftwidth=N
set softtabstop=-1 " Use value of shiftwidth
set smarttab       " Always use shiftwidth

Using a Different Number of Blanks for Alignment

smarttabs behavior allows <Tab> to insert a different number of blanks when not at the start of a line.
This is done by using the softtabstop option.
This is useful for aligning comments and variable names, for example.

For a tabs-only style, this doesn't really work due to how softtabstop works, since changing the value of tabstop can then mess up your alignment, if it contains tabs.
If you want a 'indent with tabs, align with spaces' style, you'll have to look for a plugin like Smart Tabs.

For spaces-only and mixed styles, you can simply change softtabstop to your desired alignment size.

Epilogue

And that about wraps it up! I hope I was able to clear up some of the confusion around Vim's settings :)

If you have any suggestions or questions, let me know! And of course, happy vimming!

@Beerosagos
Copy link

Very nice guide, thank you!

@jasonmittels
Copy link

Thank you!

@Fernu292
Copy link

Thank you <3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment