Always indent in vim - vim

So far I've always used xemacs for source code editing (C++), but for several reasons i'd like to switch to or at least try out vim. One of the very basic things is indentation, where I'm super happy with xemacs behaviour. However I have yet to find a solution for having this behaviour in vim.
What I'm talking about is basically the ability to press Tab in any position of a line, and the line will always be indented to the correct level. This means:
1) pressing Tab multiple times will not indent multiple times, instead the text will be (re-)aligned to the indentation level suitable for the current code
2) pressing Tab e.g. in the middle of a word will not insert spaces or a tab in between this word, but rather indent the whole line
Is it possible to achieve this with vim?
Currently I have:
filetype indent plugin on
set cident
set autoindent
set shiftwidth=3
set softtabstop=3
set expandtab

In normal mode, pressing == should fix the indentation of the current line.
You can fix the indentation of several lines by:
selecting them and pressing =,
using a motion, =},
using a text-object, =ip.
In insert mode, you can fix the indentation of the current line with <C-o>== but the insertion point moves as well. You are not supposed to do that kind of thing in insert mode anyway.

Related

Why does x>> in vim have another indent than when im pressing tab?

When im using the vim command 4>> in vim to indent four lines of code vim indents the lines with 8 spaces, but if i indent these lines manually but pressing tab in front of them they are indented with 4 spaces which is what i have configured in my .vimrc file. It seems like the 4>> command is somehow bypassing my configuration..does someone know why this is happening..
Also, does someone know if there is a way to ident the other way as well and not just indent to the right but also to the left.
You seem to have inconsistent values of 'shiftwidth' (which governs the >> behavior and seems to be 8 in your case) and 'tabstop' / 'softtabstop' (which control the amount of spaces inserted when pressing Tab in insert mode; either 8/4 or 4/4 or 4/0 in your case).
Hitting TAB indents to the next multiple of the tabstop value.
Using >> indents by the value of the shiftwidth variable.
Also, does someone know if there is a way to ident the other way as well and not just indent to the right but also to the left.
<< is the opposite of >>

How to go back to previous indentation level in insert mode?

Sometimes vim's smartindent does not pick the correct level of indentation for the next line once you hit enter and you'd like to go back to the indentation level of the previous line and just go from there. I know that you can hit ctrl-d a few times to achieve this but it would be more useful for a key that immediately goes to the indentation level of the line above.
I don't know if it's pure coincidence, but Alexey Radev has just published the prev_indent plugin, which provides an insert mode mapping and :PrevIndent command to move the current line to the previous indentation level.
If you can't be bothered to install a plugin for such a simple task (I couldn't), try this simple mapping:
:inoremap <C-D> <Esc>:call setline(".",substitute(getline(line(".")),'^\s*',matchstr(getline(line(".")-1),'^\s*'),''))<CR>I
Now CtrlD in insert mode will do the deed: indent the current line like the previous line.
This works best before you start typing on the new line, because it will reset the cursor to just past the indentation.
In normal mode you can use < and > to increase or decrease indentation. They work as expected with movements, visual selection and >> << for the current line. You can also use = to chose the "correct" indentation level, again it works as expected with regards to movements etc.
So what I usually do is fix indentation errors in normal mode after I'm done editing, by a combination of block selecting and using =, and then fixing individual lines with << and >>.
You can use <C-O>=G to indent from cursor to end of file in insert mode. Or <C-O><< to remove one indentation level.

Using folds with synmaxcol in vim

