Pasting inside delimiters without using visual selection - vim

In Vim, let's say I want to replace the contents of one String with the content of another.
Original input
var1 = "January"
var2 = "February"
Desired output
var1 = "January"
var2 = "January"
What I would usually do is:
Move cursor to line 1
y i " (yank inner quotes)
Move cursor to the destination quote in line 2
v i " p (visual select inner quotes, paste)
While this works well, I generally try to avoid visual mode when possible, so I am not completely satisfied with my step 4 (v i " p).
Is there any way to specify a "destination paste area" without using Visual mode? I suspect it might be something chained to g, but I can't think of anything.

There are many ways of doing this however using visual mode is the easiest.
Use the black hole register to delete the content then paste. e.g. "_di"P
Do ci"<c-r>0. <c-r> inserts the contents of a register
Simply paste and then move over a character and delete the old text. e.g pldt"
However visual mode still has my vote. I find that the concerns most people have is that using visual mode + paste is that the default register is swap with the selected text and it doesn't repeat well. Good news everybody! The 0 register always stores the last yank. The bad news is visual mode still doesn't repeat well. Take a look at this vimcast episode, Pasting from Visual mode, for more information. It mentions a few plugin that help with this.

I need this so often, I wrote a plugin to simplify and allow maximum speed: ReplaceWithRegister.
This plugin offers a two-in-one gr command that replaces text covered by a {motion} / text object, entire line(s) or the current selection with the contents of a register; the old text is deleted into the black-hole register, i.e. it's gone. It transparently handles many corner cases and allows for a quick repeat via the standard . command. Should you not like it, its page has links to alternatives.

It's not particularly pretty, but here goes:
Go to line one and yi"
Move to line two
Type "_di"hp
That deletes what's in the quotes, but sends the deleted text to a black hole register. Then it moves the cursor back one, and pastes what you yanked from line one.
All in all, you can start on the first line and type yi"j"_di"hp. Why is it that people find vim intimidating? ;)
Alternatively, yank the first line as normal, then drop to line two and type ci"<Ctrl+p> and select the previously yanked text from the menu.

Excerpt from my .vimrc:
" Delete to 'black hole' register
nnoremap <leader>d "_d
vnoremap <leader>d "_d
So, you just need to \di"P as your last step (assuming you use \ as a <leader>).

There is a plugin that addresses this problem precisely. It was presumably born out of the same feeling you're feeling, namely that Visual mode often feels less than ideal to advanced Vim users.
operator-replace – Operator to replace text with register content
With operator-replace installed the replacing goes like this.
Yank the word inside the quotes.
yi"
Move to the target line
j
Replace inside the quotes with the yanked text. (I've set up gr as the replace operator: :map gr <Plug>(operator-replace). Pick your own mapping.)
gri"
Check it out! This is part of the truly excellent textobj/operator frameworks. I couldn't work without them.

Related

vim - surround text with function call

I want to wrap some code :
myObj.text;
with a function call where the code is passed as an argument.
console.log(myObj.text);
I've thought about using surround.vim to do that but didn't manage to do it.
Any idea if it's possible ? I
With Surround in normal mode:
ysiwfconsole.log<CR>
With Surround in visual mode:
Sfconsole.log<CR>
Without Surround in normal mode:
ciwconsole.log(<C-r>")<Esc>
Without Surround in visual mode:
cconsole.log(<C-r>")<Esc>
But that's not very scalable. A mapping would certainly be more useful since you will almost certainly need to do it often:
xnoremap <key> cconsole.log(<C-r>")<Esc>
nnoremap <key> ciwconsole.log(<C-r>")<Esc>
which brings us back to Surround, which already does that—and more—very elegantly.
I know and use two different ways to accomplish this:
Variant 1:
Select the text you want to wrap in visual mode (hit v followed by whatever movements are appropriate).
Replace that text by hitting c, then type your function call console.log(). (The old text is not gone, it's just moved into a register, from where it will be promptly retrieved in step 3.) Hit <esc> while you are behind the closing parenthese, that should leave you on the ) character.
Paste the replaced text into the parentheses by hitting P (this inserts before the character you are currently on, so right between the ( and the )).
The entire sequence is v<movement>c<functionName>()<esc>P.
Variant 2:
Alternatively to leaving insert mode and pasting from normal mode, you can just as well paste directly from insertion mode by hitting <ctrl>R followed by ".
The entire sequence is v<movement>c<functionName>(<ctrl>R")<esc>.
You can use substitution instruction combined with visual mode
To change bar to foo(bar):
press v and select text you want (plus one more character) to surround with function call (^v$ will select whole text on current line including the newline character at the end)
type :s/\%V.*\%V/foo\(&\)/<CR>
Explanation:
s/a/b/g means 'substitute first match of a with b on current line'
\%V.*\%V matches visual selection without last character
& means 'matched text' (bar in this case)
foo\(&\) gives 'matched text surrounded with foo(...) '
<CR> means 'press enter'
Notes
For this to work you have to visually select also next character after bar (^v$ selects also the newline character at the end, so it's fine)
might be some problems with multiline selections, haven't checked it yet
when I press : in visual mode, it puts '<,'> in command line, but that doesn't interfere with rest of the command (it even prevents substitution, when selected text appears also somewhere earlier on current line) - :'<,'>s/... still works

Vim command to paste over highlighted word

I've only recently learned about use v command to mark a section I want to copy or cut. This is great!
But I'd like to use the v command to make the section I want to replace.
For example:
$another_obj->method_in_obj
$self->method_actually_in_obj
I want to mark "another_obj" and overwrite "self" with "another_obj". Basically I want to tell vim that, I want to take these 4 characters (self) and turn them into these 11 characters (another_obj) and have vim adjust my line accordingly.
So the final should be:
$another_obj->method_in_obj
$another_obj->method_actually_in_obj
Thanks!
#Kent has outlined the basic approach: You yank the source word, then paste over the selected replacement. The downside is that you can do that only once, because that action overrides the original yanked text! To avoid that, you need to specify the black-hole register.
I do this so often, I wrote a plugin to simplify and allow maximum speed: ReplaceWithRegister.
This plugin offers a two-in-one gr command that replaces text covered by a {motion} / text object, entire line(s) or the current selection with the contents of a register; the old text is deleted into the black-hole register, i.e. it's gone. It transparently handles many corner cases and allows for a quick repeat via the standard . command. Should you not like it, its page has links to alternatives.
cursor on [a]nother, pressing yw
then j cursor is on [s]elf, press:vawp

How to efficiently paste over multiple lines again and again with the same text in Vim?

Objective
Yank a line and use it to overwrite some of the lines following it.
Assumption
It is preferable in this case to manually select the lines to apply the substitution to. In other words, automated find and replace is not desired.
Analogy
Think of this process as creating a “stamp” from a line of text and going through a list of items—each item being a line of text following the “stamp” line—and deciding whether that line should be overridden using the contents of the “stamp” or not (in the former case, replacing the line with the “stamp”, of course).
This last step of triggering the replacement of the line under the cursor with the contents of the stamp, should be as easy as possible; preferably, as easy as pressing . (repeat last change) or ## (execute the contents of macro register #).
Issue
The straightforward workflow is, of course, as follows.
Position the cursor on the line to be copied (using movement commands).
Enter line-wise Visual mode (via the V command).
Copy selected text (using the y command).
Manually position the cursor onto the line to be replaced (using movement commands).
Enter Visual mode again to select the text to be replaced (using the V command).
Paste over the selection (using the p command).
However, this approach does not work when the replacement has to be done multiple times. Specifically, replacing the text on step 6 overrides the (unnamed) register containing the line initially copied and intended to be used as a “stamp”.
What I have tried
I have tried using "_y to either yank or delete into the _ register, avoiding the loss of the contents of the stamp, but I am looking for something that ends up being quick and comfortable to type as I manually go through the list and apply replacements where I see fit.
What I would prefer not to use
I would rather not use macros or “remaps” for this, if I can help it.
Illustrative sample file
See the sample starting file below, followed by the desired final stage, for further clarity.
Sample file, starting condition
At this stage, I select the blueberry and make it my “stamp”.
blueberry
apple
banana
coconut
apple
banana
coconut
apple
banana
coconut
Sample file, desired final state
After having moved through the list, I have applied some replacements, “stamping” over some lines, making them the same as the “stamp” blueberry line.
blueberry
apple
banana
blueberry
apple
banana
coconut
apple
banana
blueberry
To make your workflow work as expected, you need to paste from the previous yank register "0, rather than the default register.
So use Vy (or yy, which is the same) to yank the first line as before, then position the cursor over the line you want to replace, and do
V"0p
this replaces the current line with the previously yanked text, but doesn't overwrite the yanked text. I hope I understood you correctly!
EDIT 1: repeating using a macro
I was surprised that this operation isn't repeatable using ., but this is presumably due to the use of visual mode. To repeat the operation using a macro, do this:
qqV"0pq
The macro can then be repeated by pressing #q or ##.
EDIT 2: repeating using .
Here's an attempt at making it repeatable using . by not using visual mode. After yanking the stamp line and moving the cursor, do this:
"_S<c-r>0<delete>
which uses the insert mode <c-r> command to insert the contents of register 0. Note that the <delete> is necessary because the stamp line contained a carriage return. If it did not (i.e. yanking using y$ rather than yy) the <delete> could be omitted.
I don't think you are going to reach your goal without at least a little bit of "remapping".
I've been using this one for a "long" time:
vnoremap <leader>p "_dP
p and P still work as usual and I simply hit ,p over a visual selection when I want to repeat the same paste later. You could also map a single function key to make the whole thing quicker.
Also, do you know about the c flag for substitutions?
:%s/coconut/blueberry/c
will ask for your confirmation for each match.
Many answers here outline the general keys or commands. I've turned them into my ReplaceWithRegister plugin, which also handles many corner cases, and allows quick repeat via the . command. I also use your described create stamp and replace technique often, and found my script indispensable. Should you not like it, the plugin page also has links to alternative plugins.
A really easy solution: just put this script in your .vimrc, then toggle off the "buffer-overwriting" side-effect behavior of the delete key by typing ,, (two commas) to enter "no side effects" mode.
In this mode your workflow now works exactly as you described: yank whatever you like, then select, paste, and delete freely and repeatedly -- your buffer always remains intact. Then type ,, again if you wish to restore vim's normal buffer-altering behavior.
The script is the accepted answer here:
vim toggling buffer overwrite behavior when deleting
One can resort to Ex commands to achieve the said workflow.
For a single substitution, yank the “stamp” line (with yy, Vy,
:y, or otherwise), then repeatedly use the combination of the
:put and :delete commands:
:pu|-d_
Like any other Ex command, this one can be easily repeated with the
#: shortcut (see :help #:) — unless another Ex command was issued
in the meantime (in which case that command would be repeated instead).
Of course, you can also record the above Ex command as a macro and
invoke it that way, too.
Starting with your cursor at the start of the line to be duplicated:
y$ to yank the whole line (excluding the linefeed).
j and k to advance to the next line to be replaced (repeating as needed)
Replace the line with your yanked text
C<c-r>0<esc>0 (first time)
. (subsequent times)
If there are more lines to be replaced, goto 2.
The cursor will remain in column zero after each step.

vim: replace block

Let's say I have this text:
something "something else"
something here "just another quoted block"
I want to substitute "something else" with "just another quoted block", so I do:
/quot<enter> (to jump to second quoted block searching for the string "quot")
yi" (to yank inner text for current quoted block)
?else<enter> (to jump back to the first quoted block wich contains "else")
vi" (to visually select the quoted block)
p (to paste yanked text)
This works, but I would like to know if the two last steps can be replaced by a single one, to avoid visual mode. I know it's not a huge gain keystroke-wise, but I think that the Vim philosophy would encourage what I'm trying to do, and every time I do this my mind keeps asking for this command. :-P
What I tried so far:
r (replace) replaces just one character
c (change) throws me into Insert mode and does not let me paste the text.
"_di"P
Delete inside quotes to the blackhole register; paste last yanked before cursor.
Or
ci"<Ctrl-R>0<ESC>
Change inside quotes to retrieve last yank; leave insert mode.
With my ReplaceWithRegister plugin, the last two steps would be gri". It also offers grr (replace current / [count] lines); though it only saves a little typing, I find this indispensable.
Key stroke wise, j$yi"k then vi"p is actually probably the fastest. However, if you absolutely must go into insert mode you can j$yi"k then "_ci"<C-r>" or ci"<C-r>0. The :help i_CTRL-R operator allows you to put the contents of a register into insert mode.
I usually try to keep it simple, using what I feel is more intuitive with every day commands:
j
yi"
k
ci"
<ESC>
p

In Vim, what is the best way to select, delete, or comment out large portions of multi-screen text?

Selecting a large amount of text that extends over many screens in an IDE like Eclipse is fairly easy since you can use the mouse, but what is the best way to e.g. select and delete multiscreen blocks of text or write e.g. three large methods out to another file and then delete them for testing purposes in Vim when using it via putty/ssh where you cannot use the mouse?
I can easily yank-to-the-end-of-line or yank-to-the-end-of-code-block but if the text extends over many screens, or has lots of blank lines in it, I feel like my hands are tied in Vim. Any solutions?
And a related question: is there a way to somehow select 40 lines, and then comment them all out (with "#" or "//"), as is common in most IDEs?
Well, first of all, you can set vim to work with the mouse, which would allow you to select text just like you would in Eclipse.
You can also use the Visual selection - v, by default. Once selected, you can yank, cut, etc.
As far as commenting out the block, I usually select it with VISUAL, then do
:'<,'>s/^/# /
Replacing the beginning of each line with a #. (The '< and '> markers are the beginning and and of the visual selection.
Use markers.
Go to the top of the text block you want to delete and enter
ma
anywhere on that line. No need for the colon.
Then go to the end of the block and enter the following:
:'a,.d
Entering ma has set marker a for the character under the cursor.
The command you have entered after moving to the bottom of the text block says "from the line containing the character described by marker a ('a) to the current line (.) delete."
This sort of thing can be used for other things as well.
:'a,.ya b - yank from 'a to current line and put in buffer 'b'
:'a,.ya B - yank from 'a to current line and append to buffer 'b'
:'a,.s/^/#/ - from 'a to current line, substitute '#' for line begin
(i.e. comment out in Perl)
:'s,.s#^#//# - from 'a to current line, substitute '//' for line begin
(i.e. comment out in C++)
N.B. 'a (apostrophe-a) refers to the line containing the character marked by a. ``a(backtick-a) refers to the character marked bya`.
To insert comments select the beginning characters of the lines using CTRL-v (blockwise-visual, not 'v' character wise-visual or 'V' linewise-visual). Then go to insert-mode using 'I', enter your comment-character(s) on the first line (for example '#') and finally escape to normal mode using 'Esc'. Voila!
To remove the comments use blockwise-visual to select the comments and just delete them using 'x'.
Use the visual block command v (or V for whole lines and C-V for rectangular blocks). While in visual block mode, you can use any motion commands including search; I use } frequently to skip to the next blank line. Once the block is marked, you can :w it to a file, delete, yank, or whatever. If you execute a command and the visual block goes away, re-select the same block with gv. See :help visual-change for more.
I think there are language-specific scripts that come with vim that do things like comment out blocks of code in a way that fits your language of choice.
Press V (uppercase V) and then press 40j to select 40 lines and then press d to delete them. Or as #zigdon replied, you can comment them out.
The visual mode is the solution for your main problem. As to commenting out sections of code, there are many plugins for that on vim.org, I am using tComment.vim at the moment.
There is also a neat way to comment out a block without a plugin. Lets say you work in python and # is the comment character. Make a visual block selection of the column you want the hash sign to be in, and type I#ESCAPE. To enter a visual block mode press C-q on windows or C-v on linux.
My block comment technique:
Ctrl+V to start blockwise visual mode.
Make your selection.
With the selection still active, Shift+I. This put you into column insert mode.
Type you comment characters '#' or '//' or whatever.
ESC.
Or you may want to give this script a try...
http://www.vim.org/scripts/script.php?script_id=23
For commenting out lines, I would suggest one of these plugins:
EnhancedCommentify
NERD Commenter
I find myself using NERD more these days, but I've used EnhancedCommentify for years.
If you want to perform an action on a range of lines, and you know the line numbers, you can put the range on the command line. For instance, to delete lines 20 through 200 you can do:
:20,200d
To move lines 20 through 200 to where line 300 is you can use:
:20,200m300
And so on.
Use Shift+V to go in visual mode, then you can select lines and delete / change them.
My usual method for commenting out 40 lines would be to put the cursor on the first line and enter the command:
:.,+40s/^/# /
(For here thru 40 lines forward, substitute start-of-line with hash, space)
Seems a bit longer than some other methods suggested, but I like to do things with the keyboard instead of the mouse.
First answer is currently not quite right?
To comment out selection press ':' and type command
:'<,'>s/^/# /g
('<, '> - will be there automatically)
You should be aware of the normal mode command [count]CTRL-D.
It optionally changes the 'scroll' option from 10 to [count], and then scrolls down that many lines. Pressing CTRL-D again will scroll down that same lines again.
So try entering
V "visual line selection mode
30 "optionally set scroll value to 30
CTRL-D "jump down a screen, repeated as necessary
y " yank your selection
CTRL-U works the same way but scrolls up.
v enters visual block mode, where you can select as if with shift in most common editors, later you can do anything you can normally do with normal commands (substitution :'<,'>s/^/#/ to prepend with a comment, for instance) where '<,'> means the selected visual block instead of all the text.
marks would be the simplest mb where u want to begin and me where u want to end once this is done you can do pretty much anything you want
:'b,'ed
deletes from marker b to marker e
commenting out 40 lines you can do in the visual mode
V40j:s/^/#/
will comment out 40 lines from where u start the sequence

Resources