vim ident: don't remove tabs indent when closing } - vim

When I have the following in vim with cindent or vim-javascript turned on:
if(bla){
#
(# shows cursor)
I type a new line:
if(bla){
#
and then close the }
if(bla){
}
The problem is, now I go back up to the previous line and
if(bla){
#
}
There's no more indent after #! Now you might think this isn't annoying, but when I am working in files with multiple levels of tab indenting it destroys my productivity because of the way I code. Is there any way to make closing a } NOT destroy the tab indent before the lines?

The tab is not deleted because you closed the {}, it's deleted because you didn't enter any text on that line.
I've had many variants of the following mappings in my ~/.vimrc to "fix" that issue (waiting for a cleaner solution) for a couple of years:
inoremap {<CR> {<CR>}<C-o>==<C-o>O
inoremap {; {<CR>};<C-o>==<C-o>O
Both do the same thing: they close the {} and put the cursor where it belongs. There are a bunch of autoclosing plugins that offer that feature but I've found them too annoying in the long run.

What are you using to move up to the blank line? The arrow keys (a bad habit, according to some)? Maybe you don't need to put in the closing brace until you've written the stuff above it? You could also just not leave the blank line, hit the closing brace, then type <esc>O to open above. Or if you like to leave the blank line for some reason just use S to reset the indent.

Related

Why does typing a curly brace in vim insert mode indent the line to the left?

This happens even with an empty .vimrc
When on a file with a .html extension, if it is currently in this state:
<p>
t
</p>
and I put my cursor over the "t", press a (append)
<p>
t_
</p>
and then type "{", the line will indent left and result in this:
<p>
t{_
</p>
with my cursor still in insert mode at "_"
I've tried looking up "indent" and "{" in various vim help files but I can't find anything on why it automatically indents the line to the left.
Is there any way to disable this auto left indent?
Your indenting is being handled by a function called HtmlIndent(). If you open vim with vim --clean testIndent.html from the command line, then type :set indentexpr? in vim and hit enter, you will see indentexpr=HtmlIndent(). See :h indentexpr to read more about what this setting means. As for what the function does, you would need to look at where it is defined. You can type :e $VIMRUNTIME/**/indent/html.vim into vim and (before hitting enter) hit tab. Vim should automatically fill in the location of vim's html indent file. For me on Ubuntu with vim 8.2, this is at /usr/local/share/vim/vim82/indent/html.vim. The HtmlIndent() function is defined there.
That is the first part of the answer. The second part answers why your indenting is triggered by typing the { character. HtmlIndent() determines what the indent of a line should be, but the indentkeys setting triggers a line's proper indent to be evaluated and set when certain keys are typed. See :h indentkeys. If you open vim again with vim --clean testIndent.html and type :set indentkeys?, you will see something like indentkeys=o,O,<Return>,<>>,{,},!^F. The { character in that setting is causing vim to evaluate, through HtmlIndent(), what it believes is the proper indent for the line you are on every time you type {.
Given this, you have several options. You could look for someone who has made their own addition to vim's html indenting settings. You could simply disable this automatic indenting. You could attempt to modify vim's HtmlIndent() function. One very simple option for you is to remove the { character from the indentkeys setting. You can do this with :set indentkeys-={. Then do :set indentkeys? again to verify that { has been removed. You could remove } the same way. Note that this will only prevent vim from automatically re-indenting a line every time you type the {, } characters. It will not actually change vim's opinion on what that line's indent should be, so in other cases where vim evaluates and sets a line's indent, it will still do so in a way you disagree with.

How to insert tabs on new line in Vim before a character is typed

If I write an if statement in my C program, press enter three times, then write a comment, the below is my output. Notice the two lines between the condition and the comment are completely empty.
if(my_condition) {
<Tab>// My comment here
My issue is that Vim does not insert any tab character(s) between the beginning of the line and the cursor position until a character is typed. This is very annoying for me, because I like to move my cursor up and down the block of code often. Since there isn't a real tab on the two lines, if I moved up one line my cursor would go to the beginning of the line, instead of staying on the same column. I come from Sublime Text and other editors where this has never been a problem.
Is there a plugin or setting such that I can accomplish the following?
if(my_condition) {
<Tab>
<Tab>
<Tab>// My comment here
All help is appreciated. I've looked into using Visual mode, but have had undesirable side effects of enabling it all the time. Certainly there is a simple way to automatically add the tabs when I make a new line?
This is very annoying for me, because I like to move my cursor up and down the block of code often.
Well, as you might have noticed, switching to vim means that you need to change your own editing behavior. And that might be the toughest, more than learning the new commands, because habits die hard!
I'm not saying that you should stop scrolling around your function in an useless manner, though, but that you should stop moving around with the "cursor" keys in insert mode.
When you're doing movements when in insert mode it has the side effect you're exposing as "inconvenient", but it also has the side effect of breaking the "repeat" command (.). After a cursor movement in insert mode, a . will only repeat characters typed after that movement.
So, what you should consider in your editing behavior, is to avoid empty lines, avoid trailing spaces/tabs and never move around in insert mode. Insert mode is for insertion, and the normal mode is for moving around and doing actions on the text.
There are a lot of move commands you can abuse in normal mode (j/k, <C-e>/<C-y>, {/}, …).
That being said, if you get yourself in a situation where you've fscked the indentation, you might want to keep on editing, not caring about the indent, and once you're back in normal mode issue a =i{ that will indent everything within the block following the syntax file (and your indent settings).

vim 7.4 comment/uncomment lines in Vim without plugins

I tried out answers in What's a quick way to comment/uncomment lines in Vim?, but they don't work. Pressing shift i on visual mode after selection just brings me in insert mode. I run it with --noplugin, no use.
You might need to take visual block before proceeding , Ctrl-v to use it. More at help blockwise-visual
Then, use any nagivation keys like h,j,k,l, followed by I, then insert your comment character like # or // and finalize by Esc.
This should comment whole block.
To uncomment, repeat the same operation of visual block and navigation but replace I by any delete operation like x for # or 2x for //.
Hope this helps
There are many ways to comment/uncomment in Vim. Anyway, assuming "C++-style" comments, eg. // foobar…
Commenting a single line
I// <Esc>
Uncommenting a single line
^dw
Commenting several lines
vjjj
:'<,'>norm! I// <CR>
or
<C-v>jjj
I// <Esc>
Uncommenting several lines
vjjj
:'<,'>norm! ^dw<CR>
or
<C-v>jjjllld

Vimrc settings to emulate Sublime's parenthesis auto-completion

How do I emulate Sublime text's auto complete behavior for curly braces {} on vim? Basically, when a parenthesis is opened, it should auto close in the same line, and when <CR> is pressed the cursor should go to the next line with a block indentation and } should fall in line with the original indention of the line containing the {. If my question is not clear, this is the default behavior of most code editors when dealing with {}.
The Automatically append closing characters page on the Vim Tips Wiki has everything from simplistic mappings to complete plugin solutions. There seem to be issues with the latest Vim 7.4 version, though.
There exist many plugins with similar features as Ingo pointed out.
lh-brackets, that I'm maintaining, has the features you describe:
{ inserts {} and moves the cursor in between (and also inserts a placeholder after the closing bracket
hitting <cr> while within a pair of curly-brackets will insert another newline in-between (and indent correctly)

Issue with smartindent in Vim

In vim with smartindent on:
Press Enter after say an if-statement
Type in {
Press Enter twice
Type in }
If you hit ↑ and go to the previous line, indentation is removed from the blank line.
Even the vim documentation says that:
If you do not type anything on the new line except <BS> or CTRL-D and then type <Esc>, CTRL-O or <CR>, the indent is deleted again.
Is there any way to keep this indentation and not have it deleted?
Use Shift+S to start editing on a blank line (from command mode, obviously). This will start your cursor off with the expected level of indentation.
Another doesn't-answer-the-question-as-asked-but-is-a-better-solution-overall:
When typing an opening brace in insert mode, this will insert a matching set of braces
and leave the cursor on a new line in the middle.
:imap { {<CR>}<Esc>O
Similarly, this will auto-insert matching parens and square brackets.
:imap ( ()<Left>
:imap [ []<Left>
(Strip off the leading : when adding to vimrc.)
As I commented on Victor's answer, changing Vim's indentation behavior will leave "empty" lines containing extraneous spaces throughout your files. IMO, this is completely intolerable.
When this happens to me, I sometimes use ddko (or ddO) to delete the line without enough spaces and open a new line with the correct indent. Or, I'll just press A and then Tab enough times to get to the correct indent.
the article here talks about you're very same problem, and what to put in vimrc to fix it.
inoremap <CR> <CR><Space><BS>
nnoremap o o<Space><BS>
nnoremap O O<Space><BS>
I havn't exactly tested this tho.
also the same article links to a shorter alternate solution.
My preferred method is {<CR>}<esc>shift+o as it outpaces {<CR><CR>}<esc>k shift+s by several strokes. I get in a rut with it, though, and end up just using o or O to grab new, properly-indented lines off an empty when I should be using S.
That is, set up your bracing structure and open line-above:
if (true) {
}//cursor here, press shift-o
And you get the indenting you expect.
The open-above trick isn't any fewer keypresses than <up><end><cr>, but with escape remapped and shift being chorded, you can throw it in quite fast.
Also, don't forget your manual indent reset and block-movement. If you're inside a mangled curly brace block, simply use ={ (or =i{ if you're on top of one of the braces). I use that when I have a Good Idea that needs to see text asap, and I don't worry about any formatting frippery until I take a breather.

Resources