Is it possible to convert tabs to spaces, while maintaining text alignment?
Simply replacing only works usefully when there are no leading characters.
Is 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.
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.
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.
– Shahbaz
Mar 04 '17 at 15:49
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
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
– EvergreenTree
Feb 01 '16 at 21:29
:h vim-faqand search/tab characters. The hard to memorize tag is:h faq-14.16. – Hotschke Jul 23 '19 at 07:55