Vim: can indentation use spaces after non-whitespace? - vim

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.

Related

How do I make vim treat $ as an identifier character?

I'd like to have vim (after pressing Ctrl+]) look up tags containing special characters like $ or #. I can do it with the :tag command (e.g., tag $some$symbol) but it doesn't work with Ctrl+].
How can I configure what vim treats as an identifier?
Looking at :help CTRL-], it says:
CTRL-] Jump to the definition of the keyword under the
cursor. Same as ":tag {name}", where {name} is the
keyword under or after cursor.
From there, one might find :help 'iskeyword', or end up with :help word, which explains:
A word consists of a sequence of letters, digits and underscores, or a
sequence of other non-blank characters, separated with white space (spaces,
tabs, ). This can be changed with the 'iskeyword' option. An empty line
is also considered to be a word.
Therefore, you need to add $ to the 'iskeyword' option:
:setlocal iskeyword+=$
Making that permanent
The 'iskeyword' option is local to buffer, and many syntax scripts rely on correct settings for highlighting. Therefore, it's not recommended to change this globally for all filetypes (with :set, in your ~/.vimrc).
Instead, you should identify the (few) filetype(s) were you need this, and then define this only locally.
Put the corresponding :setlocal command into ~/.vim/after/ftplugin/{filetype}.vim, where {filetype} is the actual filetype (e.g. java). (This requires that you have :filetype plugin on; use of the after directory allows you to override any default filetype settings done by $VIMRUNTIME/ftplugin/{filetype}.vim.)
Alternatively, you could define an :autocmd FileType {filetype} setlocal iskeyword+=$ directly in your ~/.vimrc, but this tends to become unwieldy once you have many customizations.

Indenting after newline following new indent level vim

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

Automatically indent code with broken indentation in vim

I am working with a CMS where the code's indentation is a mess. Is it possible to fix it automatically with vim, running some command?
Generally you can use the = operation to indent.
See :help =
(You'll also need to have filetype indent on in your vimrc to enable different indentation rules for each type of file you'll edit)
gg=G will reindent a whole file. (gg move to beginning of the file, = will reindent every line under motion, G goes to the end of the file)
By default, Vim support well C and C like language. See :help C-indenting for options. You'll probably need to adjust these options before reformating your files. You'll have to define set cindent in your .vimrc if you want to use the "smart" indentations that is controlled by cinoptions.
See :help indent-expressionfor other languages.
In addition, you'll probably will have to fiddle withshiftwidth, expandtab and tabstop options if you want to use whitespaces or tab to indent.
For example, if you to replace all tab by 4 spaces, you 'll have to use:
set shiftwidth=4 " used by >>, << and tab.
set tabstop=4 " number of space characters used when displaying TAB
set expandtab " replace TAB by spaces
I usually do this with ggVG=. gg = go to file start, V = mark lines, G = go to file end, = = indent.
Maybe it is not the fewest keystrokes to do this, but I think it's easy to remember.

Pressing "Home" in Vim on an Indented Line

