How to filter visual selection? - vim

Suppose we have some nice bunch of text:
Hello world
and we select the world in visual mode. Then we could filter the visual selection using a shiny command like this one:
:'<,'>!echo foobar
However, that would replace the entire line with foobar instead of just the world. Why is this, and how can we just replace the world?

The :! filter command always works on entire lines (this is as old as the original vi, embedding Ex commands that start with :), and the '<,'> range also only specifies lines.
You can use the venerable vis plugin to achieve your result; it offers a :B command that limits the following command to the visually selected text.
:'<,'>B !echo foobar
The plugin works for all kind of Ex commands; for :substitute within the selection you can also use the special \%V atom, though.

Related

How to execute specific regex substitution on selected lines in visual mode in vim

I want to replicate the VS code feature of 'highlight and comment out code' (usually bound to keys SHIFT + /) in vim.
I can run :g//s/^/\/\/ / in normal mode to prepend // at the start of every line. I just want to put a constraint on this so it only applies the substitution to lines highlighted in visual mode.
Visually select all the lines (using V), then hit :.
This will give you :'<,'> which is the range of your visual selection.
Then you can add your vim command to it.
I would recommend the following method if you wish to not use plugins.
:'<,'>normal I//
Which is not a substitution.
If you want a really nice vim plugin that does this task in a vim manner, check out tpope's vim-commentary which is an essential in my opinion.
I can run :g//s/^/\/\/ / in normal mode to prepend // at the start of every line.
Well, that would be an unnecessarily complicated way to do it and your command wouldn't really work anyway.
:g// either matches nothing or it matches the previous search. What you want, here, is probably something like :g/^/ or :g/$/.
A simple substitution on the whole buffer would be much simpler and much faster:
:%s/^/\/\/ /
Using :help :global in this context provides no value (you want to operate on every line anyway) and is considerably slower (we are talking thousands of times slower)
You can use alternative separators to avoid all that backslashing:
:%s#^#// #
The last separator is not even needed:
:%s#^#// <-- there is a space, here
And the kicker: you can enter command-line mode from visual mode like you would do from normal mode, by pressing :. So you can simply make your visual selection, press :, and run your substitution:
v " enter visual mode
<motion> " expand the selection
: " press :
:'<,'> " Vim inserts the range covering the visual selection for you
:'<,'>s#^#// <CR> " perform your substitution

Selecting a number of lines in visual mode in vim

I have a vim plugin that works mainly with the visual mode. One of its commands sends the visually selected region to an interpreter.
However, I would like to select the first 3105 lines of a file.
1,3105mycommand does not work, this is not implemented in the plugin.
Is there a vim command xx that, after invoking 1,3105xx would visually select the first 3105 lines?
An alternate method:
If the plugin only looks at visual mode's marks, then this might suffice:
1k<
3015k>
If it actually needs the visual mode to be on, then you would need to also add
normal gv
:help :k, :help gv
Note that nvim will start in character-wise visual mode, so change the last line to normal gvV for nvim.
The solution is simple: in visual mode one can use the 3105G command in command mode, typed blindly and that extends the visually selected region.

How to use an external command in Vim to modify the selection

Something I've found useful in other editors is the ability to:
take the selected text
run an external command and pass the selection to its stdin
take the external commands stdout and replace the current selection with it.
This way you can write useful text tools which operate on the selection using any language that can do basic io.
How can this be done with vim?
(Directly in the command line, or via a key binding?)
:'<,'>!command
'<,'> represents the (linewise) visual selection and is automatically inserted when you hit : and have something selected.
Example:
If you select a line containing:
print("Hello!")
and run the Vim command:
:'<,'>!python
the text will be replaced with Hello!.
If you want to set this to a key-binding (F5 to evaluate for example)
vnoremap <F5> :!python<cr>

Vim auto-completion on substitutions and searches in the command line

Is it possible to use Ctrl+n style auto-completion when doing searches and substitution commands in vim?
What I mean is: say I have a variable named myNumber in my current file. If I enter insert mode and type myNu and then hit Ctrl+n, it will autocomplete the word to myNumber (assuming there are no other words that start with those letters).
Is there any way to get this same functionality on the command line? Is there a setting or plugin that will allow me to type /myNu and then hit a key to complete my text search to /myNumber ? Or, more realistically: let me type :s/myN and complete that to :s/myNumber so I can more quickly type out substitution commands?
While in command mode, press Ctrl+f — you will enter command line window. There you can edit your command like in vim. Auto-completion should work too.
Looks like the plugin http://www.vim.org/scripts/script.php?script_id=2222 does more or less exactly what I wanted. Upvoting Kent though, because that's really nifty.
This plugin also enables auto-completion in command line.
https://github.com/vim-scripts/sherlock.vim

How do I repeatedly search & replace a long string of text in vim?

I'm aware of the vim replace command, which is of the form, eg:
:%s/old/new/gc
But what if either of these strings is long? How can I use something like visual selection mode, the clipboard or vim registers instead of having to type the old/new text in?
You can use q: to bring up a command-line window. This lets you use all the vim editing commands to edit the vim command line, including p to paste. So, you could copy the text into a register, paste it into the command line window, and execute it that way.
I recently discovered this feature via vimcasts.
According to the manual, you can use Ctrl+R to insert the contents of a register into the current position in the command line. The manual also claims that Ctrl+Y inserts the text highlighted with the mouse into the command line. Remember that in X11 and some other systems, you can also paste text into a program from the system clipboard using the middle mouse button or a menu command in your terminal emulator.
I think to avoid have your command line be huge you can use this to solve your issue
:%s/foo/\=#a/g
That replaces "foo" with whatever is in register a.
If you're trying to do a substitute with a long complicated search pattern, here's a good way of going about it:
Try out the search pattern using some test cases and refine it until you have the pattern you want. I find incsearch really helps, especially with complicated regular expressions.
You can then use :%s//new to replace all instances of the last searched for pattern.
If you've entered a pattern and want to copy it out of the search history, you can use q/ to bring up a command line window containing recent search patterns very similar to the q: one that contains recent command history.
On the other hand, if you're asking about how to copy and paste text into the substitute command:
I'd write the pattern out in insert mode and yank the search and replacement into two distinct registers using, say, "ay and "by and then use :%s/<C-R>a/<C-R>b/gc to do the substitute. There are lots of variations of the yank command, but this one should also work automatically when using a visual selection.
If you're copying in text from the clipboard, you can use <C-R>* to paste it's contents in insert mode.
I have the following mapping in my .vimrc
vnoremap <leader>r "ry:%s/^Rr/
So I visually select the thing I want to replace, and hit ,r, type the replacement and hit return. If I want to paste the replacement, I yank it before selecting the text to replace, and then use <C-r>" to paste it as the replacement before hitting return.
Note: to insert ^R in your .vimrc, you actually type <C-v><C-r>.

Resources