How to select from line to line in vi? - text

I frequently want to select multiple lines in vi. e.g. from line 1 to line 10.
So, what I usually do when I want to jump from line to line is I type :110 to jump to line 110, e.g.
And, when I want to select from line to line, I usually press v to get into visual mode, and then I just scroll down using k or l.
So, intuitively it makes sense to me to just press v, and then type :<line number>. but that doesn't work.
How to select from line X to line Y in vi?

Let's assume you want to highlight from line 10 to line 20. You can use:
10GV20G
Breakdown:
10 enters 10 into the buffer
G goes to the line number in the buffer
V enters visual line mode
20 enters 20 into the buffer
G goes to the line number in the buffer
Note that G means Shift+g (capital G).
Source and a : command are here.

Selection by itself isn't meaningful; you usually want to invoke a command on the selection. Many commands that work on the visual selection have a corresponding Ex command. With that, going through visual mode is unnecessary if you already know the exact ranges. The great benefit of visual mode is that you can interactively and iteratively adapt the selected area if there's no single motion or text object.
The benefit :help :range is that you can succinctly specify the lines. For example, lines 110 to 120 can be written as :110,120, but also as :110;+10.

simple just press Shift v line number gg
example: your current line to line 41
Just press Shift v 41 gg
note: you can move to selected line by press line number gg

If you set both number and relative number it becomes easy to see the target end line.
:set number relativenumber
So, let's say you are at the line 10 and the target line shows 11, you start your selection with capital V, then press 11j
V11j
If your block has blank lines before and after, just type vip (visuall inner paragraph)

Related

vim - when triggering a macro, normal mode isn't switched from insert mode (xterm)

