1419

How do I make vi-Vim never use tabs (converting spaces to tabs, bad!), makes the tab key == 4 spaces, and automatically indent code after curly brace blocks like Emacs does?

Also, how do I save these settings so I never have to input them again?

I've seen other questions related to this, but it always seems to be a little off from what I want.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
mmcdole
  • 91,488
  • 60
  • 186
  • 222
  • 3
    Related: [How to replace tabs with spaces?](http://vi.stackexchange.com/q/495/467) at Vim SE – kenorb Feb 19 '15 at 13:23

12 Answers12

2125

As has been pointed out in a couple of other answers, the preferred method now is NOT to use smartindent, but instead use the following (in your .vimrc):

filetype plugin indent on
" show existing tab with 4 spaces width
set tabstop=4
" when indenting with '>', use 4 spaces width
set shiftwidth=4
" On pressing tab, insert 4 spaces
set expandtab

In your [.vimrc:][1] file:
set smartindent
set tabstop=4
set shiftwidth=4
set expandtab

The help files take a bit of time to get used to, but the more you read, the better Vim gets:

:help smartindent

Even better, you can embed these settings in your source for portability:

:help auto-setting

To see your current settings:

:set all

As graywh points out in the comments, smartindent has been replaced by cindent which "Works more cleverly", although still mainly for languages with C-like syntax:

:help C-indenting
Neuron
  • 5,141
  • 5
  • 38
  • 59
Ken
  • 77,016
  • 30
  • 84
  • 101
  • Thanks - smartindent (as a name) was new to me. I hadn't managed to work out which option did the trick on MacOS X. – Jonathan Leffler Oct 24 '08 at 17:55
  • Even with those settings applied, if I press ‘o’ in a line indented with spaces, the new line is indented with tabs :-( How can I change this behaviour? – Azat Razetdinov Dec 04 '08 at 09:04
  • 4
    If you have expandtab set then it should be using spaces. Do you also "set compatible"? That has various side effects including resetting expandtab to its default of "off" – Ken Dec 04 '08 at 14:59
  • 66
    Sorry, but smartindent was replaced by cindent, which itself is only appropriate for C-style syntax. Turning on either in your vimrc can be a problem when working with other languages. Just use "filetype indent on" instead. – graywh Feb 01 '10 at 20:43
  • 2
    Well, smartindent is *also* only for C-style syntax and is essentially deprecated. – graywh Jul 07 '10 at 16:31
  • 2
    Ken: You should update your answer, see http://stackoverflow.com/a/23426067/2987828 which is more up to date. – user2987828 Feb 13 '15 at 10:06
  • 2
    I noticed when I do `backspace`, wim will only delete one space at a time, which is annoying. Any solutions? – Fermat's Little Student Nov 15 '15 at 05:00
  • It seems this actually added a tab the size of 8 spaces now. – User Nov 18 '15 at 19:03
  • 4
    if I enable expandtab, is there a way to actually input the tab character in the text anyway? – Daniele Segato Mar 16 '16 at 10:47
  • 3
    @DanieleSegato should work in insert mode : http://stackoverflow.com/questions/4781070/how-to-insert-tab-character-when-expandtab-option-is-on-in-vim – Ken Mar 16 '16 at 14:53
  • @graywh can you explain the filetype line? The others have nice comments and I'm struggling to understand the help – JonnyRaa Oct 06 '17 at 15:26
  • 1
    @JonnyLeeds `:filetype on` enables filetype detection (so FileType autocmds will work). `:filetype plugin on` enables the loading of filetype-specific scripts in ftplugin directories when the filetype is set. The same goes for `:filetype indent on`. All three can be combined into a single line. – graywh Oct 17 '17 at 17:02
  • Note that this broke ``vim`` for me in Vagrant 2.0.0 when I edited the file with ``vim``. It got stuck after vim opened a file - you couldn't do anything except ``Ctrl + C``. However, mysteriously, it works again after I simply opened the file with ``nano`` and saved. No idea what causes that. – Juha Untinen Nov 09 '17 at 07:37
  • Add `set nu` if you want to display line numbers :) – code_dredd May 25 '18 at 04:20
  • You could comment out`filetype plugin indent on` for preventing multi-lines paste problem such as Cmder. – Nick Tsai Jun 11 '18 at 10:44
  • This is great worked like a charm. I felt like I was wasting time removing tabs when I forgot to hit the space bar x number of times. – PAT-O-MATION Nov 15 '20 at 16:36
276

Related, if you open a file that uses both tabs and spaces, assuming you've got

set expandtab ts=4 sw=4 ai

You can replace all the tabs with spaces in the entire file with

:%retab
netjeff
  • 7,968
  • 4
  • 27
  • 30
  • 11
    FYI, if you dont want your tab to be replaced by spaces, remove the expandtab line. – Eno Feb 23 '12 at 20:54
  • 7
    Aren't tabs whitespace? ;-) – Rob Wells Feb 26 '14 at 16:12
  • 13
    @Rob-Wells: I changed "whitespace" to "spaces". Are you happy now? ;-) – netjeff Feb 28 '14 at 21:04
  • Could you explain what that first line means? – Nic Sep 21 '16 at 00:49
  • 4
    expandtab determines if tabs are expanded to spaces. ts = tabstop = Number of spaces that a in the file counts for. sw = shiftwidth = Number of spaces to use for each step of (auto)indent. ai = autoindent = Copy indent from current line when starting a new line. – mcmacerson Nov 26 '17 at 14:37
