Vim paste behaviour - vim

I am a bit of a beginner when it comes to Vim and it is currently irritating me in many ways. One of which is the following:
Say i have the following text in a file
one
two
three
four
dog
frog
log
mog
and I have used visual mode to select the number words (4 lines) if I then use P to paste at the 'd' in dog i get the following:
one
two
three
four
one dog
two frog
threelog
four mog
My desired output would be:
one
two
three
four
one
two
three
four
dog
frog
log
mog
I've noticed that it behaves as I expect if i do a y4y instead of visually selecting the lines. So what is causing the difference in behavior that I am seeing? and how can I get my visually selected block to paste as I would like?

Seems that you are entering into the Visual Block selection mode (Ctrl-V).
To get your desired output, enter into a Linewise Selection mode, just by pressing V.

Use Shift+V, it selects line by line

try
:set paste
before pasting.

Related

How to yank words between dots on multiple lines in VIM?

I try to find the best way to copy (all occurrences) and paste (all the occurrences somewhere else) the second word in between the dots in this example case with vim (without plugins):
1 somename.xyz.something
2 so.someday.zzzz
3 text.example.fese.efsse
The result after I paste it somewhere else:
5 xyz
6 someday
7 example
I would copy the lines in question (e.g. yip or through visual mode) and paste them to the desired location, so you'd get:
somename.xyz.something
so.someday.zzzz
text.example.fese.efsse
somename.xyz.something
so.someday.zzzz
text.example.fese.efsse
And then delete the unwanted parts. For example by selecting them in visual mode and running :'<,'>normal 0df.f.D, resulting in:
somename.xyz.something
so.someday.zzzz
text.example.fese.efsse
xyz
someday
example

Why does changing case on words change behaviour when inside a macro?

I was changing some words to uppercase, I hit viw~ to change the case of the word from lowercase to uppercase. I moved foward a word and hit . to repeat the action on the next word and I noticed that it affected the case of some of the letters of the word ahead and on other times it would not change case of the entire word.
Here is an example done with vim -u NONE on a file with a single sentence
this is a test sentence
with my cursor at the start of the sentence, I hit
viw~
my sentence is now:
THIS is an example test sentence
I move forward by 1 word with w and hit . to repeat the action.
My sentence is now:
THIS IS An example test sentence
w.
THIS IS aN Example test sentence
w.
THIS IS aN eXAMple test sentence
w.
THIS IS aN eXAMple TEST sentence
The same behaviour happens when I instead capture the actions as a macro instead of using .
I suspect vim is just changing the case of the same number of letters as was in the first word, but why? Why does viw not work in macros?
The action was repeated on an area equivalent to the area covered by the previous command. This has nothing to do with macros.
From :help .:
Note that when repeating a command that used a Visual selection, the same SIZE
of area is used, see visual-repeat.
and from :help visual-repeat:
When repeating a Visual mode operator, the operator will be applied to the
same amount of text as the last time:
- Linewise Visual mode: The same number of lines.
- Blockwise Visual mode: The same number of lines and columns.
- Normal Visual mode within one line: The same number of characters.
- Normal Visual mode with several lines: The same number of lines, in the
last line the same number of characters as in the last line the last time.
The start of the text is the Cursor position. If the "$" command was used as
one of the last commands to extend the highlighted text, the repeating will
be applied up to the rightmost column of the longest line.
One of Vim's strengths is that you don't need to select text before doing many actions. In this case, you should use the :help g~ operator, which will be repeated with . in a more intuitive way:
g~iw
instead of:
viw~
I suspect vim is just changing the case of the same number of letters [...]
You're right. In order to do what you expect, Vim would have to remember how you created the visual selection. In your example, that was easy (iw), but you may apply multiple text objects and movements, use o to move to the other side of the selection, modify that, and so on. That would be very hard to recreate elsewhere, and to avoid inconsistent behavior, Vim consistently acts stupid and just uses the previous width of the selection when redoing with the . command.
If you want to apply an operation to a certain text object or motion, skip visual mode and instead use the corresponding motion-mapping; e.g. g~iw instead of viw~.

Vim: move visual selection, not text, up & down lines

If I have this line visually selected
Alpha <-- selected
Bravo
Charlie
is there a vim command to move the selected area down, without adding to the original selection?
Alpha
Bravo
Charlie <-- selected
hjkl key will only add lines to your selection. And I didn't see anything in visual's help doc that indicated it could be done.
In selection mode, you can use o (lowercase o) to swap between moving the top and bottom boundary. So you can do this without leaving selection mode using jjojj.
This will certainly do it:
jjVV
But it isn't really any different from canceling the original selection first:
escjjV
Or:
VjjV
as far as I understand your question, you would like to select Alpha and move it down. Let us say move Alpha under Charlie. You need to select Alpha in visual mode and then type : (colon) and type m 3. So your typing format should like :m 3. This means that move selected text to line 3. I hope this will be your question answer. Have a great day.

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.

Replace colon with tab to make columns

I have word lists where the word or expression in Spanish is separated by its translation with a colon (":"). I want to make two columns, one for Spanish, the other for English. In vim I tried with
:%s/:/^I^I^I/g
But it does not give the desired output. The different columns are not aligned.
When deleting the colon by hand and inserting the number of tabs with the same amount of tab strokes, it always ends up aligned.
Any idea how to solve this, preferably in vim?
On a Linux/*nix system I use column(1)
:%!column -s':' -t
followed by
:%retab!
I'd probable do a
:s/:/^I/g
followed by a
:set ts=25
Where 25 is the length of the longest word expected + 2. So, if you expect the longest word of your input (on the left side of the colon) to be 12 characters, I'd choose something around 14 instead.
With Tabular.vim it's quite easy, just type :Tab /:\zs and it does the rest.
When in insert mode a setting of yours makes tab to reach a nth column. This is set with the 'softtabstop' settings if I am right.
For those tasks you could use a plugin like Align.vim or Tabularize.
Another option is to insert a huge number of spaces, and then use Visual Block with < operator as many times as necessary, if you have to do it once. Otherwise prefer reusable methods.

Resources