copy and paste behavior using VIM with yiw and di" - vim

I try to copy dog with yiw and replace with cat using di" and P.
The problem is that when I use di" it overwrites the dog buffer.
Starting point:
dog
debugPrint("cat");
debugPrint("cat");
debugPrint("cat");
debugPrint("cat");
Expected result:
dog
debugPrint("dog");
debugPrint("dog");
debugPrint("dog");
debugPrint("dog");
I managed to get the expected result using this (but I found it too complex to repeat):
Copy dog to register a : "ayiw then replace cat using di" and paste with "aP.

I recommend using the :%s to replace the cat with the dog since the way di" then P takes too much time.
:%s/cat/dog/

Related

vim substitution of register following capture group

Unexpected behavior of the :s[ubstitution] function.
Given the file:
dog
cat
cow
And a populated register 'a':
let #a='fish'
Executing the following command:
:%s/\(cat\)/\1\=#a/g
Modifies the file to be:
dog
cat=#a
cow
Where I would expect the output to be:
dog
catfish
cow
Does there need to be some kind of encapsulation/delimiter of the capture group symbol or register symbol in the :s function for these to work as intended when next to each other?
\= must come at the start of the replacement part.
Wrong:
:s/cat/&\=#a <-- cat\=#a
Right:
:s/cat/\=submatch(0) . #a <-- catfish
See :help s/\=.
You can use Ctrl+R to insert the content of a register.
:%s/cat/&<C-R>a/g

Vim how can I move text into a set of parentheses?

In Vim, this has been happening to me and I'm wondering the best way to handle it. Example:
something(|)something, else // pipe is the cursor location
I'd like to end up with this:
something(something, else)
I'd also like to be able to do this:
something(something) else _// in case I only want the first word
Assuming you are in insert mode:
" first example
<Del><S-Right><S-Right><S-Right>)
and:
" second example
<Del><S-Right><Del>)
Assuming you are in normal mode, with the cursor on the closing parenthesis:
" first example
x$p
and:
" second example
xeplx
I assume the pair of paranthesis has no space in between so that it looks like ()word, another-word etc etc. Then
d EEp
changes it into (word, another-word) etc etc.
The d initiates a delete. The following space tells vim how much you want to delete: one character (this is the )). An E jumps over a word. So, the double EE jumps over two words. With the final p you insert (paste) what you have deleted (that is the )).

How to replace the whole line with the text in the buffer in VIM?

Here is the text I'm working on:
line1: website = "a.com";
...
line3: website = "b.com";
...
line5: website = "c.com";
Suppose I want to change all website to "stackoverflow.com", I can do:
- change "a.com" to "stackoverflow.com"
- yank the whole line (Y)
- go to line3, hit p, k, dd to paste from buffer and delete the old "b.com" line.
Now the problem is that since dd puts the "b.com" into the buffer, to replace line5 I'll have to yank the whole line again.
Is there any simple way so that I can replace line3 and line5 with the already yanked line quickly?
UPDATE:
Thanks for the answers, now there are several ways doing it: delete to black hole, yank from named buffer, etc. I found this being my favorite method ( I use key R instead r as sometime I need to replace a single character):
In Vim is there a way to delete without putting text in the register?
I put some links to similar SO questions below:
How to Delete (desired text), delete (undesired text), and paste (desired text) in Vim
In Vim is there a way to delete without putting text in the register?
First things first
You can go one better by not needing to explicitly delete the line:
yank the whole line into register x: "xY
go to the next line to replace
visually select the whole line: V
paste over the selection from register x: "xp
Now the deleted line is in register ", as always, but the yanked line is still in register x, so you can repeat steps 2 through 4 without having to yank over and over.
Repeated things repeated
Unfortunately you cannot use . to repeat steps 3+4. So if you have to do this for a lot of lines, insert a few more steps to record a macro:
yank the whole line into a register x: "xY
go to the next line to replace
record a macro into the w register: qw
visually select the whole line: V
paste over the selection from register x: "xp
stop recording: q
go to the next line to replace
replay the macro recorded into w: #w
go to the next line to replace
and now finally, you can replay same-as-last-time: ##
Then you can simply repeat steps 9 and 10 for the next 50 lines you need to replace.
Last (repeated) things last
In fact, if you find the next line by searching, then you should use that search to go to the first line as well. Because then the n that you use to go to the next line can be included as part of the macro – basically you just swap steps 6 and 7.
Then you don’t have to manually go to the next line to replace at all, because the macro will send you there as the last thing it does. You can just keep hitting ##, along with any occasional ns whenever you happen to want to skip a particular match.
References
help "
help registers
help complex-repeat
You can use named buffers for this instead of the default unnamed buffer: "lY then "lp to yank resp. paste from register l, then let the dd use the default buffer.
This is not an answer to your question as put but it is an answer to your real question, I think.
Technique 1: Are you aware of :s? If you are just wanting to replace all matches, you could do something like this:
:%s/^website = "\zs.*\ze\.com";$/stackoverflow/
As you haven't specified precise format of it all and whether or not you are wanting to replace all or only some, I can't say whether this is what you want or not.
Technique 1b: Even if you only want to replace some, there's a useful and not terribly widely known flag for :s: c, "confirm". (See :help :s_flags and more specifically :help :s_c.) Then you can decide with each one whether you want to replace it or not.
:%s/^website = "\zs.*\ze\.com";$/stackoverflow/c
Technique 2: You could also search, replace and then repeat. /^website = "\zs.*\ze\.com";$, then cwstackoverflowEsc to replace the word with "stackoverflow". Then n to go to the next match and if you want to replace it with "stackoverflow", use ..
Rereading this question I think this is closer to what you're after:
In Vim is there a way to delete without putting text in the register?
E.g. instead of using dd use "_dd
The "0 register always contain your last yanked text. Then you can do:
change "a.com" to "stackoverflow.com"
yank the whole line (Y)
go to line3, hit "0p, k, dd to paste from buffer and delete the old "b.com" line.
go to line5, hit "0p, k, dd to paste from buffer and delete the old "c.com" line.
ci" - change inside the ""
ctrl-r 0 - put default register
jj - move down two lines
. - repeat last command
jj
.

