How to select between brackets (or quotes or ...) in Vim? - vim

I'm sure there used to be a plugin for this kinda stuff, but now that I need it, I can't seem to find it (naturally), so I'll just ask nice and simple.
What is the easiest way to select between brackets, or quotes, or generally a list of matching characters?
write ( *, '(a)' ) 'Computed solution coefficients:'
For example, here I'd like to select (a), or Computed solution coefficients:.
I'm not interested in multiline, just cases which occur on one line.

To select between the single quotes I usually do a vi' ("select inner single quotes").
Inside a parenthesis block, I use vib ("select inner block")
Inside a curly braces block you can use viB ("capital B")
To make the selections "inclusive" (select also the quotes, parenthesis or braces) you can use a instead of i.
You can read more about the Text object selections on the manual, or :help text-objects within vim.

Use whatever navigation key you want to get inside the parentheses, then you can use either yi( or yi) to copy everything within the matching parens. This also works with square brackets (e.g. yi]) and curly braces. In addition to y, you can also delete or change text (e.g. ci), di]).
I tried this with double and single-quotes and it appears to work there as well. For your data, I do:
write (*, '(a)') 'Computed solution coefficients:'
Move cursor to the C, then type yi'. Move the cursor to a blank line, hit p, and get
Computed solution coefficients:
As CMS noted, this works for visual mode selection as well - just use vi), vi}, vi', etc.

This method of selection is built-in and well covered in the Vim help. It covers XML tags and more.
See :help text-objects.

