How to do column editing in vim? - vim

Vim is pretty powerful when editing by line - the search/replace tools are modeled to work linewise.
But what if I want to change a particular column across all lines? For example, how can I change the 80th column in my file to a # easily?

To edit a column, follow these steps:
Stand on the beginning of the column
Press Ctrl+v, then mark across the column you want to edit.
Press Shift+i to insert text at the beginning of the column, Shift+a to append text, r to replace highlighted text, d to delete, c to change... etc.
Hit ESC when done.
I think people (me) sometimes map the column editing keys to Ctrl+Q so it won't collide with visual select line (V) or paste-text if you mapped it as such.

...I couldn't follow the steps of sa125 (facepalm) so I looked someplace else and found a simpler explanation at: https://blog.pivotal.io/labs/labs/column-edit-mode-in-vi
Ctrl+v [ and select what ever you want]
Shift+i [and write whatever...(check out ** below)]
Esc
*c without Shift can be used instead of step 2, to delete selection before insert. And also r to replace.
**!! Attention Don't be discouraged by the fact that only the first row is changed when you 'write whatever...'!!
Hope it helps!

You can use a substitution where the pattern matches a specific column (\%c):
:%s/\%80c/#/<CR>
Or you can use block-wise visual mode:
gg80|CTRL+vGr#
The 'virtualedit' option can be used to allow positioning the cursor to
positions where there is no actual character:
:set virtualedit

I may be totally off topic here, but if your idea is to avoid long lines, you could have a look at the colorcolumn option of vim 7.3.

For column-wise editing, vis.vim is really useful. You can block-select your column of interest, and manipulate it with normal commands, and even arbitrary Ex commands. From the example on that page, I have often used the pattern:
:'<,'>B s/abc/ABC/g
You can Vundle/Pathogen install vis.vim from github:
Plugin 'taku-o/vim-vis'

Related

Vim equivalent of Emacs' open-rectangle

