Surround two words with quotes in Vim - 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"

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.

Vim: Quickest way to copy text inside quotes

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

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~.

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/")

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