Community Wiki: "Vim: Advanced usage of the yanking mechanism" - vim

Community Wiki
As the documentation of the yank system shows (thanks Michal), The Vim yank system seems to be more intricate then a standard clipboard. I therefore think it beneficial if vim veterans could perhaps show us some different styles of making use of this mechanism. particularly with the usage of vim for complicated projects without the use of a heavyweight IDE (say C++ ?).
Original Question
Now that I am using vim for everything I type, rather then just for configuring servers, I wan't to sort out the following trivialities. I tried to formulate Google search queries but the results didn't address my questions :D.
Question one: How do I yank and replace multiple times ?
Once I have something in the yank history (if that is what its called) and then highlight and use the 'p' char in command mode the replaced text is put at the front of the yank history; therefore subsequent replace operations do not use the the text I intended. I imagine this to be a usefull feature under certain circumstances but I do not have a need for it in my workflow.
Question two: How do I type text without causing the line to ripple forward ?
I use hard-tab stops to allign my code in a certain way -- e.g.,
FunctionNameX ( lala * land );
FunctionNameProto ( );
When I figure out what needs to go into the second function, how do I insert it without move the text up ?
Question three Is there a way of having a uniform yank history across gvim instances on the same machine ? I have > 1 monitors. Just wondering, atm I am using highlight + mouse middle click.

Answer one: A relevant, if not particularly encouraging, qoute from the Vim docs (see :help put-Visual-mode):
When using a put command like |p| or |P| in Visual mode, Vim will try to
replace the selected text with the contents of the register. Whether this
works well depends on the type of selection and the type of the text in the
register. With blockwise selection it also depends on the size of the block
and whether the corners are on an existing character. (Implementation detail:
it actually works by first putting the register after the selection and then
deleting the selection.)
The previously selected text is put in the unnamed register. If you want to
put the same text into a Visual selection several times you need to use
another register. E.g., yank the text to copy, Visually select the text to
replace and use "0p . You can repeat this as many times as you like, the
unnamed register will be changed each time.
Answer two: R (the capital 'R') puts you in replace mode.
I'm missing answer three, I'm afraid.
Answer three: Not quite matching the "uniform yank history" spec, but "+y yanks to clipboard and "+p pastes from clipboard if a clipboard is available.

Yank into a buffer
:y b
yanks into buffer b
And
:p b
places it.
I think there are more named buffers available.

Related

Why does vim use registers for almost every command?

I love the simplicity of composing commands that have semantic meaning. Like, for example cib reads like a sentence change in brackets - wonderful.
But why does vim need to copy the old contents into my clipboard? Nowhere in that command have I suggested I want to copy it and the problem goes much deeper.
dw diw etc all copy to the my clipboard/register as well. Why? It seems like this abandons the semantic value of these commands and I would say it is unexpected behaviour.
Am I using these commands wrong, or is there some way to completely disable this feature? Currently I have done a few remappings like this:
nnoremap dd "_dd
nnoremap cc "_cc
but I would like to not do that for every single possible combination of non-explicit copying.
By default, most of the commands you're talking about use the unnamed register, ". It sounds like you're dealing with the clipboard being overwritten for all these things too, which can be a symptom of setting clipboard to unnamed or unnamed_plus.
To go back to standard, you can probably do set clipboard=, if the output of set clipboard? is one of those two options.
*'clipboard'* *'cb'*
'clipboard' 'cb' string (default "autoselect,exclude:cons\|linux"
for X-windows, "" otherwise)
global
{not in Vi}
{only in GUI versions or when the |+xterm_clipboard|
feature is included}
This option is a list of comma separated names.
These names are recognized:
*clipboard-unnamed*
unnamed When included, Vim will use the clipboard register '*'
for all yank, delete, change and put operations which
would normally go to the unnamed register. When a
register is explicitly specified, it will always be
used regardless of whether "unnamed" is in 'clipboard'
or not. The clipboard register can always be
explicitly accessed using the "* notation. Also see
|gui-clipboard|.
*clipboard-unnamedplus*
unnamedplus A variant of the "unnamed" flag which uses the
clipboard register '+' (|quoteplus|) instead of
register '*' for all yank, delete, change and put
operations which would normally go to the unnamed
register. When "unnamed" is also included to the
option, yank operations (but not delete, change or
put) will additionally copy the text into register
'*'.
Only available with the |+X11| feature.
Availability can be checked with:
if has('unnamedplus')
I'll offer a dissenting view, and suggest that you are likely using Vim non-idiomatically. This is in no way unexpected behaviour. Are you using cib as a preparation for pasting, so that cib screws it up? Do vibp instead.
dw diw etc all copy to the my clipboard/register as well. Why? It seems like this abandons the semantic value of these commands and I would say it is unexpected behaviour.
d then p is the normal Vim idiom for cut-and-paste (i.e. move text). This is an operation I do every day, multiple times per day, and it would be really annoying if d did not also yank. You seem to think d is equivalent of Del on other text editors; it is rather the equivalent of ctrl-x (cut). To cancel this, you'd do "_d as you said; I find that I hardly ever need it.
As an advanced example, the default semantics of c and visual-mode p makes it trivial to exchange two objects; for example:
I drank all their food and ate all their whiskey.
Go to "drank", diw (delete the word and yank it), go to "ate", viwp (select a word and paste over it, yanking the previous content), ctrl-o to go back to where "drank" was and P (paste before cursor):
I ate all their food and drank all their whiskey.
(I also have a plugin which defines "function parameter" as a text object, so I use the same idiom in coding if I mix up, or refactor, the parameter order.)
The only thing I want to prevent more commonly is yank-on-paste in visual mode (so that I can paste the same content multiple times); for this, I use
xnoremap <expr> P '"_d"'.v:register.'P'
(from here). This only remaps P in visual mode (which is otherwise identical to p in visual mode). Neither p nor P outside visual mode yank, so it's a non-issue.