I have a bad habit of using the 'home' key to go back to the beginning of a line. As I recently started using vim I noticed that when I press the home key on a lined that is indented, it returns me to the very beginning of the line. In Notepad++ (the editor I used to use) it would return me to the beginning of the code on that line, right after the indent.
Is there some way to replicate this behavior in vim? Usually, when I'm pressing home it's in the Insert mode for me to (usually) stick a variable there.
I have set smartindent in my vimrc, with set noautoindent as a "tips" page told me to make sure to disable autoindent (although it didn't seem to be enabled in the first place - perhaps that option is extraneous.)
There are two usual ways to go to the "beginning" of a line in Vim:
0 (zero) go to the first column of text
^ go to the first non-whitespace on the line
I find that using 0w is usually the most convenient way for me to go to the first nonblank character on a line, it's the same number of keys as ^ and is easier to reach. (Of course, if there are no leading spaces on the line, don't press w.)
You could remap Home to be the same as ^ (the docs say Home's default function is equivalent to the movement command 1|):
:map <Home> ^
:imap <Home> <Esc>^i
Which should make the insert mode mapping be equivalent to escaping out of insert mode, pressing ^ and then returning to insert mode. I don't know about the best method of mapping a motion command for use inside insert mode, so this may break something, but it seems to work.
As to your indentation settings, they shouldn't have an effect on movement controls, but I also think you probably would prefer to have them set differently. autoindent just keeps your current indentation for new lines (so if you place 4 spaces at the beginning of a line, after you press return your new line will also have 4 spaces placed in front of it). I don't know why you wouldn't want that, since it's pretty useful in pretty much any programming language, or even just freeform text. smartindent on the other hand implements a couple of hard-coded lightly C-ish indentation rules, like indenting after an opening {, and deindenting after a closing }, but doesn't automatically carry over indentation from previous lines. The docs recommend keeping autoindent on if you use smartindent.
However, smartindent is useless for languages that don't meet its hard-coded rules, or even actively harmful (like when it automatically removes indentation from any line starting with a '#', which it thinks is a preprocessor directive but is wrong for python programmers trying to write an indented comment).
So vim also includes a more advanced indentation mode, filetype indentation, which allows flexible indentation rules on a per-language/filetype basis and is the preferred indentation mode for most people (even for C-like languages). If you do use filetype indentation, it's best to turn off smartindent (otherwise it can interfere with the filetype indentation, like moving all comment lines to column 0 in python files).
Personally, I always have autoindent on, use filetype when available, and never use smartindent. My .vimrc includes:
set autoindent " doesn't interfere with filetype indents, and is useful for text
if has("autocmd")
" Enable file type detection and indentation
filetype plugin indent on
set nosmartindent
endif
I imagine there's something you could do to have smartindent turned on only when filetype indenting doesn't exist for a filetype, if you're editing that many different C-like languages with no filetype indentation available.
Here’s what I have in my .vimrc. This maps Home to move to the beginning of the
text if you are anywhere in the line, and column 0 if you are at the beginning
of the text.
function ExtendedHome()
let column = col('.')
normal! ^
if column == col('.')
normal! 0
endif
endfunction
noremap <silent> <Home> :call ExtendedHome()<CR>
inoremap <silent> <Home> <C-O>:call ExtendedHome()<CR>
Note: I am using a keyboard layout that maps Home to Alt Gr+A, that why I’m using this. If you have to leave the letter field of your keyboard to reach Home, you should probably go to normal mode instead.
You could also use _ in Normal mode to go to the first non-whitespace character of the current line. You can also use a count with this motion.
_ <underscore> [count] - 1 lines downward,
on the first non-blank character linewise.
Try pressing 0 (also see :help 0)
also, this might help:
:imap <C-Home> <esc>0a

Tab key == 4 spaces and auto-indent after curly braces in Vim

How do I make vi-Vim never use tabs (converting spaces to tabs, bad!), makes the tab key == 4 spaces, and automatically indent code after curly brace blocks like Emacs does?
Also, how do I save these settings so I never have to input them again?
I've seen other questions related to this, but it always seems to be a little off from what I want.
As has been pointed out in a couple of other answers, the preferred method now is NOT to use smartindent, but instead use the following (in your .vimrc):
filetype plugin indent on
" show existing tab with 4 spaces width
set tabstop=4
" when indenting with '>', use 4 spaces width
set shiftwidth=4
" On pressing tab, insert 4 spaces
set expandtab
In your [.vimrc:][1] file:
set smartindent
set tabstop=4
set shiftwidth=4
set expandtab
The help files take a bit of time to get used to, but the more you read, the better Vim gets:
:help smartindent
Even better, you can embed these settings in your source for portability:
:help auto-setting
To see your current settings:
:set all
As graywh points out in the comments, smartindent has been replaced by cindent which "Works more cleverly", although still mainly for languages with C-like syntax:
:help C-indenting
Related, if you open a file that uses both tabs and spaces, assuming you've got
set expandtab ts=4 sw=4 ai
You can replace all the tabs with spaces in the entire file with
:%retab
The best way to get filetype-specific indentation is to use filetype plugin indent on in your vimrc. Then you can specify things like set sw=4 sts=4 et in .vim/ftplugin/c.vim, for example, without having to make those global for all files being edited and other non-C type syntaxes will get indented correctly, too (even lisps).
To have 4-space tabs in most files, real 8-wide tab char in Makefiles, and automatic indenting in various files including C/C++, put this in your ~/.vimrc file:
" Only do this part when compiled with support for autocommands.
if has("autocmd")
" Use filetype detection and file-based automatic indenting.
filetype plugin indent on
" Use actual tab chars in Makefiles.
autocmd FileType make set tabstop=8 shiftwidth=8 softtabstop=0 noexpandtab
endif
" For everything else, use a tab width of 4 space chars.
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.
On many Linux systems, like Ubuntu, the .vimrc file doesn't exist by default, so it is recommended that you create it first.
Don't use the .viminfo file that exist in the home directory. It is used for a different purpose.
Step 1: Go to your home directory
cd ~
Step 2: Create the file
vim .vimrc
Step 3: Add the configuration stated above
filetype plugin indent on
set tabstop=4
set shiftwidth=4
set expandtab
Step 3: Save file, by pressing Shift + ZZ.
The recommended way is to use filetype based indentation and only use smartindent and cindent if that doesn't suffice.
Add the following to your .vimrc
set expandtab
set shiftwidth=2
set softtabstop=2
filetype plugin indent on
Hope it helps as being a different answer.
From the VIM wiki:
:set tabstop=4
:set shiftwidth=4
:set expandtab
edit your ~/.vimrc
$ vim ~/.vimrc
add following lines :
set tabstop=4
set shiftwidth=4
set softtabstop=4
set expandtab
The auto-indent is based on the current syntax mode. I know that if you are editing Foo.java, then entering a { and hitting Enter indents the following line.
As for tabs, there are two settings. Within Vim, type a colon and then "set tabstop=4" which will set the tabs to display as four spaces. Hit colon again and type "set expandtab" which will insert spaces for tabs.
You can put these settings in a .vimrc (or _vimrc on Windows) in your home directory, so you only have to type them once.
Firstly, do not use the Tab key in Vim for manual indentation. Vim has a pair of commands in insert mode for manually increasing or decreasing the indentation amount. Those commands are Ctrl-T and Ctrl-D. These commands observe the values of tabstop, shiftwidth and expandtab, and maintain the correct mixture of spaces and tabs (maximum number of tabs followed by any necessary number of spaces).
Secondly, these manual indenting keys don't have to be used very much anyway if you use automatic indentation.
If Ctrl-T instead of Tab bothers you, you can remap it:
:imap <Tab> ^T
You can also remap Shift-Tab to do the Ctrl-D deindent:
:imap <S-Tab> ^D
Here ^T and ^D are literal control characters that can be inserted as Ctrl-VCtrl-T.
With this mapping in place, you can still type literal Tab into the buffer using Ctrl-VTab. Note that if you do this, even if :set expandtab is on, you get an unexpanded tab character.
A similar effect to the <Tab> map is achieved using :set smarttab, which also causes backspace at the front of a line to behave smart.
In smarttab mode, when Tab is used not at the start of a line, it has no special meaning. That's different from my above mapping of Tab to Ctrl-T, because a Ctrl-T used anywhere in a line (in insert mode) will increase that line's indentation.
Other useful mappings may be:
:map <Tab> >
:map <S-Tab> <
Now we can do things like select some lines, and hit Tab to indent them over. Or hit Tab twice on a line (in command mode) to increase its indentation.
If you use the proper indentation management commands, then everything is controlled by the three parameters: shiftwidth, tabstop and expandtab.
The shiftwidth parameter controls your indentation size; if you want four space indents, use :set shiftwidth=4, or the abbreviation :set sw=4.
If only this is done, then indentation will be created using a mixture of spaces and tabs, because noexpandtab is the default. Use :set expandtab. This causes tab characters which you type into the buffer to expand into spaces, and for Vim-managed indentation to use only spaces.
When expandtab is on, and if you manage your indentation through all the proper Vim mechanisms, the value of tabstop becomes irrelevant. It controls how tabs appear if they happen to occur in the file. If you have set tabstop=8 expandtab and then sneak a hard tab into the file using Ctrl-VTab, it will produce an alignment to the next 8-column-based tab position, as usual.
Afterall, you could edit the .vimrc,then add the conf
set tabstop=4
Or exec the command
Simplest one will be n vim file
set tabstop=4

Resources