Vim: delete inside matching delimiter as in Neovim - vim

As a Neovim user, I am able to type di( (also di", di{ and so on) in order to delete the content delimited by matching brackets/quotes. For example, in a situation like the following
(cursor here)
/
void foo(int bar)
-
By running di( I would get
(cursor here)
/
void foo()
-
And by running da( I would get
(cursor here)
/
void foo
-
However, in vim this behaviour can be accomplished only by placing the cursor on the starting bracket/quote first. So di( works only if the cursor is positioned as follows
(cursor here)
/
void foo(int bar)
-
Because of that, in vim I have to run f(di( or F(di( according to where my cursor is on the line in order to move the cursor to the starting delimiter and, then, deleting the content. In neovim I can, instead, directly run di( obtaining the same result.
Is there any remap I can set in order to make vim behave like neovim does?

Vim used to treat nesting pairs (where the beginning and end are different) and non-nesting pairs (where the beginning and end are identical) differently but it all changed late in 8.2's lifecycle.
Your Neovim build includes the patch but your Vim build doesn't.
Update Vim to a version > 8.2.3255 and you will have the desired behavior.

Related

How to match git conflict markers with %

In vi and vim, % can be used to find a matching symbol e.g.:
/** <- With the cursor on / ...
* Some comment
*
...
*
*/ <- % moves the cursor to the / on this line
This works with matching {}, () [] pairs, and also works with c-conditionals like #ifdef.
Is there a setting to make this work with git conflict markers?
#! /usr/bin/env ruby
def hello
<<<<<<< HEAD <- With the cursor on this line
puts 'hola world'
=======
puts 'hello mundo'
>>>>>>> mundo <- % moves the cursor to this line
end
Can (and how) vi and/or vim be configured to do that?
In your startup files (eg $HOME/.vimrc) you can add:
packadd! matchit
let b:match_words = '<<<<<<<:=======:>>>>>>>'
packadd! enables the optional plugin, and match_words specifies the match pattern. Note that this will override any previous assignment of match_words, and this sort of thing is typically better suited to store in a filetype plugin. Adding those two lines directly in the main startup file should work, but may not be the best solution. (eg, if you're merging a file whose type is recognized, the filetype plugins may override the setting of match_words)
Assuming you are actually talking about Vim (which makes this configurable) and not vi (which doesn't).
The functionality is documented under :help %:
% Find the next item in this line after or under the
cursor and jump to its match. |inclusive| motion.
Items can be:
([{}]) parenthesis or (curly/square) brackets
(this can be changed with the
'matchpairs' option)
/* */ start or end of C-style comment
#if, #ifdef, #else, #elif, #endif
C preprocessor conditionals (when the
cursor is on the # or no ([{
is following)
For other items the matchit plugin can be used, see
|matchit-install|. This plugin also helps to skip
matches in comments.
From there, you can follow the 'matchpairs' tag to :help 'matchpairs', which won't help you because you can only add pairs of single characters like <:>.
You can then follow the promising matchit-install tag, which should put you on the right path.
Try harder.

Easy motion vim plugin mapping issue

I have the vim EasyMotion plugin installed.
Pressing,
<Leader><Leader>f searches forward from the current line.
<Leader><Leader>F searches backward from the current line.
Is there a way to search the entire visible part of the buffer only using 'f'? I would ideally not want to use two different bindings for searching forwards and backward. One single binding to search the entire visible portion of the buffer would be most ideal.
You can try a mapping like this:
nnoremap <leader><leader>f :execute "/\\%>" . line('w0') . "1\\%<" . line('w$') . "l"<left>
That's a confusing syntax, so I'll unpack it.
line('w0') and line('w$') return the line numbers of the first and last visible lines in the buffer, respectively, so you use them to find the range for the visible part.
The / search command allows a range to be specified, but with an odd syntax. The format is /\%>Xl\%<Yl where X is the line to start from and Y is the line to end at.
It's not possible to just drop the results from line() into a normal / invocation, but we can build a string, using . to join segments together, and once the command is built, pass it in to :exec to make it happen.
Finally, there's the <left>. That's for cursor positioning. When you execute <leader><leader>f, the whole mapping fires as though you were typing it, so you end up with the full :exec command on the line, and it ends with a ", but you want to type inside those quotes. Alternatively, you could remove "<left> from the end of the mapping, but then you'll have to remember to close the quote after typing your search term.
I'm not familiar with EasyMotion, so this may not give you exactly what you were asking for (I realized this after I typed up the answer), but it will let you run a search in the currently visible part of a buffer only, and you can probably adapt it to EasyMotion's purposes without too much difficulty.

How to delete a paragraph as quickly as possible

I want to delete the following codes in my config file:
server {
listen 80;
server_name xxx;
location / {
try_files xx;
}
}
I know I can use 7dd, but this is not handy enough- if the section is too long, counting the rows would be inconvenient.
Is there a better way to do this?
Sometimes, I have to delete a whole function, any ideas for that?
As in common in Vim, there are a bunch of ways!
Note that the first two solutions depend on an absence of blank lines within the block.
If your cursor is on the server line, try d}. It will delete everything to the next block.
Within the entry itself, dap will delete the 'paragraph'.
You can delete a curly brack block with da}. (If you like this syntax, I recommend Tim Pope's fantastic surround.vim, which adds more features with a similar feel).
You could also try using regular expressions to delete until the next far left-indented closing curly brace: d/^}Enter
]] and [[ move to the next/previous first-column curly brace (equivalent to using / and ? with that regex I mentioned above. Combine with the d motion, and you acheive the same effect.
If you're below a block, you can also make use of the handy 'offset' feature of a Vim search. d?^{?-1 will delete backwards to one line before the first occurrence of a first-column opening curly brace. This command's a bit tricky to type. Maybe you could make a <leader> shortcut out of it.
Note that much of this answer is taken from previous answer I gave on a similar topic.
If there is a blank line immediately after these lines, Vim will identify it as a paragraph, so you can simply use d} to delete it (assuming the cursor is on the first line).
Try using visual mode with %.
For example, say your cursor is at the beginning of the "server" line.
Press v to go into visual mode. Press % to highlight to the end of the block. Press d to delete it.
As David said their are many ways. Here are a few that I like:
Vf{%d This assumes you are on the line w/ server and you do a visual line selection, find the { and then find the matching } via the % command.
set relativenumber or set rnu for short. This turns on line numbering relative to your cursor. So you do not have to count the lines just look and 7dd away to deleting your block.
Use VaB to visually select a block i.e. { to }, line-wise. While still in visual mode continue doing aB until the proper block is selected then execute d. This means you can select a block from inside the block instead of at the start or end.
d} will delete a paragraph. This works in your current scenario because there is no blank line inside the block. If there is one then all bets are off. Although you can continue pressing . until the block is properly deleted.
If inside a block you can jump to the current block via [{ then continue executing [{ until you are at the correct block then V%d or d%dd to delete the block
Using the techniques above you can delete a function as well, but you can also use the [M and friends ([m, ]m, ]M) to jump to the start and endings of methods but they commonly work for functions as well.
For more information
:h %
:h 'rnu'
:h aB
:h }
:h .
:h [{
:h [m
Given matching parens, or braces, you can use % with d to delete, spanning lines.
So, assuming that you're on the server { line, you can do d%. This is generally useful for all code blocks, e.g. function blocks, loop blocks, try blocks.
Similarly, dip works, but d} is shorter. However, both will only delete to the next empty line.

How to run a search and replace command without cursor moving in Vim?

In Vim, when I run a substitution command like
:%s/foo/bar/g
it replaces all occurrences of foo with bar in the entire buffer. When it completes, the cursor moves to the last location where foo was replaced with bar.
How can I run :%s/foo/bar/g without having the cursor leave its original location where it was before the substitution command was issued?
Is there some option I can set in the .vimrc file?
When the :substitute command is run, prior to any replacements being
carried out, the current position of the cursor is stored in the jump
list (see :help jumplist).
In order to return to the position before the latest jump, one can use
the `` or '' Normal-mode commands. The former
jumps exactly to the stored position; the latter jumps to the first
non-whitespace character on the line the stored position belongs to.
It is possible to both invoke a substitution command and move
the cursor back afterwards, at once, by issuing the command
:%s/pat/str/g|norm!``
or, if jumping to the containing line is sufficient, by using
the command
:%s/pat/str/g|''
It is not necessary to preface '' with norm! in the latter
command, because the '' address is allowed by the range syntax
of Ex commands and refers to the same line the Normal-mode
command '' jumps to (see :help :range); both just look into
the contents of the ' psudo-mark.
I just type Ctrl+O after the replace to get back to the previous location.
It's old, but for anyone coming across this question, I wanted to share my solution since it will work correctly even if nothing is substituted:
:exe 'norm m`' | %s/pattern/substitution/eg | norm g``
exe is needed since norm treats the bar as an argument.

Vim: replacing text within function body

I have some very useful plugins to find and replace text through files (see EasyGrep vim script - it's very helpful for programmers). I can even replace text only in the current buffer - by using plugins or :%s .... But what if I just want replace text within the current function body?
Consider the following example:
void f0()
{
int foo = 0;
// ...
}
// 99 other functions that uses foo as local variable.
void f100()
{
int foo = 0; // I want to replace foo with bar only in this function
// 1000 lines of code that uses foo goes below
// ...
}
Of course, I can use :%s ... with c flag for confirmation, but I believe there is a faster way to do this.
Thanks.
You can apply a substitution to the whole file using % or on a selection.
To create a selection :
Go in Visual mode Linewise for example, with Shift+v, select a few line and then type :.
Your prompt will look like :
:'<,'> it means : current selection
Type then s/foo/bar/g and it will replace foo by bar in the current selected line.
The better way to select a function content is to go inside a function with your cursor and type :
vi} it will select everything between { and }.
See :help text-objects for more tips on selection.
You could mark the function with V. Then when you type a command in :, it'll automatically be prefixed by and only be executed in the marked area.
There's probably a command for jumping to beginning of function and end of function, so you could do begin-function, V, end-function, substitute very quickly. Don't know those commands though.
I've always used [[ to jump to the beginning of the function, then use % to jump to the end of the function. I used mt and mb to mark the top and bottom of the function, respectively. Then to search and replace within the marked top and bottom, :'t,'bs/pattern/newpattern/g. This has always worked for me. I'm sure you can create a macro for this.
The visual select (vi}) is much easier and faster. It is aware of the cursor position. So, if the cursor is inside a fucntion sub block, then vi} selects all lines in that block. If you want to select the entire function, one needs to place the cursor outside of the sub blocks then do vi}. This is great for function blocks that fits in the current window. For functions that spans beyond the current window, the selection is lost once scroll up.
I really like the visual select of the vi} because it's so much easier and faster, but I have to resort the old school method on occasion.

Resources