For selecting within single quotes use vi'.
For selecting within parenthesis use vi(.

Use arrows or hjkl to get to one of the bracketing expressions, then v to select visual (i.e. selecting) mode, then % to jump to the other bracket.

I wanted to add to the already good answers. I came here looking for a way to change the text inside of html brackets, so I want to provide an answer for anyone else that is also looking for that.
You might think ci< would work, but actually that only works if you are inside one of the tags themselves:
<would work inside here> But not here </would work inside here>
What I wanted was to change the text between the html tags themselves:
<div>change me</div>
What I wanted was "change inner tag": cit
Thank you to the other answer that mentioned the documentation (:help text-objects) which is how I found what I was looking for.

Write a Vim function in .vimrc using the searchpair built-in function:
searchpair({start}, {middle}, {end} [, {flags} [, {skip}
[, {stopline} [, {timeout}]]]])
Search for the match of a nested start-end pair. This can be
used to find the "endif" that matches an "if", while other
if/endif pairs in between are ignored.
[...]
(http://vimdoc.sourceforge.net/htmldoc/eval.html)

I would add a detail to the most voted answer:
If you're using gvim and want to copy to the clipboard, use
"+<command>
To copy all the content between brackets (or parens or curly brackets)
For example: "+yi} will copy to the clipboard all the content between the curly brackets your cursor is.

Stop at the beginning of brackets, and to select all and print
vi'
vi(
vi[
vi{
vi<
vi"
if you want to delete replace vi with di

I've made a plugin vim-textobj-quotes: https://github.com/beloglazov/vim-textobj-quotes
It provides text objects for the closest pairs of quotes of any type. Using only iq or aq it allows you to operate on the content of single ('), double ("), or back (`) quotes that currently surround the cursor, are in front of the cursor, or behind (in that order of preference). In other words, it jumps forward or backwards when needed to reach the quotes.
It's easier to understand by looking at examples (the cursor is shown with |):
Before: foo '1, |2, 3' bar; after pressing diq: foo '|' bar
Before: foo| '1, 2, 3' bar; after pressing diq: foo '|' bar
Before: foo '1, 2, 3' |bar; after pressing diq: foo '|' bar
Before: foo '1, |2, 3' bar; after pressing daq: foo | bar
Before: foo| '1, 2, 3' bar; after pressing daq: foo | bar
Before: foo '1, 2, 3' |bar; after pressing daq: foo | bar
The examples above are given for single quotes, the plugin works exactly the same way for double (") and back (`) quotes.
You can also use any other operators: ciq, diq, yiq, viq, etc.
Please have a look at the github page linked above for more details.

A simple keymap in vim would solve this issue.
map viq F”lvf”hh
This above command maps viq to the keys to search between quotes. Replace " with any character and create your keymaps.
Stick this in vimrc during startup and you should be able to use it everytime.

Related

Enclosing curly braces in parenthesis with Vim?

How to enclose curly braces in parenthesis in vim?
Initial string:
{a: b}
Final string:
({a: b})
The string possibly span multilines:
{
a: b
}
Assuming you are in normal mode and on any curly bracket character (opening or closing).
The manual/vanilla version (without any bracketing plugin) would be
c%(^R")
With:
^R meaning CTRL+R
the default register (") being filled with the content of the dictionary.
ca{ that should be used instead of c% if you're anywhere within the dictionary.
With my lh-brackets plugin, I would use v%( or vi{( -- unlike the vanilla version, will leave the default register unmodified.
With the popular surround plugin, I guess (I may be wrong as I've been using my plugin for decades) it would be something like ys%( or ysa{(.
PS: the fact your dictionary spans on several lines doesn't make any difference here.
With the vim-surround plugin you can visually select the text first e.g. va{, then surround with parentheses using S). I find it easier to remember this visual surround sequence v{motion}S<char> than the other options

Is there a good way to copy text within parentheses in Vim?

I want to copy the parameters foo(bar).baz in the following code:
function(foo(bar).baz)
First attempt: Cursor on one of the parentheses, then y%. This gives me the parameters plus a bit extra:
(foo(bar).baz)
Second attempt: Cursor on opening parenthesis. Set a mark ma, jump to end with
% then y`a to copy back to the mark. This gives me:
(foo(bar).baz
Setting a mark at the end and going the other way gives me exactly the same. Setting a
mark on the f, then typing mah%y`a does give me the foo(bar).baz that I want, but maybe there's something more concise. Is there?
Use text objects:
yi( (or ya( if you want to include the parenthesis).
You can also use " to work inside quotes, etc. See the link for details, or type :help text-objects in Vim.
A slightly shorter alternative to yi( is yib. Similarly yiB is equivalent to yi{ - yanks the contents inside braces.
Personally I usually do vib (visual select the text inside braces) first to make sure that the expected text is selected, followed by a y.
For more text object goodness, see :help text-objects.
Following should do it
Yank Inner Block
yi(

In vim, is there a plugin to use % to match the corresponding double quote (")?

The % key is one of the best features of vim: it lets you jump from { to }, [ to ], and so on.
However, it does not work by default with quotes: Either " or ', probably because the opening and closing quote are the same character, making implementation more difficult.
Thinking a bit more about the problem, I'm convinced that it should be implemented, by counting if the number of preceding quotes is odd or even and jumping to the previous or next quote, accordingly.
Before I try to implement it myself, I'd just like to know if someone already has?
Depending on your reason for needing this, there may be a better way to accomplish what you're looking for. For example, if you have the following code:
foo(bar, "baz quux")
^
and your cursor happens to be at the ^, and you want to replace everything inside the quotes with something else, use ci". This uses the Vim "text objects" to change (c) everything inside (i) the quotes (") and puts you in insert mode like this:
foo(bar, "")
^
Then you can start typing the replacement text. There are many other text objects that are really useful for this kind of shortcut. Learn (and use) one new Vim command per week, and you'll be an expert in no time!
Greg's answer was very useful but i also like the 'f' and 'F' commands that move the cursor forward and backward to the character you press after the command.
So press f" to move to the next " character and F" to move to the previous one.
I have found this technique very useful for going to the start/end of a very long quoted string.
when cursor is inside the string, visually select the whole string using vi" or vi'
go to start/end of the string by pressing o
press escape to exit visual select mode
this actually takes the cursor next to the start/end quote character, but still feels pretty helpful.
Edit
Adding Stefan's excellent comment here which is a better option for anyone who may miss the comment.
If you use va" (and va') then it will actually visually select the quotes itself as well.
– Stefan van den Akker
I'd like to expand on Greg's answer, and introduce the surround.vim plugin.
Suppose that rather than editing the contents of your quotes, you want to modify the " characters themselves. Lets say you want to change from double-quotes to single-quotes.
foo(bar, "baz quux")
^
The surround plugin allows you to change this to
foo(bar, 'baz quux')
^
just by executing the following: cs"' (which reads: "change the surrounding double-quotes to single-quotes").
You could also delete the quote marks simply by running: ds" (which reads: "delete the surrounding double-quotes).
There is a good introduction to the surround plugin here.
I know this question is old but here is a plugin to use % to match the corresponding double quote:
https://github.com/airblade/vim-matchquote

How to quickly remove a pair of parentheses, brackets, or braces in Vim?

In Vim, if I have code such as (in Ruby):
anArray << [anElement]
and my cursor is on the first [, I can hop to ] with the % key, and I can delete all the content between the [] pair with d%, but what if I just want to delete the [ and ] leaving all the remaining content between the two. In other words, what's the quickest way to get to:
anArray << anElement
One can take advantage of the text objects that are built in into Vim
(see :help text-objects). The desired edit can be stated as a
sequence of the following three actions.
Cut the text inside the square brackets:
di[
Select the (empty) square brackets:
va[
Alternatively, you can just select the character under the
cursor and the one to the left of it, because the command
from step 1 always puts the cursor on the closing bracket:
vh
Paste the cut text over the selected brackets:
p
Altogether, it gives us the following sequence of Normal-mode commands:
di[va[p
or, when the alternative form of step 2 is used:
di[vhp
ma%x`ax (mark position in register a, go to matching paren, delete char, go to mark a, delete char).
EDIT:
%x``x does the same thing (thanks to #Alok for the tip).
Using the Surround plugin for Vim, you can eliminate surrounding delimiters with ds<delimeter>.
To install it via Vundle plugin, add
Plugin 'tpope/vim-surround'
to your .vimrc file and run :PluginInstall.
If you have issues with the marks pointing to the first char of the line or with using % ...
di[vhp
works as well... It deletes matching [] brackets, when the cursor is anywhere inside. '[' can be replaced by '{' or '(' .
The other answers work fine if you want to delete delimiters one line at a time.
If on the other hand you want to remove a function and it's delimiters from the entire file use:
:%s/function(\(.*\))/\1/g
which replaces function(arguments) with arguments everywhere in the file.
You can use d% while your cursor is on the bracket/parentheses.

How can I insert text in the middle of the line to multiple lines in Vim?

Say I have ten lines and I want to prepend text to some word that occurs in those lines? It does not have to be at the beginning of the line.
From:
sdfsd foo sdfsd
sfsd foo fsdf
sdfsdf foo sdfsdf
to:
sdfsd bar(foo sdfsd
sfsd bar(foo fsdf
sdfsdf bar(foo sdfsdf
Is it also possible to not only prepend the bar( but actually surround foo with bar(foo)?
I would also like a quick way to append // comments to multiple lines (C-style comments).
I use Vim/GVim 7.2.
Go to the first foo, press Ctrl-v to enter visual block mode and press down until all the lines with foo are marked. Then press Shift-i to insert at the beginning (of the block). When you are finished and press Esc, the inserted characters will be added to each line at the left of the marked block.
To insert at the end, press again Ctrl-v, move up/down to mark all affected lines and then press End or $ to extend the selection until the end of the lines. Now you can press Shift-a to append at the end of all the lines, just like previously with Shift-i.
The visual selection can also be done with normal movement commands. So to comment a whole block in C you could move to the opening brace and type Ctrl-v % Shift-i // Esc.
To answer your first question, the below
:%s/foo/bar(&)/g
will look for foo, and surround the matched pattern with bar(). The /g will do this multiple times in one line.
Since you're just matching foo, you could do a simple :s/foo/bar(foo)/g. The above will work, however, if you decide to match on a regular expression rather than a simple word (e.g. f[a-z][a-z]). The '&' in the above represents what you've matched.
To prefix a set of lines I use one of two different approaches:
One approach is the block select (mentioned by sth). In general, you can select a rectangular region with ctrl-V followed by cursor-movement. Once you've highlighted a rectangle, pressing shift-I will insert characters on the left side of the rectangle, or shift-A will append them on the right side of the rectangle. So you can use this technique to make a rectangle that includes the left-most column of the lines you want to prefix, hit shift-I, type the prefix, and then hit escape.
The other approach is to use a substitution (as mentioned by Brian Agnew). Brian's substitution will affect the entire file (the % in the command means "all lines"). To affect just a few lines the easiest approach is to hit shift-V (which enables visual-line mode) while on the first/last line, and then move to the last/first line. Then type:
:s/^/YOUR PREFIX/
The ^ is a regex (in this case, the beginning of the line). By typing this in visual line mode you'll see '<,'> inserted before the s automatically. This means the range of the substitution will be the visual selection.
Extra tip: if your prefix contains slashes, you can either escape them with backslash, or you can use a different punctuation character as the separator in the command. For example, to add C++ line comments, I usually write:
:s:^:// :
For adding a suffix the substitution approach is generally easier unless all of your lines are exactly the same length. Just use $ for the pattern instead of ^ and your string will be appended instead of pre-pended.
If you want to add a prefix and a suffix simultaneously, you can do something like this:
:s/.*/PREFIX & SUFFIX/
The .* matches the whole line. The & in the replacement puts the matched text (the whole line) back, but now it'll have your prefix and suffix added.
BTW: when commenting out code you'll probably want to uncomment it later. You can use visual-block (ctrl-V) to select the slashes and then hit d to delete them, or you can use a substitution (probably with a visual line selection, made with shift-V) to remove the leading slashes like this:
:s:// ::
:normal to the rescue!
:%norm Wibar(
:%norm WEa)
:norm(al) replays the commands as if you had typed them:
W - goes to the next word
i - starts insertion mode
bar( - types the sequence 'bar('
Or in one line:
:%norm Wibar(ctrlvESCEa)
If you're running Windows then type ctrlq instead of ctrlv.
Yet another possibility (probably not-so-useful in your test case, but handy in other situations) is to cordon off the area you want to change with marks.
Put the cursor anywhere in the top line and press 'a
Put the cursor anywhere in the last line and press 'b
Issue the command :'a,'b s/foo/bar(&)/
I usually like visual block mode if everything is visible on the screen, and I usually prefer marks if the start and stop are separated by many screens.
Another simple regular expression is:
%s/^/<text you want to prepend>/
For the C-style comments, use the regexp answer by Brian, and match on line ending $, and insert away.

Resources