-- is there a way to copy up to a search term, _including_ the term?

If I have the following words
cat Oliver Louis
and the cursor is on "c", I can copy up to the beginning of Louis with y/Louis<CR> (where "CR" is the enter key), which will copy the string "cat Oliver ".
Is there a way to copy the search term, "Louis", as well, for a copied string of "cat Oliver Louis"? Thanks in advance.
Use the /e modifier: y/Louis/e<CR>. If you want to repeat the last search pattern, just leave it out: y//e<CR>.
:help search-offset
Since the / search is exclusive, it will select everything up to the match, but not including the match. (check :help exclusive)
A more convenient way might be to use the inclusive f and t motion commands.
With the following line:
cat Oliver Louis
typing yfs in normal mode will yank everything up to the letter "s", or in this case, cat Oliver Louis
Obviously, this isn't as convenient if the line is something like
cat Assassins Scissors
There are too many s's. In this case you might want to go into visual mode and either repeat the inclusive f search motion by tapping ; until you reach the last s. Or, as you suggested above, simply use w preceded by the number of words you'd like to copy. In this case y3w will work.
One way is to use look-behind assertions... but the syntax is rather ugly!
y/\(Louis\)\#<=
This doesn't look for Louis, but for a position preceded by the string Louis.

Vim copy and paste

My previous question seems to be a bit ambiguous, I will rephrase it:
I have a file like this:
copythis abc
replacethis1 xyz
qwerty replacethis2
hasfshd replacethis3 fslfs
And so on...
NOTE: replacethis1, replacethis2, replacethis3, ... could be any words
How do I replace "replacethis1","replacethis2","replacethis3",.. word by "copythis" word by using minimum vim commands.
One way I can do is by these steps:
delete "replacethis1","replacethis2","replacethis3",.. by using 'dw'
copy "copythis" using 'yw'
move cursor to where "replacethis1" was and do 'p'; move cursor to where "replacethis2" was and do 'p' and so on...
Is there a better way to do this in VIM (using less number of vim commands)?
Since you changed your question, I'd do it this way:
Move to the first "replacethis1" and type cw (change word), then type "copythis" manually.
Move to the next "replacethis", hit . (repeat last operation)
Move to the next "replacethis", hit .,
and so on, and so on.
If "copythis" is a small word, I think this is the best solution.
The digit needs to be included, and there could be more than one instance per line:
:%s/replacethis\d/copythis/g
Given that "replacethis[1-3]" can be arbitrary unrelated words, the quickest/simplest way to do this globally would be:
:%s/replacethis1\|replacethis2\|replacethis3/copythis/g
(Note that you need to use \| to get the pipes to function as "or". Otherwise, vim will look for the literal | character.)
I've been struggling with this for a long time too, I think I just worked out the cleanest way:
Use whichever command is cleanest to put copythis into register r:
/copythis
"rye
Then go to the replacement and replace it with the contents of r:
/replacethis
cw<CTRL-R>r<ESC>
Then you can just n.n.n.n.n.n.n. for the rest of them, or if they're wildly different just go to the beginning of each and hit .
The key is replacing and pasting in one step so you can use . later.
:%s/copythis/replacethis/g
To replace all occurrences of copythis with replacethis. Or you can specify a range of line numbers like:
:8,10 s/copythis/replacethis/g
Note, the /g on the end will tell it to replace all occurrences. If you leave that off it will just do the first one.
create this mapping:
:map z cwcopythis^[
( ^[ is the escape character, you can type it in vim using Ctrl+V Ctrl+[ )
go to each word you want to replace and press z
if u need to do essentially the same action multiple times - swap 1st word of one line with second word of the next line, I say you could record a macro and call it whenever you need to
Have you tried string replacement?
%s/replacethis/copythis
A host of other parameters are possible to fine-tune the replacement. Dive into the Vim help for more details. Some more examples here.
You can remap e.g. the m key in normal mode to delete the word under the cursor and paste the buffer: :nnoremap m "_diwP.
Then you can just copy the desired word, move the cursor anywhere onto the to-be-replaced word and type m.
EDIT: Mapping to m is a bad idea since it is used to mark locations. But you can use e.g. ; anyway.

Resources