# Vim Tabs vs Spaces Configuration

Nothing causes more heated debates than tabs vs spaces, but what matters is consistency within a project. Vim has multiple settings that control indentation, and they interact in ways that can be confusing. Let me break down exactly how to configure Vim for your preferred style.

Understanding the Settings

Vim has several related settings:

SettingPurpose
tabstopWidth of a tab character in spaces
shiftwidthWidth for autoindent and <<, >> commands
expandtabConvert tabs to spaces when typing
softtabstopHow many spaces a Tab key inserts/deletes
smarttabUse shiftwidth for Tab at line start

Check current values:

vim
:set tabstop? shiftwidth? expandtab? softtabstop?

Tabs Configuration

Use actual tab characters:

vim
set tabstop=4       " Tab character appears as 4 spaces
set shiftwidth=4    " Indentation uses 4 spaces
set noexpandtab     " Don't convert tabs to spaces
set softtabstop=4   " Tab key inserts/deletes 4-space chunks

With these settings, pressing Tab inserts a real tab character that displays as 4 spaces.

Spaces Configuration

Use spaces instead of tabs:

vim
set tabstop=4       " For displaying existing tabs
set shiftwidth=4    " Indentation width
set expandtab       " Convert tabs to spaces
set softtabstop=4   " Tab key inserts 4 spaces

With expandtab, pressing Tab inserts spaces, not a tab character.

2-Space Indentation (Common for Web Development)

vim
set tabstop=2
set shiftwidth=2
set expandtab
set softtabstop=2

Detect Project Style Automatically

Use vim-sleuth or editorconfig for automatic detection:

Using vim-sleuth

vim
Plug 'tpope/vim-sleuth'

This plugin automatically adjusts indentation based on the file.

Using editorconfig

Install the plugin:

vim
Plug 'editorconfig/editorconfig-vim'

Create .editorconfig in your project:

```ini root = true

[*] indent_style = space indent_size = 4

[*.js] indent_size = 2

[*.py] indent_size = 4 indent_style = space

[Makefile] indent_style = tab ```

Convert Between Tabs and Spaces

Convert Tabs to Spaces

vim
" Retab entire file (requires expandtab to be set)
:set expandtab
:retab

This converts all tabs to spaces using tabstop value.

Convert Spaces to Tabs

vim
:set noexpandtab
:retab!

The ! forces conversion even with noexpandtab.

Partial Conversion

Convert only leading whitespace:

vim
" Replace leading spaces with tabs
:%s/^\s\+/\=repeat('\t', len(submatch(0))/&ts)/

Filetype-Specific Indentation

Set different rules per file type:

```vim " Python: 4 spaces autocmd FileType python setlocal ts=4 sw=4 sts=4 expandtab

" JavaScript: 2 spaces autocmd FileType javascript setlocal ts=2 sw=2 sts=2 expandtab

" Go: tabs autocmd FileType go setlocal ts=4 sw=4 sts=4 noexpandtab

" Makefiles: tabs (required) autocmd FileType make setlocal ts=4 sw=4 sts=0 noexpandtab ```

Visual Indentation Guides

Show indentation levels visually:

Using Built-in List Chars

vim
set list
set listchars=tab:▸\ ,trail:·,space:·

This shows tabs as and trailing spaces as ·.

Using indent-blankline (Neovim)

lua
require("ibl").setup()

Using indentLine

vim
Plug 'Yggdroot/indentLine'
let g:indentLine_char = '│'

Preserve Existing Indentation

Don't change indentation when opening files:

vim
set preserveindent

Smart Tab Handling

Behave intelligently at line start:

vim
set smarttab

With smarttab, Tab at the beginning of a line inserts shiftwidth spaces, not tabstop.

Show Current Settings

Create a command to display indentation info:

vim
command! IndentSettings echo 'tabstop='.&ts.' shiftwidth='.&sw.' expandtab='.&et.' softtabstop='.&sts

Use :IndentSettings to see current values.

Fix Misaligned Indentation

Reindent Entire File

vim
gg=G

This reindents from first line to last using syntax rules.

Fix Specific Range

vim
" Reindent lines 10-20
:10,20normal! ==

Copy Indentation from Another File

```vim " Open another file :split template.py

" Copy settings :setlocal ts=<value from other file> :setlocal sw=<value from other file> :setlocal sts=<value from other file> :setlocal et=<value from other file> ```

Common Issues

Mixed Tabs and Spaces

When a file has both:

```vim " Visualize :set list

" Retab to normalize :set expandtab :retab ```

Backspace Deletes Wrong Amount

If backspace deletes too many or too few spaces:

```vim " Ensure softtabstop matches your intent set softtabstop=4

" And enable proper backspace behavior set backspace=indent,eol,start ```

Autoindent Wrong Size

If autoindent uses wrong width:

vim
set shiftwidth=4
set autoindent
set smartindent

Or for smarter indentation:

vim
filetype plugin indent on

Copy-Paste Messes Up Indentation

Use paste mode:

vim
:set paste
" Paste your content
:set nopaste

Or use "+p to paste from system clipboard without reindentation.

Makefile Requirement

Makefiles require tabs. Ensure they're preserved:

vim
autocmd FileType make setlocal noexpandtab

Complete Indentation Setup

Here's a practical .vimrc configuration:

```vim " Default to 4-space indentation set tabstop=4 set shiftwidth=4 set softtabstop=4 set expandtab set autoindent set smartindent set smarttab

" Filetype-specific overrides augroup IndentationSettings autocmd! autocmd FileType python,javascript,typescript,json,html,css setlocal ts=2 sw=2 sts=2 autocmd FileType go,rust setlocal ts=4 sw=4 sts=4 noexpandtab autocmd FileType make setlocal ts=4 sw=4 noexpandtab augroup END

" Visual indication set list listchars=tab:▸\ ,trail:·

" Toggle paste mode set pastetoggle=<F2> ```

Quick Reference

```vim " Show current settings :set ts? sw? et? sts?

" Tabs: use tab characters :set ts=4 sw=4 sts=4 noet

" Spaces: use spaces :set ts=4 sw=4 sts=4 et

" Convert file to spaces :set et | :retab

" Convert file to tabs :set noet | :retab! ```

With these settings and commands, you can handle any indentation style requirement.