autoindent in vim for selected text - vim

1) Is there anyway to autoindent/retab on a set of lines, rather than the entire file?
set shiftwidth=4
set expandtab
set tabstop=4
has been defined in my .vimrc.
What I want is to select a bunch of lines and apply indentation only on them. This is because the file is large and I just want to clean my line of codes. By doing :retab, I would have to force the whole file to be reindented.
For example select the following code and reindent automatically
def hello(self):
line1
line2
to
def hello(self)
line1
line2
2) Is there any way that I can reverse tab? Something like Shift-Tab in Eclipse. It goes back 4 spaces.

You can try this one...
Shift + V to enter in Visual mode
Then press j until you reach the text you want to be ident.
Finally press
=, it will ident automatically your selected code.
If you want to ident the whole code just type gg=G.

What I want is to select a bunch of lines and apply indentation only on them
You can apply indentation to certain lines in Visual mode. To do this follow these steps:
Position your cursor in the first line to be indented
Enter visual mode by typing shift + v
Move down, typing j until you reach the last line to be indented (alternately you can type line # + G if you know the line number of the last line to be indented).
Type >
Another solution is to do this with a regex in command-line mode:
2,5s/\v(.*)/\t\1/g
Here the line range is specified in the first two numbers of the regex (in this case from line 2 to 5).

To answer both of your questions at the same time, you can use the > and < operators. Since they are operators, they behave just like y, d, c, and all the other operators do, so you must supply them with a motion. For example, >> will indent the current line (with 4 spaces), and >j will indent the current line and the line below. >G will indent everything to the end of the buffer, etc.
Similarly, < will unindent whatever you specify.
In your specific example, there are two different approaches I would recommend.
Use normal mode. This one kinda depends on how large your function is. If it's just the two lines, you could put your cursor on line1, and type <j>,. (Of course, if your function has more than 2 lines, you'll need to adjust). Unfortunately you need to unindent before reindenting because otherwise you'll end up with 5 spaces, which I assume you don't want.
Use visual mode. This one is slightly less convenient unless you modify your .vimrc because calling > or < in visual mode will drop your visual selection. That's why I have the following in my .vimrc:
"Make it easier to indent a visual selection several times.
xnoremap > >gv
xnoremap < <gv
With this setup, you can visually select the lines you would like to reindent, and then do <>. IMO, this is the best solution, and I frequently use this kind of workflow.

Most (if not all) Ex commands take a range so you could just visually select the lines and do :'<,'>retab.
Or :12,16retab.
Or :.,+9retab.
And so on.
See :help :retab and :help :range.

Related

How can I select all the text on a line without the indentation in Vim?

