How to avoid indentation error after changing tab stops in Vim? - vim

I used to have 8-space tabs in Vim. Then I changed to 4 spaces, but now whenever I add a line to some code I had written before changing to 4 spaces, it gives me an indentation mismatch error even though everything is lining up nicely. Is there any way to avoid this problem?

Have you done a :%retab ...?

Have you changed just the tabstop option?
I use 4 spaces (fill with spaces when I hit tab, to insert actual tab hit ctrl-v tab). Here are the tab related settings from .vimrc:
" tabs
set tabstop=4
set shiftwidth=4
set expandtab
When you fill tab with spaces you will always insert spaces instead of tab and your code will always look the same.
When you use tabs each tool displays tab differently and you end up spending your time setting up how many spaces should be displayed for tab (8,4,3.5) instead of doing productive work.
Or choose one of these (from vim 7.1 help tabstop):
Note: Setting 'tabstop' to any other value than 8 can make your file
appear wrong in many places (e.g., when printing it).
There are four main ways to use tabs in Vim:
1. Always keep 'tabstop' at 8, set 'softtabstop' and 'shiftwidth' to 4
(or 3 or whatever you prefer) and use 'noexpandtab'. Then Vim
will use a mix of tabs and spaces, but typing <Tab> and <BS> will
behave like a tab appears every 4 (or 3) characters.
2. Set 'tabstop' and 'shiftwidth' to whatever you prefer and use
'expandtab'. This way you will always insert spaces. The
formatting will never be messed up when 'tabstop' is changed.
3. Set 'tabstop' and 'shiftwidth' to whatever you prefer and use a
|modeline| to set these values when editing the file again. Only
works when using Vim to edit the file.
4. Always set 'tabstop' and 'shiftwidth' to the same value, and
'noexpandtab'. This should then work (for initial indents only)
for any tabstop setting that people use. It might be nice to have
tabs after the first non-blank inserted as spaces if you do this
though. Otherwise aligned comments will be wrong when 'tabstop' is
changed.

For python code, you are probably best off with the following:
:set tabstop=8
:set shiftwidth=4
:set expandtab
That way you are still using the 'industry standard' 8 space tabs, but you won't be putting any of them into your file. That should keep your old code clean as well, although you'll have to go back through and manually move everything left over time. You'll definitely want to :retab everything too.
If you want to replace everything with 4 space indents do
:set tabstop=4
:retab
:set tabstop=8
This will re-indent everything using spaces at 4 spaces per tab, and set you back to sane defaults.
Obvously, this is subject to opinion, but in my book using tabs set to anything other than what you get when you cat the file is asking for trouble.

The best way to visualise a mismatch is to :set list which will show whitespace issues.
set listchars=tab:>-,trail:-,nbsp:+ "This is terminal friendly but you can make fancy
set list
I'd say this is an essential setting for python editing when spaced indents are the norm. Especially when a file is edited by a co worker.
I also double checked the style guideunder "Code lay-out". theres a python -tt option you might want to use as specified in http://www.python.org/dev/peps/pep-0008/. That will throw warnings and errors if you mix tabs with spaces.
You could incorporate this into your unit testing. It seems the pep is recommending 4 spaces for newer code. You might want to consider changing if you intend on contributing to open source projects.
also to be extra tidy I have for deleting whitespace at eol
nnoremap <leader>wd :%s/\s\+$//<cr>

Related

How to change the way vim displays hard tabs

How would you make vim display tabs as 4 spaces?
I tried playing with set list and set listchars But this only changes the 8 characters representing the the tab. I want to keep the tabs, but have them take 4 spaces instead of 8. Is this possible?
:h 'ts'
you will see:
'tabstop' 'ts' number (default 8)
local to buffer
Number of spaces that a <Tab> in the file counts for. Also see
|:retab| command, and 'softtabstop' option.
Note: Setting 'tabstop' to any other value than 8 can make your file
appear wrong in many places (e.g., when printing it).
There are four main ways to use tabs in Vim:
1. Always keep 'tabstop' at 8, set 'softtabstop' and 'shiftwidth' to 4
(or 3 or whatever you prefer) and use 'noexpandtab'. Then Vim
will use a mix of tabs and spaces, but typing <Tab> and <BS> will
behave like a tab appears every 4 (or 3) characters.
2. Set 'tabstop' and 'shiftwidth' to whatever you prefer and use
'expandtab'. This way you will always insert spaces. The
formatting will never be messed up when 'tabstop' is changed.
3. Set 'tabstop' and 'shiftwidth' to whatever you prefer and use a
|modeline| to set these values when editing the file again. Only
works when using Vim to edit the file.
4. Always set 'tabstop' and 'shiftwidth' to the same value, and
'noexpandtab'. This should then work (for initial indents only)
for any tabstop setting that people use. It might be nice to have
tabs after the first non-blank inserted as spaces if you do this
though. Otherwise aligned comments will be wrong when 'tabstop' is
changed.
The width of a Tab character is determined by the 'tabstop' option:
:set tabstop=4
Note that changing this from the default of 8 may affect how other programs display the file, and is therefore discouraged. In such a case, better insert literal space characters (via :set expandtab).