Pasting text in vim. A tedious operation?

I've been using vim for somewhat longer than a year now and during this time I have never feel really comfortable with the way vim works with yanking and pasting text (or maybe it is just me not using it in the most efficient way)
For example, I have the word "World" yanked onto a register, and I want to paste it after "Hello". (Note that there are no spaces on either of the words). So, what I would do is
Hello
|
Place cursor here, and press "p". Then, what I will end up with is
HelloWorld
So, in order to avoid this, I have always to swith into insert mode, insert a espace, and go back into normal mode (or either make sure that the yanked word has a space before it). Be as it may, this is quite annoying behaviour I can't think of a solution for... Am I missing something here?
Suggestions will be appreciated.
Thanks
option zero
just live with what you have now.
option one
create a mapping for your workflow. for example
nnoremap <leader>p i<space><esc>p
option two
:set ve=all
then you could move your cursor to anywhere and paste
option three
you could in insert mode use <c-o> do normal mode stuff or <c-r> to get register values
I recommend option zero
You can use the Smartput : Adjust spaces and commas when putting text plugin for that. It modifies the p / P commands (this can be toggled on / off).

How could I go about changing which buffer Visual mode will empty to when I override text?

I've recently stumbled upon this useful feature:
nnoremap D "_d
Allowing me to do "Dd" or "D$" in order to delete things without overriding the default buffer. However,
nnoremap V "_v
doesn't seem to do the trick when I try and replace text by selecting and pasting over it.
Any suggestions on how I accomplish that?
Thanks in advance.
I don't quite understand what you are trying to achieve.
d is an operator, so you can decide to put the result of the delete operation into a given register; the _ register in your case.
However v is not an operator, it is only a command to switch from normal to visual mode. So I don't think that "_v makes much sense.
You might be thinking of another operator like c (change), y(yank) or p (paste)
To get the full list of operators, type :help operators
You should have a look at :help registers, you might find what you want, it describes all the registers and how they behave.
short extract :
"" is the default register
"0 always contains the content of the latest "yank"
"1 always contains the content of the latest "delete" or "change"
The other numbered registers are used to keep the history of your previous actions.
So rather than avoiding to delete the default register when you are deleting you might use :
"0p when pasting to be sure to paste the last yanked text and not what you have just deleted.
Edit : Add some Vim speak
A buffer is the in-memory text of the file you are editing. It contains the whole file. :ls will display a list of open buffers.
A register is a buffer (for lack of better word) where your deleted or copied text goes. It could be a word, a line, etc. :reg will display the content of all your registers.

Multiple selections in VIM