I want to replace all the text of the current line under the cursor and change the text so I start typing the new code. But I want to keep the indentation.
Currently I am using ddO. This will delete the line and open a line before the cursor in insert mode, it's good because vim will take notice of the previous indentation and place the cursor as expected.
But I want to use c similar to ciw (change inner word) because it feels natural to think "change the line". Vc is almost what I want but it will lose the indentation.
Any idea ?
Maybe you are looking for cc?
:h cc
["x]cc Delete [count] lines [into register x] and start
insert |linewise|. If 'autoindent' is on, preserve
the indent of the first line.
You can try this (to put in your vimrc):
:onoremap ii :<c-u>normal! v^o$h<cr>
:xnoremap ii ^o$h
The first line defines the mapping ii which will work with any command expecting a motion (cii, dii, yii...).
The second mapping allows to use it in visual mode (e.g., vii).
Brief explanation of the :normal! command:
v : visual mode, ^ : go to 1st non-blank char, o : go to the opposite side of the selection, $h : go past to the end of line then go 1 char left.

Delete backwards from cursor to the end of the previous line in Vim?

Say I want to edit the following line:
var myVar =
"I am a string!";
So that it looks like this:
var myVar = "I am a string!";
Is there a movement that goes to the end of the previous line?
What you want is the line join command, J.
In normal mode, put your cursor anywhere on the var myVar = line and type J (capital j).
Direction-wise motions work with J - 5J indents 5 lines below the cursor, etc. You can also select a range of lines using visual mode (v to start visual mode selection) and join them all into one using J.
The &joinspaces option affects this behavior as well. When it's "on" (set joinspaces or set js) it adds two spaces after a sentence-ending mark (i.e. '.', '?', or '!') when joining lines. set nojoinspaces or set nojs to turn that off and insert only one space.
Also,
:set backspace=indent,eol,start
The backspace option determines the behavior of pressing the backspace key (). By default, Vim’s backspace option is set to an empty list. There are three values that can be added that each independently alter the behavior of the backspace key. These are indent, eol, and start.
When indent is included, you can backspace over indentation from autoindent. Without it, Vim will not allow you to backspace over indentation.
When eol is included, you can backspace over an end of line (eol) character. If the cursor is at the first position of a line and you hit backspace, it will essentially be joined with the line above it. Without eol, this won’t happen.
When start is included, you can backspace past the position where you started Insert mode. Without start, you can enter Insert mode, type a bit, and then when backspacing, only delete back as far as the start of Insert mode.
The backspace default is absurd, you are going to want to add all of the above to your Vim settings.
See :h 'backspace' for more details.
kJ will do what you want and is probably what you should be using, however if you want to do exactly what you've asked for Delete backwards from cursor to the end of the previous line then you can do the following:
:set virtualedit+=onemore
^ " go to the start of the line
d?$<cr>
?$<cr> is a movement that goes to the end of the previous line.
:set virtualedit+=onemore allows the cursor to move just past the end of the line, without which we would end up deleting the last character of the line, which in the example you have given would be the trailing space.
You could then create a mapping to do this (:nohl just clears the search highlighting):
:nnoremap <leader>J ^d?$<cr>:nohl<cr>
Although a simpler mapping to achieve the same thing would be:
:nnoremap <leader>J kJ

Vim: Indent with one space (not shiftwidth spaces)

The default VIM indentation commands indent by shiftwidth spaces
e.g.
>> Indent line by shiftwidth spaces
<< De-indent line by shiftwidth spaces
Is there any way to indent with one or n (where n != shiftwidth) space(s)?
One way to do that is to vertically select a column in the block with Ctrl+V then, I to insert vertically and then type a space and <Esc>. But is there a better way?
I'm not sure that there is a better way. But, there are a few ways that you could do it (that I can think of anyway)...
Your Visual Block Solution
Like you said: press Ctl-V select the lines you want, press I to insert, and enter the number of spaces.
Search
Similar to the above but a little more flexible - you can use with with the 'select paragraph' vip command, or any range really: press v or vip or what have you to select the range, and the type :s/^/{n spaces} where {n spaces} is the number of spaces you want to insert.
Its a little more verbose, but works pretty well for pretty much any range. Heck, if you wanted to do the whole file you could do Ctl-A (OS dependent) and indent the whole file (or just skip the whole visual mode thing and just do it command mode...as in :1,$s/^/{n spaces}
Note that you don't have to include the third slash in s/// since you aren't putting any switches at the end of the search.
Global
Maybe you want to only indent lines that match some pattern. Say...all lines that contain foo. No problem: type :g/foo/s/^/{n spaces}
Global is especially handy if its multi-line sections with a similar pattern. You can just escape into normal mode land and select the lines you want and indent accordingly: :g/foo/norm Vjj:s/^/{n spaces}Ctl-V{Enter}. Little more complicated with that extra Ctl-V{Enter} at the end but useful under certain circumstances.
Use tabstop and shiftwidth
Yes, if your doing it a lot - I'd do :set ts=2 and :set et and :set sw=2 and use >> and << every which way...
Make a Function
Okay, so still not brief enough and for whatever reason you need to do this a lot and you can't abide messing with sw, et and ts settings. No problem, just write up a quick function and give it a localleader mapping:
function! AddSpace(num) range
let s:counter = 0
let s:spaces = ''
while s:counter < a:num
let s:spaces .= ' '
let s:counter = s:counter + 1
endwhile
execute a:firstline .','. a:lastline .'s/^/'. s:spaces
endfunction
:map <LocalLeader>i :call AddSpace(3)Ctl-V{enter}
Maybe just knowing more than one way to do this is better than only knowing one? After all, sometimes the best solution depends on the problem :)
Indent a block of code in vi by three spaces with Visual Block mode:
Select the block of code you want to indent. Do this using Ctrl+V in normal mode and arrowing down to select text. While it is selected, enter ":" to give a command to the block of selected text.
The following will appear in the command line: :'<,'>
To set indent to 3 spaces, type le 3 and press enter. This is what appears: :'<,'>le 3
The selected text is immediately indented to 3 spaces.
Indent a block of code in vi by three spaces with Visual Line mode:
Open your file in VI.
Put your cursor over some code
Be in normal mode press the following keys:
Vjjjj:le 3
Interpretation of what you did:
V means start selecting text.
jjjj arrows down 4 lines, highlighting 4 lines.
: tells vi you will enter an instruction for the highlighted text.
le 3 means indent highlighted text 3 lines.
To change the number of space characters inserted for indentation, use the shiftwidth option:
:set shiftwidth = <number>
Have a look here for more details.
You can also add that to your .vimrc file.
If I'm understanding correctly, you could use:
ctrl+V, jj then ':le n', where n is the number of spaces to indent.
http://vim.wikia.com/wiki/Shifting_blocks_visually
Place marks ('a' and 'b') between the code you want to indent:
<position cursor at top of block>
m a
<position cursor at bottom of block>
m b
Do a replace command such that each newline character between your marks is replaced with the number of spaces desired (in this example, 2 spaces):
:'a,'bs/^/ /g
If white space indentation already exists and you want to increase it further by one or more columns, then select a block of one or more white space columns using Ctrl-V, yank and paste it in the same place.
I had to dedent by a given number of spaces, amount, inside a vim script. This worked:
let sw_setting = &shiftwidth
set shiftwidth=1
exe "normal v" . amount . "<"
let &shiftwidth = sw_setting
A side-effect is that it resets the last visual mode selection. Instead, you may wish to edit the exe... line such that it executes "<<" repeated amount times in normal mode. That is: instead of normal v3<, make it normal <<<<<<, if amount is 3.
I like to use Space to indent a visual selection with a single space:
vnoremap <silent> <space> :s/^/ /<CR>:noh<CR>gv
And I couldn’t get Shift+Space to dedent, so I use z:
vnoremap <silent> z :s/^\s\=//<CR>:noh<CR>gv

How to tab without losing block

I have been using vim for about 3 weeks now and have been having problem with tabs.
What I usually do is do gg to go to the top, do a ctrl+v for visual block, do a G to select everything to below(one column), do a $ to select to the right, then press < or > to tab.
However having to do all this, I lose the selection and I have to do all those commands to do another tab.
How do I not lose selection? Or is there a better way?
NOTE: I sometimes don't need to select everything sometimes just a portion of the file.
To reselect a visual selection use the gv command followed by your command. Although this is not the best way.
Instead select the whole buffer with ggVG then indent with >. This will indent the selection. To repeat the command again just press .. The . command will repeat the last normal command, in this case the > command. If you have indent a few times to many just use the undo command, u, as many times as necessary. This vimcast is a great screencast describing this technique and this one describe more indention techniques.
Others prefer the following mappings:
xnoremap <Tab> >gv
xnoremap <S-Tab> <gv
I am not sure what is important here: being able to do multiple indents in a single go or keeping the visual block. Assuming you want to do multiple indents, just prefix the > with a number, e.g. 3> will indent the selected block three times.
Also, you don't need to select the entire line to indent it (i.e. the $ is not needed).

Vim: Smart indent when entering insert mode on blank line?

When I open a new line (via 'o') my cursor jumps to a correctly indented position on the next line. On the other hand, entering insert mode while my cursor is on a blank line doesn't move my cursor to the correctly indented location.
How do I make vim correctly indent my cursor when entering insert mode (via i) on a blank line?
cc will replace the contents of the current line and enter insert mode at the correct indentation - so on a blank line will do exactly what you're after.
I believe that the behaviour of i you describe is correct because there are many use cases where you want to insert at that specific location on a blank line, rather than jumping to wherever vim guesses you want to insert.
Well this actually wasn't as bad as I thought it would be. One way to enable this is to add the following to your ~/.vimrc
"smart indent when entering insert mode with i on empty lines
function! IndentWithI()
if len(getline('.')) == 0
return "\"_ccO"
else
return "i"
endif
endfunction
nnoremap <expr> i IndentWithI()
It simply checks for an empty line when you hit 'i' from insert mode. If you are indeed on an empty line it will delete it and open a new one, effectively leveraging the working 'open line' behavior.
Note: "_ before the cc makes sure that your register doesn't get wiped
On an empty line, to enter insert mode correctly indented, you can simply use s.
Note that s is a synonym for cl, so if you're not actually on an empty line, it'll end up deleting a single character and not indenting. In that case, you're better off using cc, as sml suggested some 18 months ago. But I've frequently improved my score at VimGolf by using this shortcut, so thought I'd mention it. ;)

Resources