Have vim ai obey the formatting of spaces from the previous line

When I indent/format my code I use tabs for indentation, spaces for alignment. I feel that this is intuitive and very effective at keeping code nicely formatted independent of the tab width of other programmers (as long as they are using monospace).
I like to keep my code nicely formatted for other potential developers and this is one thing about vim that irks me and I want to know if there is a solution. Using the ai format in vim if you have a line that is 2 tabs followed by 9 spaces (assuming 4 space wide tabs) when you enter a new line vim will have the new line be 4 tabs and 1 space. Which is not the desired behavior( I would like it to be 2 tabs and 9 spaces, like the previous line).
My question is, is this even possible? If no, why not? If yes, how do I do it?
Try this in your ~/.vimrc:
set noexpandtab
set copyindent
set preserveindent
set softtabstop=0
set shiftwidth=4
set tabstop=4
It will add spaces though, if your current indentation is not a multiple of tabstop.

In vim, how can I modify all existing indents to be 2?

In vim, I set shiftwidth=2, but all my previous indents are still at the default 8. How can I change the previous indents from 8 to 2?
You can reindent the whole file with gg=G. gg goes to the first line, = indents (taking a movement), G goes to the last line.
If you're using set expandtab (like you should), you can modify the indentation in a file with
:%s/^ */ /
The settings affect how changes are made, but do not themselves make changes to the file.
If your original indents were achieved using hard tabs stops, then one trick you can do is this. Set the hard tab stop to 2:
:set ts=2
Now you have the two-space indentation (but achieved with hard tabs).
Now, do
:retab 8
This means, roughly, change the hard tab size to 8 (as if by :set ts=8) but at the same time edit all the tabbing in the buffer so that the indentation's appearance does not change.
So now the buffer is still indented to two spaces, but now :ts is back to 8.
If you have :expandtab set, then the indentation is now all spaces, otherwise it is a combination of 8-space tabs and spaces.
Even if this doesn't apply to your situation, retab is good to know because it's handy for dealing with sources that use hard tabs and that you'd like to convert to use spaces and a different indentation level at the same time.

Vim Configuration: How to expand tabs only when saving?

I love tabs, and prefer it to spaces in indentation.
But I'd like to transform tabs into 4-space groups when saving files. (Because the file may be opened and edited in other environments) And of course, those generated spaces should be converted back to tabs if I open the file again. (Assume that there are no 4 contiguous spaces in the original text)
Well in your .vimrc:
set noexpandtab
set tabstop=4
set shiftwidth=4
fun MyRetab()
set expandtab
retab
set noexpandtab
endfun
au FileWritePre *.YOURFILEEXTENSION call MyRetab()
But I don't know what you mean by "those spaces should be still recognized as tabs if I open the file again."
If you write a file spaces instead of tabs, well it can't be undone easily AFAIK. EDIT: see the super retab wiki page for undoing it!
NOTE if you have tab(s) in your source's string contents this will replace that as well!
In addition to Zsolt Botykai's answer, you could try using retab!, which attempts to replace spaces with tabs where appropriate. This seemed to work quite well when I just tried it, but I got a few erroneous tabs. I suppose it depends how good your assumption is that there no other sequences of 4 spaces other than expanded tabs.
HOWEVER... this all seems like a risky business. In my experience, when there are coding/encoding standards such as these, it is always easiest to adhere to them from the start. "Fixing-up" the file in this way is asking for trouble.
I think Vim does a good job of emulating tab-like behaviour while using only spaces. Have you tried using smarttab and expandtab?

How to configure vim for TAB/ident like this?

I would use vim like this:
Pressing TAB indent by 4 spaces (spaces not a TAB)
Existing TAB should treated as 8 space wide
Could you help me?
From :help 'ts:
There are four main ways to use tabs in Vim:
1. Always keep 'tabstop' at 8, set 'softtabstop' and 'shiftwidth' to 4
(or 3 or whatever you prefer) and use 'noexpandtab'. Then Vim
will use a mix of tabs and spaces, but typing and will
behave like a tab appears every 4 (or 3) characters.
2. Set 'tabstop' and 'shiftwidth' to whatever you prefer and use
'expandtab'. This way you will always insert spaces. The
formatting will never be messed up when 'tabstop' is changed.
3. Set 'tabstop' and 'shiftwidth' to whatever you prefer and use a
|modeline| to set these values when editing the file again. Only
works when using Vim to edit the file.
4. Always set 'tabstop' and 'shiftwidth' to the same value, and
'noexpandtab'. This should then work (for initial indents only)
for any tabstop setting that people use. It might be nice to have
tabs after the first non-blank inserted as spaces if you do this
though. Otherwise aligned comments will be wrong when 'tabstop' is
changed.
It sounds like you want sts=4 sw=4 ts=8.
I think thats
:set sw=4 ts=8 sta

Resources