93

The best way to get filetype-specific indentation is to use filetype plugin indent on in your vimrc. Then you can specify things like set sw=4 sts=4 et in .vim/ftplugin/c.vim, for example, without having to make those global for all files being edited and other non-C type syntaxes will get indented correctly, too (even lisps).

Santosh Kumar
  • 26,475
  • 20
  • 67
  • 118
graywh
  • 9,640
  • 2
  • 29
  • 27
  • 10
    IMHO, better than the answer that has been marked correct. filetype indent on supersedes cindent and smartindent. – 0fnt Jul 04 '10 at 10:59
73

To have 4-space tabs in most files, real 8-wide tab char in Makefiles, and automatic indenting in various files including C/C++, put this in your ~/.vimrc file:

" Only do this part when compiled with support for autocommands.
if has("autocmd")
    " Use filetype detection and file-based automatic indenting.
    filetype plugin indent on

    " Use actual tab chars in Makefiles.
    autocmd FileType make set tabstop=8 shiftwidth=8 softtabstop=0 noexpandtab
endif

" For everything else, use a tab width of 4 space chars.
set tabstop=4       " The width of a TAB is set to 4.
                    " Still it is a \t. It is just that
                    " Vim will interpret it to be having
                    " a width of 4.
set shiftwidth=4    " Indents will have a width of 4.
set softtabstop=4   " Sets the number of columns for a TAB.
set expandtab       " Expand TABs to spaces.
Shervin Emami
  • 2,695
  • 25
  • 17
  • 1
    Why don't you need an`else` ? It seems to me like the last lines overwrite the makefile-specific in all cases – lucidbrot Jun 17 '17 at 07:28
  • 8
    Hi @lucidbrot, the "autocmd FileType make" statement basically tells vim some settings to use whenever it opens a Makefile. Whereas the lines below it are setting the defaults. In other words, the "tabstop=8 ..." settings are applied later when the file is opened, and will overwrite the "tabstop=4 ..." settings that apply on initialization. – Shervin Emami Jun 19 '17 at 11:10
  • 2
    +1 for making it extensible. I chose this one, because the comments about what each part does allow me to set things up exactly my way (without breaking anything), because I know what everything is doing. Hooray! – bballdave025 Dec 30 '21 at 06:00
66

On many Linux systems, like Ubuntu, the .vimrc file doesn't exist by default, so it is recommended that you create it first.

Don't use the .viminfo file that exist in the home directory. It is used for a different purpose.

Step 1: Go to your home directory

cd ~

Step 2: Create the file

vim .vimrc

Step 3: Add the configuration stated above

filetype plugin indent on
set tabstop=4
set shiftwidth=4
set expandtab

Step 3: Save file, by pressing Shift + ZZ.

