In vim, I just changed my tabs from 2 to 4 spaces. This works good - when I hit tab, it indents 4 spaces. When I am adding new lines that are the same indentation, it works. However - when I need a new level of indentation, and hit enter, it only indents 2 spaces.
previously fixed code{
previously indented code;
if (new amount of indenting should happen){
only this much is given by vim;
but hitting tab takes me here (where I want to be);
}
}
Any idea what setting I might have to change to get this to work? I've tried every one I could find (autoindent, cindent, setting all kinds of tabstop type variables), to no avail.
When you check the help file by running :help tabstop, you willl get:
'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.
so put this in your .vimrc file everything is OK.
set expandtab "Use softtabstop spaces instead of tab characters for indentation
set shiftwidth=4 "Indent by 4 spaces when using >>, <<, == etc.
set softtabstop=4 "Indent by 4 spaces when pressing <TAB>
set autoindent "Keep indentation from previous line
set smartindent "Automatically inserts indentation in some cases
set cindent "Like smartindent, but stricter and more customisable
Related
A great answer I read as to all the different type of tab-related settings in vim is in the answer here: Redefine tab as 4 spaces. However, is there a way to actually see how those settings apply and affect a file? I have used something like:
:set list
But it doesn't really show me anything more than a bunch of $ (linebreaks), and I don't see anything for spaces or tabs in my file. Is there a way to view all the space-like characters in vim so that I can play around with, for example, how tabstop might work and how softtabstop might work, and how they may all work together, etc.
There are four things in vim related to tabs:
tabstop
expandtab
shiftwidth
softtabstop
Refer to useful reference of tab stops in vim
tabstop Set tabstop to tell vim how many columns a tab counts for. Linux kernel code expects each tab to be eight columns wide. Visual
Studio expects each tab to be four columns wide. This is the only
command here that will affect how existing text displays.
expandtab When expandtab is set, hitting Tab in insert mode will produce the appropriate number of spaces.
shiftwidth Set shiftwidth to control how many columns text is indented with the reindent operations (<< and >>) and automatic
C-style indentation.
softtabstop Set softtabstop to control how many columns vim uses when you hit Tab in insert mode. If softtabstop is less than tabstop
and expandtab is not set, vim will use a combination of tabs and
spaces to make up the desired spacing. If softtabstop equals tabstop
and expandtab is not set, vim will always use tabs. When expandtab is
set, vim will always use the appropriate number of spaces.
You can see current settings in vim by using below commands, in command mode:
:set tabstop?
:set expandtab?
:set shiftwidth?
:set softtabstop?
You can set values for current session by using commands below, in command mode:
:set tabstop=4
:set expandtab #if you want to remove expand tab, set noexpandtab
:set shiftwidth=4
:set softtabstop=4
Alternatively, if you want to make the changes permanent, you can make changes to vimrc file:
It is located in the below path:
~/.vimrc on Unix;
$HOME/_vimrc on Windows
For gvim, you can go to Edit -> startup settings to see current vimrc
settings and edit them.
You need to add a line to vimrc like given below:
set tabstop=4 softtabstop=4 shiftwidth=4 expandtab
This should work:
:set lcs=space:_,tab:>~ list
I have set ts=4 in vimrc file. So, one tab moves the cursor worth 4 spaces.
I use the =i{ command to indent the block of code but when I do that, the indentation comes to the effect of indenting the code inside the {} by 8 space characters or 2 tabs, if I do it manually.
How do I make VIM on indent my code by 4 spaces or 4 tab space size when I am using the =i{ command ?
Set shiftwidth as well:
set tabstop=4
set shiftwidth=4
And if you want a tab character instead of 4 spaces, do this also:
set noexpandtab
Is it possible to make VIM use spaces for tabs, when the cursor has non-whitespace characters before it?
eg:
(Assuming TAB is --->, • is a space.)
--->function(arg);••••••/* comment */
// ^ use spaces when pressing TAB after non-whitespace chars.
Otherwise I want real tabs when pressing tab.
This is useful when tabs are used for initial indentation, but the alignment for all text after uses spaces.
This is not possible to do automatically without scripting or a plugin.
The "Smart Tabs" plugin was designed for this task. http://www.vim.org/scripts/script.php?script_id=231
To make the problem happen a little less frequently there are the built-in preserveindent and copyindent options to prevent losing your existing tab indent when expandtab is set.
Use :set expandtab.
This will expand all tabs to spaces, during insert, even the ones at the beginning of the line (which probably is the best).
Use CTRL-V<Tab> to insert a tab.
From vim help (:help expandtab)
'expandtab' 'et' boolean (default off)
local to buffer
{not in Vi}
In Insert mode: Use the appropriate number of spaces to insert a
<Tab>. Spaces are used in indents with the '>' and '<' commands and
when 'autoindent' is on. To insert a real tab when 'expandtab' is
on, use CTRL-V<Tab>. See also :retab and ins-expandtab.
NOTE: This option is reset when 'compatible' is set.
Use :set shiftwidth=4 (or :set shiftwidth=8) to control how many spaces are added per indent.
'shiftwidth' 'sw' number (default 8)
local to buffer
Number of spaces to use for each step of (auto)indent. Used for
'cindent', >>, <<, etc.
Other settings of interest are softtabstop, tabstop and autoindent.
My current setting assumes 8 spaces; how could I redefine it?
It depends on what you mean. Do you mean:
you want tab characters in your file to appear 4 character cells wide?
you want the tab key to generate an indent consisting of 4 space characters
Depending on which behavior you need, one of the following sets of settings should work:
If you want tab characters in your file to appear 4 character cells wide:
set tabstop=4
If your code requires use of actual tab characters these settings prevent unintentional insertion of spaces (these are the defaults, but you may want to set them defensively):
set softtabstop=0 noexpandtab
If you also want to use tabs for indentation, you should also set shiftwidth to be the same as tabstop:
set shiftwidth=4
To make any of these settings permanent add them to your vimrc.
If you want pressing the tab key to indent with 4 space characters:
First, tell vim to use 4-space indents, and to intelligently use the tab key for indentation instead of for inserting tab characters (when at the beginning of a line):
set shiftwidth=4 smarttab
If you'd also like vim to only use space caharacters, never tab characters:
set expandtab
Finally, I also recommend setting tab stops to be different from the indentation width, in order to reduce the chance of tab characters masquerading as proper indents:
set tabstop=8 softtabstop=0
To make any of these settings permanent add them to your vimrc.
More Details
In case you need to make adjustments, or would simply like to understand what these options all mean, here's a breakdown of what each option means:
tabstop
The width of a hard tabstop measured in "spaces" -- effectively the (maximum) width of an actual tab character.
shiftwidth
The size of an "indent". It's also measured in spaces, so if your code base indents with tab characters then you want shiftwidth to equal the number of tab characters times tabstop. This is also used by things like the =, > and < commands.
softtabstop
Setting this to a non-zero value other than tabstop will make the tab key (in insert mode)
insert a combination of spaces (and possibly tabs) to simulate tab stops at this width.
expandtab
Enabling this will make the tab key (in insert mode) insert spaces instead of
tab characters. This also affects the behavior of the retab command.
smarttab
Enabling this will make the tab key (in insert mode) insert spaces or tabs to
go to the next indent
of the next tabstop when the cursor is at the beginning of a line (i.e. the
only preceding characters are whitespace).
For further details on any of these see :help 'optionname' in vim (e.g. :help 'tabstop')
To define this on a permanent basis for the current user, create (or edit) the .vimrc file:
$ vim ~/.vimrc
Then, paste the configuration below into the file. Once vim is restarted, the tab settings will apply.
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
or shorthand for vim modeline:
vim :set ts=4 sw=4 sts=4 et :
There are few settings which define whether to use spaces or tabs.
So here are handy functions which can be defined in your ~/.vimrc file:
function! UseTabs()
set tabstop=4 " Size of a hard tabstop (ts).
set shiftwidth=4 " Size of an indentation (sw).
set noexpandtab " Always uses tabs instead of space characters (noet).
set autoindent " Copy indent from current line when starting a new line (ai).
endfunction
function! UseSpaces()
set tabstop=2 " Size of a hard tabstop (ts).
set shiftwidth=2 " Size of an indentation (sw).
set expandtab " Always uses spaces instead of tab characters (et).
set softtabstop=0 " Number of spaces a <Tab> counts for. When 0, featuer is off (sts).
set autoindent " Copy indent from current line when starting a new line.
set smarttab " Inserts blanks on a <Tab> key (as per sw, ts and sts).
endfunction
Usage:
:call UseTabs()
:call UseSpaces()
To use it per file extensions, the following syntax can be used (added to .vimrc):
au! BufWrite,FileWritePre *.module,*.install call UseSpaces()
See also: Converting tabs to spaces.
Here is another snippet from Wikia which can be used to toggle between tabs and spaces:
" virtual tabstops using spaces
set shiftwidth=4
set softtabstop=4
set expandtab
" allow toggling between local and default mode
function TabToggle()
if &expandtab
set shiftwidth=8
set softtabstop=0
set noexpandtab
else
set shiftwidth=4
set softtabstop=4
set expandtab
endif
endfunction
nmap <F9> mz:execute TabToggle()<CR>'z
It enables using 4 spaces for every tab and a mapping to F9 to toggle the settings.
I copied and pasted this into my .vimrc file:
" size of a hard tabstop
set tabstop=4
" always uses spaces instead of tab characters
set expandtab
" size of an "indent"
set shiftwidth=4
The first 2 settings mean that when I press Tab I get 4 spaces.
The third setting means that when I do V> (i.e. visual and indent) I also get 4 spaces.
Not as comprehensive as the accepted answer but it might help people who just want something to copy and paste.
One more thing, use
:retab
to convert existing tab to spaces
http://vim.wikia.com/wiki/Converting_tabs_to_spaces
Put your desired settings in the ~/.vimrc file -- See below for some guidelines and best practices.
There are four main ways to use tabs in Vim:
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.
Note: Setting 'tabstop' to any other value than 8 can make your file appear wrong in many places (e.g., when printing it).
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.
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.
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' ischanged.
Source:
vimdoc.sourceforge.net/htmldoc/options.html#'tabstop'
:help tabstop
Add line
set ts=4
in
~/.vimrc file for per user
or
/etc/vimrc file for system wide
:set sw=4
See Mastering the VI editor
My basic ~/.vimrc with comment:
set number " show line number
set tabstop=2 " set display width of tab; 1 tab = x space with
set expandtab " transform tab to x space (x is tabstop)
set autoindent " auto indent; new line with number of space at the beginning same as previous
set shiftwidth=2 " number of space append to lines when type >>
Permanent for all users (when you alone on server):
# echo "set tabstop=4" >> /etc/vim/vimrc
Appends the setting in the config file.
Normally on new server apt-get purge nano mc and all other to save your time. Otherwise, you will redefine editor in git, crontab etc.
Make sure vartabstop is unset
set vartabstop=
Set tabstop to 4
set tabstop=4
For permanent change, create the file ~/.vim/plugin/tab_expander.vim with the content
set tabstop=4 softtabstop=4 expandtab shiftwidth=4 smarttab
To prevent touching the ~/.vimrc, thus keeping other default settings untouched.
Vim is very accommodating when it comes to tab Vs. space preferences. As I understand it, the tabstop setting indicates the width of a tab character. The shiftwidth setting specifies how many columns to increment/decrement when using the << and >> commands, whereas the softtabstop setting influences the amount of whitespace to be inserted when you press the Tab key in insert mode. If expandtab is on, the tab key inserts softtabstop number of space characters. Whereas with expandtab switched off, pressing the Tab key inserts a the smallest possible number of tab+space characters that matches softtabstop. (Please correct me if I'm wrong.)
This final point makes me wonder: is there a practical case where you wouldn't want shiftwidth == tabstop && tabstop == softtabstop? I can't think of one. As far as I am concerned, it would be most convenient if I could set all 3 of these to the same value, in one single assignment. e.g. calling:
:set stab=4
which would be equivalent to running:
:set tabstop=4 softtabstop=4 shiftwidth=4
Can anyone suggest how this could be done?
UPDATE
Thanks for the replies so far from too much php, hobbs and kaiser.se. Rather than reply to each individually, I'm updating the question here.
Softtabstop with expandtab switched off
I said above that with expandtab switched off, pressing the Tab key inserts a the smallest possible number of tab+space characters that matches softtabstop. I stand by that, but I think I need to explain what I meant. I shall attempt to do so by way of a few examples. To follow along, run :set list so that you can see tab characters.
tabstop=4 softtabstop=2 shiftwidth=4 noexpandtab
In insert mode, pressing the tab key inserts 2 space characters. Press the tab key a second time, and instead of inserting two more space characters (for a total of 4 space characters) it replaces the previous 2 spaces with a single tab character. Tabstop is set to 4, so a single tab character has the same width as 4 spaces.
tabstop=4 softtabstop=6 shiftwidth=4 noexpandtab
In insert mode, pressing the tab key inserts 1 tab character plus 2 spaces. The tab character has a width of 4, so the total width is 6, and this is achieved using 3 characters. Pressing the tab key a second time inserts two tab characters, and removes the two spaces that were inserted previously. The total width is 12, and this is achieved using 3 characters.
In both of these examples, Vim inserts the minimum possible number of tab+space characters that matches softtabstop.
If I am working with expandtab switched off, I can't see myself wanting the extra granular control that can be achieved by setting softtabstop to a different value from tabstop. It would still be useful for me to be able to set tabstop, softtabstop and shiftwidth to the same value with a single command.
Does expandtab make softtabstop redundant?
tabstop=4 softtabstop=0 shiftwidth=4 expandtab
In insert mode, pressing the tab key inserts 4 spaces. Pressing the delete key deletes a single space - so you have to backspace 4 times if you hit the tab key by accident.
tabstop=4 softtabstop=4 shiftwidth=4 expandtab
In insert mode, pressing the tab key inserts 4 spaces. Pressing the backspace key deletes 4 spaces.
If I am working with expandtab switched on, I would prefer the delete key to remove the same amount of whitespace as the tab key inserts. So in this case, too, I feel that it would be useful to be able to assign the same value to tabstop, softtabstop and shiftwidth simultaneously.
A shortcut would still be useful
It's great that Vim provides so much flexibility, but I can't see myself needing it. I just want to be able to choose the width of a tab, and whether it is a 'hard' tab (using a tab character) or a 'soft' tab (made up of spaces). Toggling between hard and soft tabs is easy enough (:set expandtab!), but I wish it was more straightforward to set the width of tab, without having to fiddle with 3 different parameters.
So my proposed suggestion for something like :set stab=4 still sounds good to me.
Creating a stab option in Vim itself would not be easy, but I've whipped up this command/function that you can drop in your .vimrc (or a plugin file if you're super-organized). Use :Stab and you will be prompted for an indent level and whether or not to use expandtab. If you hit enter without giving it a new indent level, it will just print the current settings.
" put all this in your .vimrc or a plugin file
command! -nargs=* Stab call Stab()
function! Stab()
let l:tabstop = 1 * input('set shiftwidth=')
if l:tabstop > 0
" do we want expandtab as well?
let l:expandtab = confirm('set expandtab?', "&Yes\n&No\n&Cancel")
if l:expandtab == 3
" abort?
return
endif
let &l:sts = l:tabstop
let &l:ts = l:tabstop
let &l:sw = l:tabstop
if l:expandtab == 1
setlocal expandtab
else
setlocal noexpandtab
endif
endif
" show the selected options
try
echohl ModeMsg
echon 'set tabstop='
echohl Question
echon &l:ts
echohl ModeMsg
echon ' shiftwidth='
echohl Question
echon &l:sw
echohl ModeMsg
echon ' sts='
echohl Question
echon &l:sts . ' ' . (&l:et ? ' ' : 'no')
echohl ModeMsg
echon 'expandtab'
finally
echohl None
endtry
endfunction
This is my first attempt at writing VimScript, but here goes:
function! Stab(value)
let &shiftwidth = a:value
let &softtabstop = a:value
let &tabstop = a:value
endfunc
If I put this in my .vimrc file, I can call it by running :call Stab(X), where X is the desired tab width. This is an adequate solution for now, but if anyone can suggest a way of making it easier to call I would be grateful.
I've also created a function that quickly summarizes the current settings, which I have mapped to ctrl-Tab:
nmap <C-Tab> :call TabParams()<CR>
function! TabParams()
echo "tabstop: ".&tabstop
echo "shiftwidth: ".&shiftwidth
echo "softtabstop: ".&softtabstop
endfunc
Well, I put up a 100 point bounty for this answer, and now I've half solved it myself. Not sure if I can accept my own answer...
You can in edit mode also use Ctrl-T to indent and Ctrl-D to deindent to the next indentation level as set by shiftwidth, regardless of the tabstop, softtabstop or expandtab settings. Vim will automatically add/remove spaces or tabs to bring you to the right column.
If you use these commands to control indentation instead of Tab/Backspace you don't have to worry about all these tab settings fitting together and always get to the correct indentation level.
If expandtab is set then (as too much php points out), softtabstop becomes redundant. The only reason you might set shiftwidth differently from tabstop would be to cater to an odd habit; for instance, you use four-space indents but you prefer tab to insert eight spaces.
If expandtab is unset then things get fuzzier. If you want your code to look the same in with cat and non-vim editors as it does in vim, then tabstop should always be set at 8; in this case you would set softtabstop and shiftwidth both to your preferred indent level. If you instead prefer that every "physical tab" in the file represents one indent level, you would set tabstop and shiftwidth to your preferred indent level and leave softtabstop at zero (setting it equal to tabstop is equivalent except that if you change tabstop it will get out of sync, while zero just means "ignore this please").
Your understanding of softtabstop and expandtab is wrong - so the stab option you suggest wouldn't be very useful.
expandtab is for when you want to use spaces instead of tabs for everything. If you set expandtab, then Vim ignores the softtabstop option and uses tabstop and shiftwidth to work out how many spaces to insert.
softtabstop is only for when you would like to use a mix of tabs and spaces, allowing you to indent with fine control (2 or 4 spaces), while keeping tab width at a higher value (usually 8) so that text appears in the other applications. Setting softtabstop=tabstop doesn't accomplish anything because Vim will always use tabs for indenting.
Update: As kaizer.se has pointed out, if you are using expandtab, then you still need to set softtabstop if you want Vim to backspace multiple spaces as though they are a tab.
Are you changing your white space settings so often you really need a function to manage that? If you are messing with tabstop a lot and also setting expandtab, you are probably going to have a mess over time as you change files with different values passed to stab. Today I use :call stab (4), tomorrow it's :call stab (2) and last week it was :call stab (8). Sounds like even if you write it, you'll soon stop using it.
If you plan to always pass the same value to stab, why not just edit your global settings? In vim:
:e $MYVIMRC
and add the following:
set tabstop=4
set shiftwidth=4 "tabs are 4 spaces wide (default = 8)
set expandtab "Convert tabs to spaces
This is how my .vimrc is setup.
One useful option is softtabstop=-1 which will set it to the value of shiftwidth.
You can also set shiftwidth to 0, in which case the tabstop value will be used.