Vim: Quickest way to copy text inside quotes - vim

What is the most efficient way to copy text inside quotes in vim, for example hello in "hello" 'hello' '''hello''' or """hello"""? The quickest I'm able to do is:
v (enter visual mode)
w or e (get to the end of the text, approximately
h or l to get to the exact correct place
y to yank the text
Here's an example: https://gyazo.com/a2bb432dc04de58ac628327740f6c033. While I might be able to improve to get it, perhaps in 3s, doing this with a mouse would take all of 0.25s. What would be the most efficient way to do a copy-paste such as the above?

If the text is surrounded by only one pair of quotes, in this case double quotes, the most efficient way to copy that text is yi". This will copy (y) the text inside the quotes (i"), regardless of where the cursor originally is. To make this work with single quotes, brackets, parentheses, or something else, simply replace the " with the character surrounding the text.
If the text is surrounded by more than one pair of quotes, however, we must first navigate to the innermost quote before we can copy the text inside. The command above will not work, since it will see the first two quotes with nothing in between them ("").
The fastest way to navigate to the first quote is f". Then, press ; until the cursor is on the innermost quote, and we can now use yib (the ib command selects the inner block.) to copy the text inside!
It might be possible to create a mapping that will automatically move the cursor to the innermost quote and copy the text inside, but that is a bit too advanced for me.

If your cursor is inside the word you want to copy, simply press yi followed by a quote char ' or "
Make sure you also read :h text-objects

Related

Replace a word (or many words) with spaces of same length?

In a general sense, my question is how do I do something like "dw" or "dd", but instead of deleting characters, I want to over-write with spaces?
E.g. lets say I have text:
first second third
if the cursor is on the "s" in second, I can hit "dw" to get:
first third
but what if I want:
first third
Is there a simple way to do that? An ideal solution would be to use the "d" style syntax (e.g. dw, daw, d$, etc.) but with whitespace replacement instead of deletion.
From the start of the word,
Ctrl-v to enter visual block mode,
e to move to the end of the word (highlighting the word in the process),
r[SPACE] to replace the highlighted characters with spaces.
Because of their very nature (the next character must be consumed), r and R can't work like operators. If you want to replace a motion, visually select it first, and then do r<Space> or r_ or whatever.
In this very specific case:
ver<Space>
or:
viwr<Space>
NOTE: I used ve and viw because the semantics of w are inconsistent so I prefer to avoid it when possible.

Surround Several Words With Quotes At Once In vim

I was curious if there is a way to surround several words at once with quotes using vim. I am using tpope surround and repeat but I was wondering if there is a command like
3ysw"
so from
one two three
to
"one" "two" "three"
You can visually select the range with v3e, and then run a substitution command on it: :s/\v(\w+)/"\1"/g (the range '<,'> should automatically be inserted).
Personally though, I'd rather surround one word with ysw", and then do w.w. (repeat as often as needed).
Alternatively, record a macro that does both steps (surrounding and moving on to the next word), then call it n times:
qqysw"3wq
After this is in your q register, you can then call 2#q to perform the surroundings on the remaining words.
When you want to enquote three words, beginning with the one your cursor is currently placed within, you can do:
bv3ec'<Ctrl+r>"'
b places the cursor at the beginning of the current word, v enters visual mode, 3e jumps at the end of the current 3-word sequence, c cuts the selection and enters insert mode, where you insert the left enclosing quote ' and press <Ctrl+r>" in order to paste current contents of the clipboard buffer, before you insert the other enclosing quote '.
Omit the leading b if you start off with the cursor at the first character of the first word.
Another substitution option
s,\w\+,"&",g
s ............. substitute current line (add %s for the whole file)
\w\+ .......... one word or more
"&" ........... & represents the whole match on the search part
g ............. every occurrence on the line
OBS: When using substitution we can use a different delimiter in order to make easy to type. (Also useful when searching for things like "/my/pattern/")

Pasting with overwrite in Vim

