Vim: search first match after match of another pattern - search

How can I find the first occurrence of bar after the next occurence of Foo using one command/search pattern in Vim?
Ex: Suppose I have some text like:
Bar and bar and bar, I'm such a barbarian.
...
Foo: That bar serves German beer.
Bar bar and bar, so much bar.
Foo: Unrelated.
...bla
but then next bar.
How do I jump between the bolded bars?

The first way that came to mind (easy but not repeatable)
You can do something like this:
/Foo/;/bar
but the "last pattern" will be bar so this is not repeatable with n, N, etc. which means that you will have to do it once and then do /<Up><CR>, which may or may not satisfy your needs.
Note that, once you have jumped to the second match, you can do `` to jump back to the first one and `` to jump back to the second one, and so on.
See :help :; and :help ``.
The second way that came to mind (more complicated but repeatable)
With a single pattern, and thus repeatable with n, N, etc., you can do:
/Foo\_.\{-}\zsbar
where…
/Foo matches the next Foo,
\_.\{-} matches any character including EOL, as few as possible,
\zs starts the actual match, discarding what comes before,
which we want to be bar.
See :help \_., :help \{, and :help \zs.

I haven't figured out a way to combine the following two methods, but they answer your two requests independently.
How to find the first occurrence using one command::norm /Foo^M/bar^M
where ^M is not typed directly, you must press ctrl (or in my case ctrl+shift), then press v, then m. ^M means enter/return button, so you're basically doing two separate searches in one line. Because they're separate, doing n or N to move forwards or backwards only moves forward and backwards between bar, whether or not they come after a Foo. Which leads to:
How to move to the next bar that comes after Foo. You can do this by recording a macro. Press q then the letter to store the macro to start recording, then you can do a /Foo search, then a /bar search. Press q again to stop recording. Now you can just do #a where a is the letter you chose, and that will get you to the next bar after the next Foo. You can repeat the command to keep searching forward, or you can create another macro for doing the search backwards.

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: substitute once, starting from CURSOR position (not line)

Is there a simple way (without too many keystrokes), to substitute the next occurrence of a pattern (in the line or in the whole document, both would be interesting), starting from the cursor position?
So far, I've only come up with selecting onwards, going to normal mode, and doing :s/\%Vpattern/rep. It's too cumbersome. Perhaps there's a nice way to select the next occurrance of a pattern, and then one can "change" the selection?
Thanks
You can use the confirm option with your substitution. Use the command
:%s/pattern/replacement/gc
It will take you through each occurrence of the pattern. Type y to replace, n to move on without replacing, and q to quit the search.
You can use gn
Just search for the pattern, using /
Select using gn
Once selected, you can perform any action on it. Like y to copy, c to change etc
:h gn

Vim - Commands to visually select a regex match?

Can't figure out how to automatically select a regex match in visual mode.
For example, manually, I could search for a word
/word
It lands the cursor on the first character of the match "word".
Then I press v to enter Visual mode, and press llll to select the whole "word".
Now I want to do this by a macro, and I don't know the length of the match ahead of time.
I expected that Vim would automatically define some built-in marks at the beginning and end of the current match, so that I could ` to them. But I couldn't find any information on that.
What I want is to reassign Ctrl+n to a macro to take me to the next match and select it in visual mode, i.e. not just highlight the match. (To parallel how n takes you to the next match.)
If you're wondering why, its because I want to create folds based on regex matches (like Ctrl+n, zf), but I'm sure it will come in handy in other cases too.
//e takes you to the end character of last search.
More info -- :help {offset}.
You can find how to restore old search buffer here.
For the benefit of folks who stumble across this question in the future, vim now has this feature built-in: gn (and its close sibling gN) will jump to the next (respectively, previous) match and visually select it. It can also be used as a motion; e.g. cgn will jump to the next match and change it.
:noremap <C-n> //s<CR>v//e+1<CR>
Edit summary: was //e, but //e+1 worked for me (selected the last character of the match too).

Move to start and end of search lookup

In vim/gvim I would like to be able to move to the front and end of the current search lookup. Is this possible?
For example, with this file:
A dog and a cat
A hat and a bat
I would like to be able to perform a search, for example /dog\sand and then be able to move from the beginning of the 'dog and' expression to the end and back so that my cursor starts on column 3, under the letter 'd' of the word 'dog' and then moves to column 9 under the letter 'd' or the word 'and'.
The reason I want to be able to do this is so that I can search for an expression and then use the change command, c, combined with a movement command to replace that particular search expression. I don't want to use substitue and replace here, I want to perform this operation using the change command and a movement key.
You are looking for cgn. From :help gn:
Search forward for the last used search pattern, like
with `n`, and start Visual mode to select the match.
If the cursor is on the match, visually selects it.
If an operator is pending, operates on the match.
E.g., "dgn" deletes the text of the next match.
If Visual mode is active, extends the selection
until the end of the next match.
The beauty of this is you can do cgn and then repeat the command with . and, yes, it will do the same operation on the next search pattern match. This becomes extraordinarily useful when you start searching with complicated regular expressions.
Try ths:
/pattern<cr> to place the cursor at the start of search pattern
/pattern/e<cr> to place the cursor at the end of search pattern
You can change to the end of the match with c//e<CR>. And //<CR> will take you to the beginning of the next match. You could probably work out some kind of bindings for those that make sense. For instance I just tried the following, and it seems to work nicely:
:onoremap <silent>m //e<CR>
So that you can say cm for change match. I'm not sure what I would map //<CR> to, though. I tried mapping it to n, and it seemed to work fine. Don't know if that would be a problem for you.
:nnoremap <silent>n //<CR>
Since you know just how many words you're searching for, why not just move there and then back using word movement commands? I.e., "2w" to go to end of current search result, and "2b" to go back.

Iterate through search results by column

Is there a way in Vim (or a plugin) to search for a term and iterate through the search results (as per n in Vim), by column, rather than row? So if my file was this:
foo1 bar bar
baz baz foo3
baz baz foo4
foo2 bar bar
If I search for foo I want to iterate through the results in order 1,2,3,4. Normally n would move me through them in order 1,3,4,2.
I want this for example to browse through search results in a huge fixed-width data file or CSV file, where columns represent fields.
(I'll also settle for a way to do it in Emacs instead. :)
After seeing this question I decided to try and write a vim plugin to handle it. It's my first vim plugin, so it's probably very bad. However, it does work for the example you gave.
You can download the plugin from vim.org: SearchCols.vim
Note that it also requires the multvals plugin from the same site: multvals.vim
It creates a command :SearchCols <string>, which can be used to search for the <string> in fixed-width columns so that the search looks in the first column first, then the second column, etc. rather than the row-by-row search which is standard for vim. Repeat the command via #: and then ## since it's a colon-command.
Assumptions:
Assumes that your file is formatted with whitespace-delimited fixed width columns, i.e. there are no spaces inside the data items, only in between them.
Assumes that the first line of your file is formatted so that the column widths can be deduced from it.
Obvious improvements that I can think of would be to make searching for the next item easier than using #: and ##, including search highlighting (the code is there but it's commented out because it uses :match and you would have to use :match none to turn it off), and eliminating the dependency on multvals.vim.
EDIT: I just found an overview of using vim regular expressions for tables here. That's a lot cleaner than my amateur attempt (although this works too ;)):
searching for ^foo will search the first column, while searching for .*\ foo will search the second column, and .*\ .*\ foo will search the third.
This is not complete of course since it matches a whole block from the start of the line, so it will find foo3 and foo4 but puts the cursor at position 0.
You can however automate this with the recording function. Type exactly the following in normal mode:
qa/.*\ .*\ foo
/foo
q
(where I have used new lines to indicate you should hit the return key).
This puts two searches under the a register (qa starts recording under a, qb under b, etc). Now hit #a and you should search only the third column....
I'm sure you can turn this into a command that takes a column number, but I'm off now, sorry :)

Resources