Sometimes when I'm working on a project I want to play around with some data. Often times the data is on one line and is huge (>25k characters). I understand I could set nowrap and have this line just run off the screen, but I tend to like set wrap for other reasons. So, as a workaround I want to hide these long lines in a marker fold (e.g. {{{ long line }}}). This works fine but I run into a problem with synmaxcol for some reason. If the folded line exceeds synmaxcol then when I open the file, the syntax highlighting runs over. For example:
However, as soon as I open the fold the syntax corrects itself:
Having to open the fold every time is annoying though. As you can see in this example the line is not actually all that long -- it just exceeds synmaxcol. Since synmaxcol is exceeded at a "string" element, the rest of the file is highlighted as a string (so nothing but a singular double quote will stop it).
Why is this happening and how can I fix it? I've tried this with different syntax files and filetypes and it still occurs. I've also tried it with no plugins, a minimal vimrc (containing only syn on) and a modeline to set fdm=marker:synmaxcol=60 and it still happens.
You can manually enter :syntax sync fromstart to force Vim to rescan the syntax from the beginning of the opened file.
I would suggest defining a hotkey for convenience:
noremap <F5> <Esc>:syntax sync fromstart<CR>
inoremap <F5> <C-o>:syntax sync fromstart<CR>
Now you can press F5 to clean up most syntax highlighting problems.
Also, have a look at Vim's fixing syntax highlighting - wiki page
Moreover reading :help :syn-sync-first might shed some more light on the issue.
UPDATE:
I was able to reproduce this behavior on my machine (I'm running Vim 7.3.429).
However, when I wrapped the fold markers {{{ and }}} in block comments, vim correctly rendered the syntax. You can create appropriately wrapped fold-markers using the zf command. See Vim tips: Folding fun.
Normally Vim picks the correct blockcomment string based on the currently active syntax. However, my Vim is pretty vanilla and didn't recognize Ruby syntax. I could specify autocmd FileType ruby set commentstring==begin%s=end in my .vimrc file to set the proper block comment. See :fold-create-marker for more details.
Another solution is to set synmaxcol=0, which will effectively set it to infinity. This causes Vim to check the syntax of the entire line, no matter how long it is. However, I'm not sure what kind of performance penalty you'll have to pay for that.

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.

How to prevent Vim indenting wrapped text in parentheses

This has bugged me for a long time, and try as I might I can't find a way round it.
When I'm editing text (specifically latex, but that doesn't matter) files, I want it to auto-wrap at 80 columns. It does this, except if I happen to be in the middle of a parenthetical clause, it indents the text which is very annoying. For example, this works fine
Here is some text... over
two lines.
but this doesn't
Here is some text... (over
two
lines
If anyone can tell me how to turn this off (just for text/latex files) I'd be really grateful. Presumably it has something to do with the fact that this is desired behaviour in C, but I still can't figure out what's wrong.
:set nocindent
The other options do nothing, and the filetype detection doesn't change it.
There are three options you may need to turn off: set noai, set nosi, and setnocin (autoindent, smartindent, and cindent).
This may be related, when pasting from gui into terminal window, vim cannot distinguish paste modes, so to stop any odd things from occuring:
set paste
then paste text
set nopaste
I had similar issues trying to paste xml text, it would just keep indenting. :)
gvim, the gui version of vim, can detect paste modes.
You can have a look at the autoindent option :
autoindent - ai
Copy indent from current line when starting a new line (typing
in Insert mode or when using the "o" or "O" command). If you do not
type anything on the new line except and then type or
, the indent is deleted again. When autoindent is on,
formatting (with the "gq" command or when you reach 'textwidth' in
Insert mode) uses the indentation of the first line. When
'smartindent' or 'cindent' is on the indent is changed in specific
cases. The 'autoindent' option is reset when the 'paste' option is
set. {small difference from Vi: After the indent is deleted when
typing or , the cursor position when moving up or down is
after the deleted indent; Vi puts the cursor somewhere in the deleted
indent}.
From the official Vim documentation
filetype plugin indent on
This switches on three very clever
mechanisms:
Filetype detection. Whenever you start editing a file, Vim will try to
figure out what kind of file this
is. When you edit "main.c", Vim will
see the ".c" extension and
recognize this as a "c" filetype.
When you edit a file that starts with
"#!/bin/sh", Vim will recognize it as
a "sh" filetype. The filetype
detection is used for syntax
highlighting and the other two
items below. See |filetypes|.
Using filetype plugin files Many different filetypes are edited with
different options. For example,
when you edit a "c" file, it's very
useful to set the 'cindent' option to
automatically indent the lines. These
commonly useful option settings are
included with Vim in filetype plugins.
You can also add your own, see
|write-filetype-plugin|.
Using indent files When editing programs, the indent of a line can
often be computed automatically.
Vim comes with these indent rules for
a number of filetypes. See
|:filetype-indent-on| and
'indentexpr'.
:set noai
sets no auto indent tt may be smartindent though. Check out the doc and see if you can find something more
http://www.vim.org/htmldoc/indent.html

Resources