I want to be able to paste something from the buffer (probably using p), but instead of inserting it into the text, I want to replace whatever was there before (just like the R command). I've searched Google, vim documentation, and Stack Overflow but could not find anything on the issue. I imagine that it's just a command that I don't know about. Any help would be appreciated.
That's all I need to know, but if you want to know my specific problem:
Essentially I'm just trying to create a short script for documentation headers. At the beginning of every function I put the following:
// FunctionName <><><><><><><><><><><><><><><><><><><><>
However adding all those <> gets annoying. I want to be able to place my cursor on a function name, press the F6 key and it produce the above. The problem, of course, is that function names are not constant sizes and it would make the "chain" look weird. So I just want to paste OVER a bunch of pre-made chain so that the whole thing will always be a constant number of characters. i.e.:
start with
//<><><><><><><><><><><><><><><><><><><><><><><><><><><>
Paste " FunctionName " and end with
// FunctionName <><><><><><><><><><><><><><><><><><><><>
I found a much better solution
R Enter Replace mode: Each character you type replaces an existing character, starting with the character under the cursor.
So R <ctrl-r>" will do what you want. Note there is a space before and after <ctrl-r>".
OLD ANSWER
You can do this with a macro pretty easily
qhmhA <esc>a<><esc>40.80|D`hq
qh start macro
mh set mark
A <esc> insert a space after the existing text
a<><esc> insert '<>'
40. repeat last command 40 times
80| move to column 80
D delete to the end of the line
`h jump back to mark
q end macro
The macro can then be repeated with #h. You probably want to save this to your .vimrc like so
let #h = 'mhA ^[a<>^[40.80|D`h'
Note that the ^[ are supposed to be one character entered by pressing <ctrl-V><esc>
You can use visual selection.
Vp select the whole line and overwrite with buffer
viwp select the word under cursor and overwrite with buffer content.
vi(p overwrite what is in between parenthesis.
I particularly like that it highlights what should be overwritten, which
makes it easier to verify.
You can do it with this:
:exe "normal ".strlen(#p)."x\"pP"
It deletes the right number of chars, and then paste the content of register p.
Short answer
Simply do R and <C-r>0 or the 'register' you are trying to yank. If in doubt, check :reg
Long answer
From :help i_CTRL-R:
Insert the contents of a register. Between typing CTRL-R and
the second character, '"' will be displayed to indicate that
you are expected to enter the name of a register.
The text is inserted as if you typed it, but mappings and
abbreviations are not used. If you have options like
'textwidth', 'formatoptions', or 'autoindent' set, this will
influence what will be inserted. This is different from what
happens with the "p" command and pasting with the mouse.
Special registers:
'"' the unnamed register, containing the text of
the last delete or yank
'%' the current file name
'#' the alternate file name
'*' the clipboard contents (X11: primary selection)
'+' the clipboard contents
'/' the last search pattern
':' the last command-line
'.' the last inserted text
'-' the last small (less than a line) delete
*i_CTRL-R_=*
'=' the expression register: you are prompted to
enter an expression (see |expression|)
Note that 0x80 (128 decimal) is used for
special keys. E.g., you can use this to move
the cursor up:
CTRL-R ="\<Up>"
Use CTRL-R CTRL-R to insert text literally.
When the result is a |List| the items are used
as lines. They can have line breaks inside
too.
When the result is a Float it's automatically
converted to a String.
When append() or setline() is invoked the undo
sequence will be broken.

Surround two words with quotes in Vim

I am working with vim-surround and the following text. (* is the place of the cursor)
This is a lo*ng line and I want to highlight two words
I want to surround both the words long and line within quotes, so that it becomes
This is a "long line" and I want to highlight two words
Is it possible to do it without getting into visual mode?
Try: ys2w" (ys takes a motion or text object, and then the character with which you want to surround).
Press b first and then ys2w"
When using surround commands, I find the most logical solution is to sequence the "marking" and the "surrounding" operations.
Thus, with text objects, I use v2aw to visually mark the two words, then s" for the total of
v2aws"

How do I repeat an edit on multiple lines in Vim?

I'm aware that in Vim I can often repeat a command by simply adding a number in front of it. For example, one can delete 5 lines by:
5dd
It's also often possible to specify a range of lines to apply a command to, for example
:10,20s:hello:goodbye:gc
How can I perform a 'vertical edit'? I'd like to, for example, insert a particular symbol, say a comma, at the beggining (skipping whitespace, i.e. what you'd get if you type a comma after Shift-I in command mode) of every line in a given range. How can this be achieved (without resorting to down-period-down-period-down-period)?
Ctrl-v enters visual mode blockwise. You can then move (hjkl-wise, as normal), and if you want to insert something on multiple lines, use Shift-i.
So for the text:
abc123abc
def456def
ghi789ghi
if you hit Ctrl-v with your cursor over the 1, hit j twice to go down two columns, then Shift-i,ESC , your text would look like this:
abc,123abc
def,456def
ghi,789ghi
(the multi-line insert has a little lag, and won't render until AFTER you hit ESC).
:10,20s/^/,/
Or use a macro, record with:
q a i , ESC j h q
use with:
# a
Explanation: q a starts recording a macro to register a, q ends recording. There are registers a to z available for this.
That's what the :norm(al) command is for:
:10,20 normal I,
If you are already using the '.' to repeat your last command a lot, then I found this to be the most convenient solution so far. It allows you to repeat your last command on each line of a visual block by using
" allow the . to execute once for each line of a visual selection
vnoremap . :normal .<CR>
I believe the easiest way to do this is
1) record a macro for one line, call it 'a'; in this case one types
q a I , ESC j q
2) select the block of lines that you want to apply the macro to
3) use the 'norm' function to execute macro 'a' over this block of lines, i.e.,
:'<,'>norm#a
I think the easiest is to record a macro, and then repeat the macro as many times as you want. For example to add a comma at the start of every line, you type:
q a I , ESC j q
to repeat that 5 times, you enter
5 # a
With your edit already saved in the . operator, do the following:
Select text you want to apply the operator to using visual mode
Then run the command :norm .
Apart from the macros, as already answered, for the specific case of inserting a comma in a range of lines (say from line 10 to 20), you might do something like:
:10,20s/\(.*\)/,\1
That is, you can create a numbered group match with \( and \), and use \1 in the replacement string to say "replace with the contents of the match".
I use block visual mode. This allows you to perform inserts/edits across multiple lines (aka 'vertical edits').

Resources