Is it possible to convert tabs to spaces, while maintaining text alignment?
Simply replacing only works usefully when there are no leading characters.
Vi and Vim Stack Exchange is a question and answer site for people using the vi and Vim families of text editors. It only takes a minute to sign up.Sign up to join this community
You can use the
:retab command. From
Replace all sequences of white-space containing a
<Tab>with new strings of white-space using the new tabstop value given. If you do not specify a new tabstop size or it is zero, Vim uses the current value of
'tabstop'. [...] With
'expandtab'on, Vim replaces all tabs with the appropriate number of spaces.
Note that the command accepts a range, so you can make a visual selection and
:retab the selected lines.
You can use
:retab, as stated, however, this will change all tabs to spaces, not only tabs at the start of the line
So this (where
⇥ is a tab character):
if :; do ⇥echo "⇥hello" end
gets changed to (where
␣ is a space character):
if :; do ␣␣echo "␣␣hello" end
This can produce unexpected side-effects in some scenarios, and it's even more of an issue when changing spaces to tabs!
So, I wrote a little function to change only tabs/spaces at the start of the line:
" :retab changes *everything*, not just start of lines fun! Retab(expandtab) let l:spaces = repeat(' ', &tabstop) " Replace tabs with spaces if a:expandtab silent! execute '%substitute#^\%(' . l:spaces . '\)\+#\=repeat("\t", len(submatch(0)) / &tabstop)#e' " Replace spaces with tabs else silent! execute '%substitute#^\%(\t\)\+#\=repeat("' . l:spaces . '", len(submatch(0)))#e' endif endfun
With this version, you have to manually specify
expandtab in the function call
:call Retab(1) to change tabs to spaces), but you could also modify it
to take the current value of
&expandtab (as it already does with
:retab does. (I happen to prefer to specify it manually).
:retab! command which will replace all sequences of
<Tab> with new strings of white-space using the new tabstop (e.g.
:set tabstop=2) value given, but all tabs inside of strings can be modified (e.g. in a C program, you should use
\t to avoid this)!
So alternatively you can change all tabs into spaces using the following command:
or as suggested by @Shahbaz:
So only the tabs used in indentation are converted.
Note: there is a subtle difference between both commands. The first one will replace each Tab character by two spaces, the second one replace any number of leading Tab characters in a line by a single space.
%represents the entire buffer/file (
sstands for substitute (
^Istands for tab
- use as many spaces as you need per one tab
g- stands for global, and it'll convert multiple occurences of tabs in the same line
Then to correct indentation of the entire file, you may try: gg=G. Check: Re-indenting badly indented code for more details.
To use spaces by default instead of tabs, you need to add the following settings into your
set tabstop=2 " (ts) width (in spaces) that a <tab> is displayed as set expandtab " (et) expand tabs to spaces (use :retab to redo entire file) set shiftwidth=2 " (sw) width (in spaces) used in each step of autoindent (aswell as << and >>)
Alternative solution is to use
= could also be used to fix indentations, after you have specified that tabs are replaced with spaces. In normal mode, you can do so by typing
:set expandtab. Then
= could be used in two ways:
=would fix indentations of selected code blocks.
gg=Gwould fix the entire file, where
ggmoves the cursor to the beginning of the file, then
=is applied, and
Gmoves the cursor to the end of the file.