Erick
  • 1,408
  • 14
  • 19
  • 14
    Dont use `Shift + ZZ` it will create .swp file. use `wq`. – shas Dec 31 '15 at 06:49
  • 8
    @shas: ["ZZ" is equivalent to ":x"](http://vimdoc.sourceforge.net/htmldoc/editing.html#ZZ), which is the same as ":wq", except that it only saves if the file has been changed... (`Ctrl-Z` is another story...) – Gert van den Berg Jun 09 '17 at 14:36
  • 2
    @shas That simply untrue. If you don't want a swap file for an edit sesion, you have to run `vim -n `. A swap file is not something that is generated at save time; that would pretty much defeat its purpose, since swap files become useful in recovering abruptly terminated edit sessions. – Kaz Feb 06 '20 at 21:02
  • Detailed description can be found here.(https://vim.fandom.com/wiki/Converting_tabs_to_spaces) – Ramganesh Sep 22 '20 at 04:28
37

The recommended way is to use filetype based indentation and only use smartindent and cindent if that doesn't suffice.

Add the following to your .vimrc

set expandtab
set shiftwidth=2
set softtabstop=2
filetype plugin indent on

Hope it helps as being a different answer.

Chaudhry Junaid
  • 372
  • 5
  • 15
18

edit your ~/.vimrc

$ vim ~/.vimrc

add following lines :

set tabstop=4
set shiftwidth=4
set softtabstop=4
set expandtab
phk
  • 2,002
  • 1
  • 29
  • 54
Yusuf Ibrahim
  • 1,591
  • 5
  • 21
  • 46
17

From the VIM wiki:

:set tabstop=4
:set shiftwidth=4
:set expandtab
User
  • 23,729
  • 38
  • 124
  • 207
11

The auto-indent is based on the current syntax mode. I know that if you are editing Foo.java, then entering a { and hitting Enter indents the following line.

As for tabs, there are two settings. Within Vim, type a colon and then "set tabstop=4" which will set the tabs to display as four spaces. Hit colon again and type "set expandtab" which will insert spaces for tabs.

You can put these settings in a .vimrc (or _vimrc on Windows) in your home directory, so you only have to type them once.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Joey Gibson
  • 7,104
  • 1
  • 20
  • 14
2

Firstly, do not use the Tab key in Vim for manual indentation. Vim has a pair of commands in insert mode for manually increasing or decreasing the indentation amount. Those commands are Ctrl-T and Ctrl-D. These commands observe the values of tabstop, shiftwidth and expandtab, and maintain the correct mixture of spaces and tabs (maximum number of tabs followed by any necessary number of spaces).

Secondly, these manual indenting keys don't have to be used very much anyway if you use automatic indentation.

If Ctrl-T instead of Tab bothers you, you can remap it:

:imap <Tab> ^T

You can also remap Shift-Tab to do the Ctrl-D deindent:

:imap <S-Tab> ^D

Here ^T and ^D are literal control characters that can be inserted as Ctrl-VCtrl-T.

With this mapping in place, you can still type literal Tab into the buffer using Ctrl-VTab. Note that if you do this, even if :set expandtab is on, you get an unexpanded tab character.

A similar effect to the <Tab> map is achieved using :set smarttab, which also causes backspace at the front of a line to behave smart.

In smarttab mode, when Tab is used not at the start of a line, it has no special meaning. That's different from my above mapping of Tab to Ctrl-T, because a Ctrl-T used anywhere in a line (in insert mode) will increase that line's indentation.

Other useful mappings may be:

:map <Tab> >
:map <S-Tab> <

Now we can do things like select some lines, and hit Tab to indent them over. Or hit Tab twice on a line (in command mode) to increase its indentation.

If you use the proper indentation management commands, then everything is controlled by the three parameters: shiftwidth, tabstop and expandtab.

The shiftwidth parameter controls your indentation size; if you want four space indents, use :set shiftwidth=4, or the abbreviation :set sw=4.

If only this is done, then indentation will be created using a mixture of spaces and tabs, because noexpandtab is the default. Use :set expandtab. This causes tab characters which you type into the buffer to expand into spaces, and for Vim-managed indentation to use only spaces.

When expandtab is on, and if you manage your indentation through all the proper Vim mechanisms, the value of tabstop becomes irrelevant. It controls how tabs appear if they happen to occur in the file. If you have set tabstop=8 expandtab and then sneak a hard tab into the file using Ctrl-VTab, it will produce an alignment to the next 8-column-based tab position, as usual.

Kaz
  • 55,781
  • 9
  • 100
  • 149
  • All your mappings should use the non-recursive variants. Mapping go `` can use that syntax rather than literals. Lastly, mapping `` in normal mode will also map `` (they are the same character), so I don’t recommend that (you lose a nifty piece of vim functionality – D. Ben Knoble Feb 07 '20 at 14:15
  • 1
    @D.BenKnoble I don't recommend any of this; I use Ctrl-T, Ctrl-D, and < > myself. That's using Vim as intended. People used to using Tab in other editors might not like that, that's all. – Kaz Feb 07 '20 at 15:43
2

Afterall, you could edit the .vimrc,then add the conf

set tabstop=4

Or exec the command

2

Simplest one will be in vim file or simply edit the .vimrc

set tabstop=4
ashish
  • 361
  • 3
  • 8