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 communityIs it possible to convert tabs to spaces, while maintaining text alignment?
Simply replacing only works usefully when there are no leading characters.
You can use the :retab
command. From
:help :retab
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
then just :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
(ie. :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 &tabstop
)
just like :retab
does. (I happen to prefer to specify it manually).
Vim provides !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:
:%s/\t/ /g
or as suggested by @Shahbaz:
:%s/^\t\+/ g
So only the tabs used in indentation are converted.
Explanation:
%
represents the entire buffer/file (:help :%
)s
stands for substitute (:help sub-replace-special
)\t
, or ^I
stands for tab
- use as many spaces as you need per one tabg
- stands for global, and it'll convert multiple occurences of tabs in the same lineThen 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 .vimrc
file:
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 tidy
Related:
%s/^\t\+/ g
so that only the tabs used in indentation are converted. Also, gg=G
could be catastrophic with languages like python.
Try using:
expand -t 4 input_filename output_filename
expand
is a command-line tool to convert tabs to spaces, which you can run from a shell or with :!expand
.
It's in POSIX so it should be available on most systems. unexpand
will do the reverse, by the way.
:%!expand -t 4
inside of vim. Better yet, you could also use the current shift width option: :exe '%!expand -t ' . &shiftwidth
Feb 1, 2016 at 21:29
For completeness, =
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=G
would fix the entire file, where gg
moves the cursor to the beginning of the file, then =
is applied, and G
moves the cursor to the end of the file. Reference: link
:h vim-faq
and search/tab characters
. The hard to memorize tag is:h faq-14.16
.