Is it possible to select multiple non-consecutive lines (or sections) in VIM's visual mode? If so, how?
No, this is not possible without plugins.
But you can copy multiple lines into the same buffer, if that solves your problem.
To start the 'Accumulation Buffer':
mark a section to copy in visual mode,
press "a to operate on the buffer a with the next command and
yank it as usual (y).
To add to that buffer:
mark the next section and
press "A (capitalizing the buffer name means "do not overwrite the buffer, append to it instead")
and yank again using y.
You can then paste the accumulated buffer a at any time using "ap.
You have to install the multiselect plugin to get this capability. Find it here: http://www.vim.org/scripts/script.php?script_id=953
A more up-to-date answer is this plugin.
(disclaimer: I personally don't actually use it, it interferes too much with the rest of my vim setup. If your vim is relatively clean and you are moving over from sublime, this may certainly be your cup of tea.)
I would also like to point out the record/replay functionality of vim (the q key). Quite often recording is also unnecessary, I can do the tasks normally done with sublime's multi-select by doing it iteratively (e.g. search for something, perform the fix on the first instance of it, and then subsequent repeats are achieved by hitting n and N to move around and . to repeat the edit operation).
I do have my , comma key nnoremap'd to #q, this repeats the sequence that is recorded by pressing qq (record into q register).

Is there a way to emulate ReSharper's "extend selection" feature in Vim?

ReSharper has a nice feature called "extend selection": by pressing CTRL+W (I think this is the default) repeatedly, you select more and more from your current caret location. First it's a word, then more and more words, a line, inner then outer block of lines (for example an if-block), then a function, etc...
Basically, by pressing the key combination repeatedly, you can end up selecting the entire file. I'm sure at least some of you will be familiar with it.
I have just started learning all the intricacies of vim and I don't have enough experience to see how something like this could be implemented in Vim (although I assume it's possible). So my question is meant for Vim gurus out there: can this be done and how?
Update: a bit of a background story. I've been talking to my ex-boss about all the benefits of Vim, and he thinks it's all great. His only question/problem was: does it have "extend selection"? My question so far has been no. So, if someone knows the answer, I'll finally win a discussion :P (and maybe create a new Vim convert:-))
I had a quick go at this problem. It doesn't work as is. Feel Free to make edits and post on the vim wiki or as a plugin if you get it refined.
chances are you'd want to make a g:resharp_list for each language (eg. one for paranthesised languages, etc.)
All that is needed is a marker for the original cursor position :he markers and a timeout autocommand that resets the index.
"resharp emulator
"TODO this needs a marker
"also c-w is bad mapping as it has a lag with all the other-
"window mappings
"
let g:resharp_index = 0
let g:resharp_select = ['iw', 'is', 'ip', 'ggVG']
func! ResharpSelect()
if g:resharp_index >= len (g:resharp_select)
let g:resharp_index = 0
endif
exe "norm \<esc>v" . g:resharp_select[g:resharp_index]
let g:resharp_index = g:resharp_index + 1
endfun
nnoremap <c-w> :call ResharpSelect()<cr>
vnoremap <c-w> :call ResharpSelect()<cr>
"Something to reset on timeout. TODO this doesn't work
au CursorHold :let g:resharp_index = 0<cr>
The answer is yes. Once in Visual mode you can use all the regular navigation methods as well as some extra ones.
Some of my favourites? First hit v while in normal mode to get to visual mode then hit:
iw - to select the inner word. Great for selecting a word while excluding surrounding braces or quotes
w - hit multiple times to keep selecting each subsequent word.
b - select wordwise backwords
^ - select all from current position to beginning of text on line
$ - select all from current position to end of line
I'm sure others here could add to this list as well. Oh and don't forget Visual Block mode C-v try it out in vim with the above commands it works in two dimensions :-)
If you're talking about Vim (and you should be :-), you can start marking text with the v command, then you have all the standard cursor movement commands (and, as you know, there are a lot of them) which will extend the selection, as well as moving the cursor.
Then you just do whatever you want with the selected text.
See here for the gory details.
One would need to write a function that would save the current selection, then try increasingly wide selections, until the new selection exceeds the saved one or selects all text. Some possible selections are:
viW - select word
vis - select sentence
vip - select paragraph
viB - select text within the innermost brackets
v2iB - select text within the next most innermost brackets
ggVG - select all text
I think Jeremy Wall's heading in the right direction. And to get a little further in that direction, you might look at the "surround.vim" script from Tim Pope. A good description is available on github. Or, if you'd rather, get it from vim.org. It'll probably help you do some of the things you'd like to do, though it doesn't seem to have a feature for say, simply selecting within a tag. Let me know if I'm wrong.
Ultimately, what you'd really like is a hierarchy of enclosing text-objects. You should read up on text-objects if you haven't. A nice overview is here. Note that you can grab multiple objects in one go using counts, or do this iteratively (try vawasap}}} from normal mode).
You can also get scripts which define other text-objects, like this one that uses indentation to define a text-object. It'll work for many languages if you're formatting according to common standards, and guaranteed for python.
One annoyance is that the cursor ends up at the end of the visual block, so, for example, you can't easily select everything between some ()'s, then get the function name that precedes them...
...BUT, I just found in this post that you can change this behavior with o. Cool!
I suspect you'll find yourself more efficient being able to skip over intermediate selections in the long run.
Anyway, I'll be curious to see if anyone else comes up with a more general solution as well!
In Rider [on a Mac with VS Mac bindings with IdeaVim], I bind:
Ctrl+= to Extend Selection
Ctrl+- to Shrink Selection
Doesn't clash with any other bindings of consequence and doesn't require a v for mode switching, and easier than Cmd+Option+-> and Cmd+Option+<-
Putting it here as I always hit this question with any Rider Vim selection searches. If I get enough harassment, I'll create a self-answered "How to use Extend Selection with Rider Vim mode".

Resources