For testing purpose I created simple macro which wraps current line into single quotes and goes to next line.
Here is output from the register the macro is saved in: I'^[A'^[j
And here is testing text:
Line number 1
Line number 2
if I trigger the macro on the line number 1, cursor position should be changed to the line number 2 and the text should be changed to:
'Line number 1'
Line number 2{CURSOR_POSITION}
Instead of the expected result, vim stays in insert mode at the end of line 1 and result is following:
'Line number 1'ê{CURSOR_POSITION}
Line number 2
...where {CURSOR_POSITION} is current cursor position
Why vim place ê character at the end of first line and doesn't go to the next line?
I got same result when I ran vim with --noplugin option.
I use xterm-256color
Vim 7.4
This is kind of a bug (discussion here). I know it is stupid but this should work :-)
I'^[A'^[1j
It is because ^[j can be interpreted as a Ctrl+V Alt+J (link here).

VIM column operation

Intro
In gVim under Windows i have to replace insert and mod in each string of file some character in a specifics position.
Example
QWAER;PA 0X000055;123WAAAA
TYUIO;PA 0Y000056;123VAAAA
need to become
QWAE#;PAX000055;123;WAAAA
TYUI#;PAY000056;123;VAAAA
modify char 5 in #
delete char 9,10
insert ; in original pos 22 or after delete in pos 20
More Info
Usually I do
Put cursor and beginning of text to select
Press CTRL-V (CTRL-Q in gVim) to begin select of the column
keep press SHIFT and selecte the interested area
the go at the end of file
then do the replace insert or modification.
(This is where I learn about Keyboard-only column block selection in GVim Win32, or why does Ctrl-Q not emulate Ctrl-V when mswin.vim is included?
and here i learn how to do the insert(http://pivotallabs.com/column-edit-mode-in-vi/)
It's not a correct way to do the things.
In vim i can do the replaceof a fange of rows, and so on using commands.
I think that should be possible to use commands to replace a portion of each string but i have no Knoledge about those command.
this is the main idea
Replacing alternate line in vi text file with a particular string
Question
Is there a way to do the operations using commands with absolute position and not selection.
Thanks
:{range}normal 5|r#9|2x20|i;
Does what you want on the lines covered by {range}:
5|r# " go to column 5 and replace the character with #
9|2x " go to column 9 and cut 2 characters
20|i; " go to column 20 and insert a ; to the right
So…
:5,25norm 5|r#9|2x20|i; would apply that transformation to lines 5 to 25,
:.,$norm 5|r#9|2x20|i; would apply that transformation from the current line to the last,
:'<,'>norm 5|r#9|2x20|i; would apply that transformation to the current (or last) visual selection,
:'{,'}norm 5|r#9|2x20|i; would apply that transformation to the current "paragraph",
:%norm 5|r#9|2x20|i; would apply that transformation to the whole buffer,
and so on…
You could also record it, let's say in register q:
qq
5|r#
9|2x
20|i;<Esc>
q
and play it back on {range}:
:{range}#q
Or spend 30 minutes trying to come up with the right :s// command…
Reference:
:help range
:help :normal
:help |
:help r
:help x
:help i
:h recording

Deleting lines upward in vim Linux

How to do that in vim, lets say im in line 100 and i want to delete 20 lines upward? how to do that in vim linux?
You can do it relative if you know the number of lines:
d20k
Or absolute if you know the line number:
d80G
d = delete, 20k = 20 lines up, 80G = goto line 80
Or without taking you current position into account:
:80,100d
Personally, I use visual mode a lot becuase it gives me a nice feedback:
hit V to enter visual line mode
move 20 lines up with 20k
adjust selection with k and j if necessary
press d to delete selection
In normal mode you can use d and the movenment key k to delete upwards. And then you prefix that command with the number of times you want to repeat the command like 100dk.
If you just want to delete to the beginning you can use gg along with d, gg sends the cursor to the first character in the file. So ggd will delete the first line to the line you are standing on.
You can do it upwards with the range.
:-20,.d
In this you can specify the range of line to delete it .
Will deletes 20 lines upwards to the current and this is kind of an ex-mode command.

Vim: insert the same characters across multiple lines

Sometimes I want to edit a certain visual block of text across multiple lines.
For example, I would take a text that looks like this:
name
comment
phone
email
And make it look like this
vendor_name
vendor_comment
vendor_phone
vendor_email
Currently the way I would do it now is...
Select all 4 row lines of a block by pressing V and then j four times.
Indent with >.
Go back one letter with h.
Go to block visual mode with Ctrlv.
Select down four rows by pressing j four times. At this point you have selected a 4x1 visual blocks of whitespace (four rows and one column).
Press C. Notice this pretty much indented to the left by one column.
Type out a " vendor_" without the quote. Notice the extra space we had to put back.
Press Esc. This is one of the very few times I use Esc to get out of insert mode. Ctrlc would only edit the first line.
Repeat step 1.
Indent the other way with <.
I don't need to indent if there is at least one column of whitespace before the words. I wouldn't need the whitespace if I didn't have to clear the visual block with c.
But if I have to clear, then is there a way to do what I performed above without creating the needed whitespace with indentation?
Also why does editing multiple lines at once only work by exiting out of insert mode with Esc over Ctrlc?
Here is a more complicated example:
name = models.CharField( max_length = 135 )
comment = models.TextField( blank = True )
phone = models.CharField( max_length = 135, blank = True )
email = models.EmailField( blank = True )
to
name = models.whatever.CharField( max_length = 135 )
comment = models.whatever.TextField( blank = True )
phone = models.whatever.CharField( max_length = 135, blank = True )
email = models.whatever.EmailField( blank = True )
In this example I would perform the vertical visual block over the ., and then reinsert it back during insert mode, i.e., type .whatever.. Hopefully now you can see the drawback to this method. I am limited to only selecting a column of text that are all the same in a vertical position.
Move the cursor to the n in name.
Enter visual block mode (Ctrlv).
Press j three times (or 3j) to jump down by 3 lines; G (capital g) to jump to the last line
Press I (capital i).
Type in vendor_. Note: It will only update the screen in the first line - until Esc is pressed (6.), at which point all lines will be updated.
Press Esc.
An uppercase I must be used rather than a lowercase i, because the lowercase i is interpreted as the start of a text object, which is rather useful on its own, e.g. for selecting inside a tag block (it):
Another approach is to use the . (dot) command in combination with i.
Move the cursor where you want to start
Press i
Type in the prefix you want (e.g. vendor_)
Press esc.
Press j to go down a line
Type . to repeat the last edit, automatically inserting the prefix again
Alternate quickly between j and .
I find this technique is often faster than the visual block mode for small numbers of additions and has the added benefit that if you don't need to insert the text on every single line in a range you can easily skip them by pressing extra j's.
Note that for large number of contiguous additions, the block approach or macro will likely be superior.
Select the lines you want to modify using CtrlV.
Press:
I: Insert before what's selected.
A: Append after what's selected.
c: Replace what's selected.
Type the new text.
Press Esc to apply the changes to all selected lines.
I would use a macro to record my actions and would then repeat it.
Put your cursor on the first letter in name.
Hit qq to start recording into the q buffer.
Hit i to go into insert mode, type vector_, and then hit Esc to leave insert mode.
Now hit 0 to go back to the beginning of the line.
Now hit j to go down.
Now hit q again to stop recording.
You now have a nice macro.
Type 3#q to execute your macro three times to do the rest of the lines.
:%s/^/vendor_/
or am I missing something?
Updated January 2016
Whilst the accepted answer is a great solution, this is actually slightly fewer keystrokes, and scales better - based in principle on the accepted answer.
Move the cursor to the n in name.
Enter visual block mode (ctrlv).
Press 3j
Press I.
Type in vendor_.
Press esc.
Note, this has fewer keystrokes than the accepted answer provided (compare Step 3). We just count the number of j actions to perform.
If you have line numbers enabled (as illustrated above), and know the line number you wish to move to, then step 3 can be changed to #G where # is the wanted line number.
In our example above, this would be 4G. However when dealing with just a few line numbers an explicit count works well.
An alternative that can be more flexible:
Example: To enter the text XYZ at the beginning of the line
:%norm IXYZ
What's happening here?
% == Execute on every line
norm == Execute the following keys in normal mode (short for normal)
I == Insert at beginning of line
XYZ == The text you want to enter
Then you hit Enter, and it executes.
Specific to your request:
:%norm Ivendor_
You can also choose a particular range:
:2,4norm Ivendor_
Or execute over a selected visual range:
:'<,'>norm Ivendor_
Or execute for each line that matches a 'target' regex:
:%g/target/norm Ivendor_
I wanted to comment out a lot of lines in some config file on a server that only had vi (no nano), so visual method was cumbersome as well
Here's how i did that.
Open file vi file
Display line numbers :set number! or :set number
Then use the line numbers to replace start-of-line with "#", how?
:35,77s/^/#/
Note: the numbers are inclusive, lines from 35 to 77, both included will be modified.
To uncomment/undo that, simply use :35,77s/^#//
If you want to add a text word as a comment after every line of code, you can also use:
:35,77s/$/#test/ (for languages like Python)
:35,77s/;$/;\/\/test/ (for languages like Java)
credits/references:
https://unix.stackexchange.com/questions/84929/uncommenting-multiple-lines-of-code-specified-by-line-numbers-using-vi-or-vim
https://unix.stackexchange.com/questions/120615/how-to-comment-multiple-lines-at-once
You might also have a use case where you want to delete a block of text and replace it.
Like this
Hello World
Hello World
To
Hello Cool
Hello Cool
You can just visual block select "World" in both lines.
Type c for change - now you will be in insert mode.
Insert the stuff you want and hit escape.
Both get reflected vertically. It works just like 'I', except that it replaces the block with the new text instead of inserting it.
Suppose you have this file:
something
name
comment
phone
email
something else
and more ...
You want to add "vendor_" in front of "name", "comment", "phone", and "email", regardless of where they appear in the file.
:%s/\<\(name\|comment\|phone\|email\)\>/vendor_\1/gc
The c flag will prompt you for confirmation. You can drop that if you don't want the prompt.
Use Ctrl+V to enter visual block mode
Move Up/Down to select the columns of text in the lines you want to comment.
Then hit Shift+i and type the text you want to insert.
Then hit Esc, wait 1 second and the inserted text will appear on every line
Ctrl + v to go to visual block mode
Select the lines using the up and down arrow
Enter lowercase 3i (press lowercase I three times)
I (press capital I. That will take you into insert mode.)
Write the text you want to add
Esc
Press the down arrow
I came here to paste in many lines an already copied string. When copy with y we can paste, in the INSERT MODE, pressing Ctrl+r and right after press ''. This will have the same result as being in NORMAL MODE and press p. This is called paste from registry.
Suppose the following text in the buffer:
vendor_something
text
to_receive
the_paste
pattern
Then we can put the cursor pointing to v in vendor_ and press v, move to right using l until select the underscore symbol we want to paste in the text bellow. After that, we can point the cursor at the beginning of "text" (two lines bellow vendor_something) and press Ctrl+v. Then I to go into INSERT MODE where we press 3j Ctrl+r '' Esc. The result of this sequence will be:
vendor_something
vendor_text
vendor_to_receive
vendor_the_paste
vendor_pattern
:.,+3s/^/vendor_/
Another example, I needed to just add two spaces to a block of 125 lines, so I used (with cursor positioned at the beginning of the first line of the block):
:.,+125s/^/ /
Worked great.
If the change is required in the entire file,
:1,$s/^/vendor_/
If the change is required for only a few lines,
Go to the first line where change is required, and either give the command
:.,ns/^/vendor_/
Substitute n with the line number of the last line in the block.
Or,
:.,+ns/^/vendor_/
Substitute n with number of lines minus 1 in which the change is required.

Vim: faster way to select blocks of text in visual mode

I have been using vim for quite some time and am aware that selecting blocks of text in visual mode is as simple as SHIFT+V and moving the arrow key up or down line-by-line until I reach the end of the block of text that I want selected.
My question is - is there a faster way in visual mode to select a block of text for example by SHIFT+V followed by specifying the line number in which I want the selection to stop? (via :35 for example, where 35 is the line number I want to select up to - this obviously does not work so my question is to find how if something similar to this can be done...)
In addition to what others have said, you can also expand your selection using pattern searches.
For example, v/foo will select from your current position to the next instance of "foo." If you actually wanted to expand to the next instance of "foo," on line 35, for example, just press n to expand selection to the next instance, and so on.
update
I don't often do it, but I know that some people use marks extensively to make visual selections. For example, if I'm on line 5 and I want to select to line 35, I might press ma to place mark a on line 5, then :35 to move to line 35. Shift + v to enter linewise visual mode, and finally `a to select back to mark a.
G Goto line [count], default last line, on the first
non-blank character linewise. If 'startofline' not
set, keep the same column.
G is a one of jump-motions.
V35G achieves what you want
Vim is a language. To really understand Vim, you have to know the language. Many commands are verbs, and vim also has objects and prepositions.
V100G
V100gg
This means "select the current line up to and including line 100."
Text objects are where a lot of the power is at. They introduce more objects with prepositions.
Vap
This means "select around the current paragraph", that is select the current paragraph and the blank line following it.
V2ap
This means "select around the current paragraph and the next paragraph."
}V-2ap
This means "go to the end of the current paragraph and then visually select it and the preceding paragraph."
Understanding Vim as a language will help you to get the best mileage out of it.
After you have selecting down, then you can combine with other commands:
Vapd
With the above command, you can select around a paragraph and delete it. Change the d to a y to copy or to a c to change or to a p to paste over.
Once you get the hang of how all these commands work together, then you will eventually not need to visually select anything. Instead of visually selecting and then deleting a paragraph, you can just delete the paragraph with the dap command.
v35G will select everything from the cursor up to line 35.
v puts you in select mode, 35 specifies the line number that you want to G go to.
You could also use v} which will select everything up to the beginning of the next paragraph.
For selecting number of lines:
shift+v 9j - select 10 lines
simple just press Shift v line number gg
example: your current line to line 41
Just press Shift v 41 gg
Shift+V n j or Shift+V n k
This selects the current line and the next/previous n lines. I find it very useful.
You can press vi} to select the block surrounded with {} brackets where your cursor is currently located.
It doesn't really matter where you are inside that block (just make sure you are in the outermost one). Also you can change { to anything that has a pair like ) or ].
v%
will select the whole block.
Play with also:
v}, vp, vs, etc.
See help:
:help text-objects
which lists the different ways to select letters, words, sentences, paragraphs, blocks, and so on.
v 35 j
text added for 30 character minimum
Text objects: http://vim.wikia.com/wiki/Creating_new_text_objects
http://vimdoc.sourceforge.net/htmldoc/motion.html#text-objects
You can always just use antecedent numbers to repeat actions:
In visual mode, type 35&downarrow; and the cursor will move down 35 times, selecting the next 35 lines
In normal mode:
delete 35 lines 35dd
paste 35 times 35p
undo 35 changes 35u
etc.
} means move cursor to next paragraph. so, use v} to select entire paragraph.
It could come in handy to know:
In order to select the same ammount of lines for example use 1v
You should have done some modification to be able to use 1v, blockwise or linewise.
Today I saw this amazing tip from here:
:5mark < | 10mark > | normal gvV
:5mark < | 10mark > | normal gv
You can also reset the visual block boundaries doing so:
m< .......... sets the visual mode start point
m> .......... sets the visual mode end point
I use this with fold in indent mode :
v open Visual mode anywhere on the block
zaza toogle it twice
For selecting all in visual:
Type Esc to be sure yor are in normal mode
:0
type ENTER to go to the beginning of file
vG
Presss V to select the current line and enter the line number on keyboard and the press G.

Resources