Move to the next row which has non-white space character in the same column in VIM? - vim

As source code is usually indented, it will help navigate source code quickly if I can move to the next/previous row which has non-empty white character in the same column. Using below code snippet as example and the cursor in on the last }, is there a way to navigate the cursor to i which starts if?
if (condition) {
// some code
}

To search for the same screen column, you can use the special /\%v atom; the current column can be queried with virtcol('.'). Assert a non-whitespace (\S) at that position, and trigger a backwards search() for it:
:call search('\%' . virtcol('.') . 'v\S', 'bW')
You can easily turn this into a normal-mode mapping.

I've now implemented this motion in my JumpToVerticalOccurrence plugin; by default mapped to ]| / [|. There are other, related mappings like a ]V{char} mapping that works just like f, but vertically.
So if you don't mind installing a plugin (plus dependencies), this is more robust and functional (it supports [count] as well).

Not exactly what you're asking for, but if you start at } and hit %, the cursor moves to the matching {.

If your code has a defined indentation system, jeetsukumaran/vim-indentwise works well for relative, absolute, or block-scope movements across indented blocks.

Related

Delete till first character on next line

I have code that looks like this:
DataAssociator::Impl::Impl(const VoxelHasherSettings& settings_voxelhasher,
const CameraSettings& settings_camera)
{
initialize(settings_camera);
}
When I position my cursor on the c of the first const and press either + or <CR> I move to the next const.
However pressing d+ / d<CR> deletes too much and leaves this:
{
initialize(settings_camera);
}
Why is that the case?
How do I achieve the effect of deleting till the first character on the next line?
I am using neovim.
Thanks in advance,
Richard
When you check out :help +, this mentions linewise. So when you use + in normal mode, it moves (as documented) to the first non-blank, but after an operator (like d or y), all touched lines will be included by default.
You can change that default behavior on a case-by-case basis via :help o_v: So dv+ instead of d+.
Alternatively, you can first go into visual mode; the selection will provide feedback on what text you'll be covering: v+d. A complication here is that depending on your 'selection' setting, this may select one character too much (with the default inclusive selection).
Yet another option for this specific case:
DJx

Vim: match next/previous line in search pattern

I'm trying to practice my search patterns for ex commands and trying to do stuff I would usually do with macros using them, and I got stuck with one I'm not sure is possible.
I have some code that looks like this:
public myFunc (): any {
return {};
}
And I'm trying to yank it with this command (with the cursor after the function):
:?\vpublic\s*\w+\s*\(.*\)\s*:\s*\w+\s*\{?;/}$/y
This works as expected and matches the function that I mentioned up there.
What I would like to do but haven't found a way is to ignore the first line and the last one (I just want the contents of the function). I suspect it is possible to do it somehow (maybe +/- search offsets?), but I haven't had any luck yet.
Does anyone know how to do this? Thanks!
Yes, this is a simple matter of adding the appropriate offsets (:help search-offset). You basically define a range with two searches (one upwards from the current position, one downwards from there): ?...?;/.../. To exclude the targets, you just add / subtract 1; this is done by appending the offset to the search: ?...?+1;/.../-1. Applied to your example:
:?\vpublic\s*\w+\s*\(.*\)\s*:\s*\w+\s*\{?+1;/}$/-1y
To insert carriage return (Enter) like below use Ctrl-v Enter
:normal ?public^Mjwyiw
Explanation
:normal ............ in normal mode
?public ............. search backward for public
^M .................. Enter
j ................... move to the line below
yiw ................. yank inner word

How to select multiple lines until a determinate character?

I would like to select multiple line until a determinate character, like in the image below where the special character is for this example is =.
I've tried with VIM ctrl+v/ but doesn't work.This is the example:
global Tint=spettro.readlines()[3].split(",")[1]
global Average=spettro.readlines()[4].split(",")[1]
global Sensor_Mode=spettro.readlines()[6].split(",")[1]
global Case_Temperature=spettro.readlines()[7].split(",")[1]
global Sensor_Temperature=spettro.readlines()[8].split(",")[1]
You can't in Vim. There's blockwise visual selection (via <C-V>), but this is restricted to rectangular blocks, expect for a selection (with $) that goes to the end of all covered lines, where a "jagged right edge" is possible.
Since selection in itself is of little value, you probably want to do something with it. There are alternatives, e.g. :substitute or :global commands with a pattern that selects up to the first =: /^[^=]*/
To yank the text, I'd use this (there are different approaches, too; note that you need to adapt the range inside the getline()):
:let ## = join(map(getline(1, '$'), 'matchstr(v:val,"^[^=]*")'), "\n")
Try the vim-multiple-cursors plug-in.
Then, to select in those three lines:
/=<cr> go to the first '='
<c-n> start multiple cursors mode
<c-n> create a new cursor and jump to the second '='
<c-n> create a new cursor and jump to the third '='
ho0 select everything before the '='
Deleting and changing the selection seems to work fine. I do not know whether or not yanking is possible, too.
https://github.com/magnars/multiple-cursors.el
I haven't played with it much, but it can probably do what you want. Look at the video.
You can probably achieve your end goal with regex replacement (and maybe a keyboard macro), but you haven't stated what the end goal is. It's generally better to ask how to change one chunk of code into another, and not assume some technique (e.g. multiple selections).

How to delete, including the current character?

Let's say I've typed "abcdefg", with the cursor at the end. I want to delete back to the c, so that I only have "abc" left.
Is there a command like d that includes the current character? I know I could do dTcx, but the x feels like a work-around and I suppose there's a better solution.
No. Backward motions always start on the left of the current character for c, y and d which is somehow logical but also unnerving.
The only "clean" solutions I could think of either imply moving to the char after c first and then do a forward delete:
Tcde
or using visual mode:
vTcd
v3hd
But, given your sample and assuming you are entering normal mode just for that correction, the whole thing sounds extremely wasteful to me.
What about staying in insert mode and simply doing ←←←←?
try this:
TcD
this will leave abc for your example... well if the abcdefg is the last word of the line.
if it is not the last word in that line, you may do:
ldTc
or golfing, do it within 3 key-stroke:
3Xx or l4X
See this answer to a similar question : there is a setting to be allowed to go beyond the end of the line
From the doc :
Virtual editing means that the cursor can be positioned where there is
no actual character. This can be halfway into a tab or beyond the end
of the line. Useful for selecting a rectangle in Visual mode and
editing a table.
"onemore" is not the same, it will only allow moving the cursor just
after the last character of the line. This makes some commands more
consistent. Previously the cursor was always past the end of the line
if the line was empty. But it is far from Vi compatible. It may also
break some plugins or Vim scripts. For example because |l| can move
the cursor after the last character. Use with care!
Using the $ command will move to the last character in the line, not
past it. This may actually move the cursor to the left!
The g$ command will move to the end of the screen line.
It doesn't make sense to combine "all" with "onemore", but you will
not get a warning for it.
In short, you could try :set virtualedit=onemore, and see if your environment is stable or not with it.
Use d?c
That will start d mode, search back to 'c' and then delete up to your cursor position.
Edit: nope, that does not include current position...
I may be misunderstanding your request, but does 3hd$ do it?
I would use vFdd in this example. I think it's nicer than the other solutions since the command explicitly shows what to delete. It includes the current character and the specified character when deleting.
v: enter visual mode (mark text)
F: find/goto character backwards
d: the character "d" that will be included for removal.
d: delete command
Since it is visual mode, the cursor can also be moved before executing the actual removal d. This makes the command powerful even for deleting up to a non unique character by first marking a special character close to the character and then adjusting the position.

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.

Resources