Emacs has a function called open-rectangle, which allows you to select a rectangular region (i.e. Vim's visual block mode), then hit a key combination to fill that rectangle with spaces, pushing any existing content out to the right:
This is really useful when working with vertically-aligned columns of text. I feel like I should be able to do this easily in Vim too, using visual block + a search & replace. But I can't seem to figure out why my search & replace isn't bound to my rectangle when I try it.
:'<,'>s/\^/ /
This actually indents the whole line, instead of opening up this selected region. I've tried replacing:
:'<,'>s/\v(.*)/ \1/
But that has the same effect. How can I get my pattern to understand that I only want to replace each line in the selected block with spaces + the selected area? Simple replacements like just changing letters work, but using ^ or .* doesn't work the way I'd expect.
I am aware of the ability to hit "I" and insert some spaces the drop back into normal mode, but that is harder to judge when you're indenting by a large amount, over many lines.
How about:
yPgvr<Space>
This yanks the block and pastes it to duplicate it, then re-selects the original block and replaces it with spaces.
Another way:
Visual-block select only one column.
Hit nI<Space><Esc> with n being the number of blank columns you want.
As a variation on romainl's answer, I have this:
vnoremap <C-Space> I<Space><Esc>gv
It allows both insertion of n spaces at once via a prepended count, and iterative adding of columns by repeated application of the mapping.

Vim - Commands to visually select a regex match?

Can't figure out how to automatically select a regex match in visual mode.
For example, manually, I could search for a word
/word
It lands the cursor on the first character of the match "word".
Then I press v to enter Visual mode, and press llll to select the whole "word".
Now I want to do this by a macro, and I don't know the length of the match ahead of time.
I expected that Vim would automatically define some built-in marks at the beginning and end of the current match, so that I could ` to them. But I couldn't find any information on that.
What I want is to reassign Ctrl+n to a macro to take me to the next match and select it in visual mode, i.e. not just highlight the match. (To parallel how n takes you to the next match.)
If you're wondering why, its because I want to create folds based on regex matches (like Ctrl+n, zf), but I'm sure it will come in handy in other cases too.
//e takes you to the end character of last search.
More info -- :help {offset}.
You can find how to restore old search buffer here.
For the benefit of folks who stumble across this question in the future, vim now has this feature built-in: gn (and its close sibling gN) will jump to the next (respectively, previous) match and visually select it. It can also be used as a motion; e.g. cgn will jump to the next match and change it.
:noremap <C-n> //s<CR>v//e+1<CR>
Edit summary: was //e, but //e+1 worked for me (selected the last character of the match too).

How to insert a block of white spaces starting at the cursor position in vi?

Suppose I have the piece of text below with the cursor staying at the first A currently,
AAAA
BBB
CC
D
How can I add spaces in front of each line to make it like, and it would be great if the number of columns of spaces can be specified on-the-fly, e.g., two here.
AAAA
BBB
CC
D
I would imagine there is a way to do it quickly in visual mode, but any ideas?
Currently I'm copying the first column of text in visual mode twice, and replace the entire two column to spaces, which involves > 5 keystrokes, too cumbersome.
Constraint:
Sorry that I didn't state the question clearly and might create some confusions.
The target is only part of a larger file, so it would be great if the number of rows and columns starting from the first A can be specified.
Edit:
Thank both #DeepYellow and #Johnsyweb, apparently >} and >ap are all great tips that I was not aware of, and they both could be valid answers before I clarified on the specific requirement for the answer to my question, but in any case, #luser droog 's answer stands out as the only viable answer. Thank you everyone!
I'd use :%s/^/ /
You could also specify a range of lines :10,15s/^/ /
Or a relative range :.,+5s/^/ /
Or use regular expressions for the locations :/A/,/D/>.
For copying code to paste on SO, I usually use sed from the terminal sed 's/^/ /' filename
Shortcut
I just learned a new trick for this. You enter visual mode v, select the region (with regular movement commands), then hit : which gives you this:
:'<,'>
ready for you to type just the command part of the above commands, the marks '< and '> being automatically set to the bounds of the visual selection.
To select and indent the current paragraph:
vip>
or
vip:>
followed by enter.
Edit:
As requested in the comments, you can also add spaces to the middle of a line using a regex quantifier \{n} on the any meta-character ..
:%s/^.\{14}/& /
This adds a space 14 chars from the left on each line. Of course % could be replaced by any of the above options for specifying the range of an ex command.
When on the first A, I'd go in block visual mode ctrl-v, select the lines you want to modify, press I (insert mode with capital i), and apply any changes I want for the first line. Leaving visual mode esc will apply all changes on the first line to all lines.
Probably not the most efficient on number of key-strokes, but gives you all the freedom you want before leaving visual mode. I don't like it when I have to specify by hand the line and column range in a regex command.
I'd use >}.
Where...
>: Shifts right and
}: means until the end of the paragraph
Hope this helps.
Ctrl + v (to enter in visual mode)
Use the arrow keys to select the lines
Shift + i (takes you to insert mode)
Hit space keys or whatever you want to type in front of the selected lines.
Save the changes (Use :w) and now you will see the changes in all the selected lines.
I would do like Nigu. Another solution is to use :normal:
<S-v> to enter VISUAL-LINE mode
3j or jjj or /D<CR> to select the lines
:norm I<Space><Space>, the correct range ('<,'>) being inserted automatically
:normal is probably a bit overkill for this specific case but sometimes you may want to perform a bunch of complex operations on a range of lines.
You can select the lines in visual mode, and type >. This assumes that you've set your tabs up to insert spaces, e.g.:
setl expandtab
setl shiftwidth=4
setl tabstop=4
(replace 4 with your preference in indentation)
If the lines form a paragraph, >ap in normal mode will shift the whole paragraph above and below the current position.
Let's assume you want to shift a block of code:
setup the count of spaces used by each shift command, :set shiftwidth=1, default is 8.
press Ctrl+v in appropriate place and move cursor up k or down j to select some area.
press > to shift the block and . to repeat the action until desired position (if cursor is missed, turn back with h or b).
Another thing you could try is a macro. If you do not know already, you start a macro with q and select the register to save the macro... so to save your macro in register a you would type qa in normal mode.
At the bottom there should be something that says recording. Now just do your movement as you would like.
So in this case you wanted 2 spaces in front of every line, so with your cursor already at the beginning of the first line, go into insert mode, and hit space twice. Now hit escape to go to normal mode, then down to the next line, then to the beginning of that line, and press q. This ends and saves the macro
(so that it is all in one place, this is the full list of key combinations you would do, where <esc> is when you press the escape key, and <space> is where you hit the space bar: qai<space><space><esc>j0q This saves the macro in register a )
Now to play the macro back you do # followed by the register you saved it in... so in this example #a. Now the second line will also have 2 spaces in front of them.
Macros can also run multiple times, so if I did 3#a the macro would run 3 times, and you would be done with this.
I like using macros for this like this because it is more intuitive to me, because I can do exactly what I want it to do, and just replay it multiple times.
I was looking for similar solution, and use this variation
VG:norm[N]I
N = numbers of spaces to insert.
V=Crtl-V
*** Notice *** put space immediate after I.

Search only between specific line numbers?

I know that with Vim's substitution command you can specific a range of lines:
:12,24s/search/replace
I want to be able to specify a range with normal searches as well. Something like
:12,24/search
Since that doesn't seem to work (at least on my Vim configuration), does anybody know how to achieve this?
Great answer from akira. But after some digging, I found an alternative. It's not as elegant but easier to type in:
:12,24g/search/
This will give you one annoying prompt but it will end up on the first line within the range containing the sought string.
:help search-range
and then
:help /\%>l
so essentially:
/\%>12l\%<24lsearch
Do you really need line numbers? Another way could be to select the range visually.
select the range using v, V or whatever
press ESC to unselect the range
search using /\%Vwhat_to_search to search for 'what_to_search' in the previously selected range.
This is lesser to type, but not directly what you have asked for ;-)
See :help %V
[EDIT] Great, I have just learned that the range to search in can be changed after doing the search by selecting another range, unselecting this range again by pressing ESC and pressing n to repeat search. Vim is really always good for pleasant surprises.
Keep using the substitution command, but append the gc flags to your original example.
:12,24s/search//gc
From :help search-range
[To search within a range] use the
":substitute" command with the 'c'
flag.
Example:
:.,300s/Pattern//gc
This command will search from the
cursor position until line 300 for
"Pattern". At the match, you can type
'q' to stop, or 'n' to find the next
match.
If there marks say a and b, then the search can be restricted to the region between a and b using
/\%>'a\%<'bSearchText
This can be simplified with a cmap
cmap vmsab /\%>'a\%<'b
cmap vmscd /\%>'c\%<'d
If you would like to search to the end of the file, use $:
:3,$s/pattern//gn
This will search from 3-d line to the end
Using Narrow Region plugin we can open a temporary buffer with the range we need to search or change
:900,1000NarrowRegion
Then we can meke a search
/thing
Or a change and write the buffer back
:%s/this/that/g
:wq

How to edit multiple locations simultaneously in Vim

In certain text editors, like E, I can select multiple locations and, as I type, all the selected locations get replaced with the characters I am typing.
For example if I have:
<tag1 class=""></tag1>
<tag2><tag3 class=""></tag3></tag2>
In E I could select two locations inside sets of quotations marks then start typing and both locations would be updated simulataneously. In Vim, I can select several connected columns at once and then edit them, but I'm wondering if there is any way to select multiple locations that aren't lined up.
Here's how I would probably edit those particular lines (there are many ways):
/""<enter>
aText to replace...<esc>
n
.
First, search for the empty quotes to put the cursor on the first one. Using the "a" (append) command, type the new text to put inside the quotes. When you're done, use "n" (next) to go to the next instance, and "." (repeat last command) to insert the same text again. Repeat the "n ." as many times as necessary.
This method takes less up-front preparation and lets you get started right away without identifying ahead of time all the locations where you might want to add the text.
You may be looking for visual mode blockwise, which will allow insertion, deletion etc on several lines at once.
Blockwise mode will allow square selections with the column and line of the initial point in one corner, and the current cursor position defining the column and line of the other corner. This, as opposed to the line based selection that is the default.
CTRL-v will place you in blockwise visual mode.
If you have several lines like so:
INSERT INTO Users VALUES(1, 'Jim');
INSERT INTO Users VALUES(2, 'Jack');
INSERT INTO Users VALUES(3, 'Joseph');
And wanted to insert "0," after the id for each line, then place the cursor after the comma in the first line:
INSERT INTO Users VALUES(1,* 'Jim');
With the asterisk representing the cursor the command sequence would be:
CTRL-v # Put into blockwise visual mode
j # Down a line
j # Down a line
CTRL-I # Captial I for insert
0, # the text to insert
Esc # escape
The text should now look like:
INSERT INTO Users VALUES(1, 0, 'Jim');
INSERT INTO Users VALUES(2, 0, 'Jack');
INSERT INTO Users VALUES(3, 0, 'Joseph');
Also blockwise visual mode, x will delete a selection, y will yank it.
:help CTRL-V will give further documentation.
Have a look at SnippetsEmu. It should be doing something very similar to what you need.
It emulates TextMates snippets. You should be able to have one snippet with the same tag repeated, and editing will do the right thing, updating the same tag in all locations, as you type.
For your example I would use a substitution:
:%s/class=""/class="something"/g
Try vim-multiple-cursors.
Press Ctrl+N as many times as necessary to select the multiple occurences.
I'm also looking for something like that, more specifically a very useful functionality from ST2, where you press CTRL+D to select next occurrence and then replace both occurrence by just typing it.

Resources