Resetting Buffers in Vim - vim

Is it possible to reset the alternate buffer in a vim session to what it was previously?
By alternate buffer, I mean the one that is referred to by #, i.e. the one that is displayed when you enter cntl-^.
Say I've got two files open main.c and other.c and :ls gives me:
1 %a "main.c" lines 27
2 # "other.c" lines 56
Say I open another file, e.g. refer.c, :ls will now give me:
1 %a "main.c" lines 27
2 "other.c" lines 56
3 # "refer.c" lines 125
If I delete the buffer containing refer.c, :ls now shows:
1 %a "main.c" lines 27
2 "other.c" lines 56
But if I do a cntl-^, refer.c will be displayed again!
Is there some way to get vim to reset the alternate buffer back to what it last was automatically? A "history" of alternate buffers?
Or am I stuck with doing a :2 b to reload other.c into the alternate buffer?
Or maybe there is a good reason for this behaviour?

In this case, "alternate" just means "previous". So, yes, :b2 (or 2 ctrl-6) is probably the easiest way to change which two buffers will be toggled by ctrl-6.
Also, take a look at the :keepalt command.

As you'll come to expect with Vim, there is an excellent reason for this behaviour. :bd (mnemonic for buffer delete) does not delete the buffer, per se, it deletes it from the main buffer list!
If you try :ls! or :buffers! you will see it is is still available but with a u adjacent to it's buffer number, indicating it is now "unlisted" (that is, unlisted unless you list it with an exclamation mark!).
I'm making it sound as horrible as possible, but as with most of Vim it works once you understand it, and the use of exclamation mark / bang to force the command is consistent.
To get rid of the buffer completely you need to wipe it using :bw. When you have done that you will still have the same problem, but this time, attempting to switch to the alternate buffer with CTRL-^ will elicit No alternate file (because this time it really has gone).
To switch to the file you want, yes, use the buffer number: :b2, or whatever the buffer number is of the file you want, and that will establish a new alternate buffer.
I find it's easy to remember buffer numbers or look them up with :buffers or :buffers! really quickly, and of course changing to them is then quick, but of course there's a range of techniques in Vim for changing buffers, especially including marks.
You've also discovered another great Vim feature here, the unlisted buffers. When you're dealing with a few extra files it's sometimes helpful to "delete" them from the :buffers list using :bd, just to get them out of sight, but although hidden they're not unavailable, and you can check which one you want with :buffers! and then :b<num> to pull it up, without having to undelete it or anything.

Related

How to remove buffer from jumplist in vim

How could I delete a buffer and remove it from the jumplist? so that the next time I hit <CTRL-o> or <CTRL-i> it doesn't open it again.
To do that you should use one of the built-in commands provided by vim
:bdelete that only closes the buffer and replace it with the one next to it in the jumplist unless there are changed that has not been saved, if you want to delete the buffer and discard the changes :bdelete! is what should be used.
The problem with :bdelete[!] is that only the buffer will be deleted but everything else related to it will stay there like it's position in the jumplit and the marks that registered on it and so on.
So the second command that I find very powerful is :bwipeout[!] which will remove the buffer completely and all the metadata related to it.
With both these commands you can specify counters and ranges, for example:
to delete all buffers use :%bd[elete][!]
to delete all buffers from buffer number 4 to the last one use :4,$bdelete[!] and so on.
the same goes for :bwipeout[!]

Vim discards input characters at startup

I have been driven crazy for years with Vim's behavior of throwing away input characters. I start vim like this:
$ vim file.c
and then immediately begin typing commands. However, Vim discards some of those characters, causing the wrong action to take place.
Is there something we can put in the .vimrc to solve this issue?
Vim should be able to change the TTY to raw mode without flushing buffered input.
Update: the issue is more precisely characterized, thanks to the following investigation method. I created a script called delayvim which contains:
#!/bin/sh
sleep 2.0
vim "$#"
Now during this two second pause I can type something like iabc<ESC> and then when Vim comes up, everything is cool: the command is processed, abc is inserted and Vim pops back into command mode, with the cursor backed up over the c. Thus, it is not simply flushing the TTY input buffer.
However, if I keep typing during this delay, for instance iabcdefghijk..., it will sometimes lose a letter or two of the alphabet that is typed right around the time when the sleep terminates and the editor launches. For instance, here is the result of one trial I just performed:
abcdefghilmn_
~
~
Where are jk, oops? I am sure I typed them. I didn't type very fast; my cadence was around 4-5 strokes per second, yet two consecutive events disappeared.
Basically, it might be trying to interrogate the terminal, and in the process discarding the input that is mixed up in the response. Or it could be a combination of reading some of the prior input, then flushing the input buffer and losing the rest.
2 points that might help:
1) are you being sure to hit i first, to enter input mode, so that all characters you type afterward should go ahead and be seen in your buffer (on the screen?). Otherwise the letters you type will be processed as commands, which will often do nothing, especially if you're starting an empty file.
Note that a and o are other common commands for telling vim that you are about to begin inserting text starting with the next keystroke.
2) In case the reason on your system has to do with speed, you can look for options to change what happens at startup. For example, if you put this in your .vimrc file
autocmd VimEnter * :sleep 5
Then after processing other startup files, vim or gvim will literally do nothing for 5 seconds before showing your file on the screen. On my system, I was able to type iabcdef during those 5 seconds and when the time was up, I did see abcdef entered into my text file.
If your file was not empty, beware, as (depending on your settings) your vim installation might be kindly returning you to the last place you were editing inside the file, and you will have inserted the text there, instead of at the start.
If this doesn't work, you could try to find other things vim can do (on the web, or using :help from within vim) and program it using autocmd to happen at startup to see if it helps.

Is there a way to show line numbers at end of the line in Vim

I am using
set relativenumber
set number
which let's me move easily around. However, it is often hard to know the exact the line number of the object where I would like to jump to because I first need to look to the left. I feel it would be easier if I could see the line numbers also on the right hand side right because my eyes have less space to follow (maybe?). I think the ideal setting would be to show the relative/absolute line number where the $ appears when whitespace characters are shown and to the left/right of the buffer. I.e.
1 Random text.$1 1
159 This is the line where the cursor is.$159 159
1 Some random text.$1 1
2 More random text. Another sentence. Maybe a third one? And so on.$2 2
3 Another line which might be quite long and my eyes focus somewhere here.$3 3
4 More random text containing more text and more words and stuff.$4 4
(In this example, I would like to do 3k but I may type 2k or 4k because I did not follow the correct line to the left.)
Is it possible to achieve this somehow?
Any suggestion on how to change my workflow are welcome, too.
Note: Using cursorline does not help as I do not seek the number of the current line.
No, there is no built-in support to your requirement. also I don't think this is easy to be done by plugin.
Maybe you could consider to change your habit/workflow. E.g. enable the cursorline option, to highlight your "current" line, it may let you easier to identify which line are you on right now.
To move cursor, if you don't want to count lines, you may want to try the EasyMotion plugin. It is very handy plugin. However it won't replace the hjkl ... motions.
No, that's not possible, unless you modify Vim's source code in a non-trivial way, or work around with kludges like a vertically split small scratch buffer at the side that is updated via autocmds.
Do you have :set cursorline? That helps (me) a lot to follow the current line, even with large window widths. Reducing those might help, too, though you have to deal with wrapping / scrolling of long lines then.

vim Jump to the next non-identical line

I am looking at files that may have several consecutive identical lines.
Is there a easy way of jumping to the next non-identical line?
Alternatively I would like to be able to fold all the lines that are equal to the initial one showing just the number of linees that are folded.
You could define your own fold-expr:
first set fdm:
:set fdm=expr
then
:set foldexpr=getline(v:lnum)==#getline(v:lnum-1)?1:0
now you can test by typing zM, to close all fold, if you are lucky ^_^ all duplicated lines are folded.
you could type zR to open all folds.
if it works and you open those kind of file very often, you could put the above lines in your .vimrc.(au with ft) if only one time job, you can write mode line into that file.
Try this:
:nmap <F2> "1y$<CR>/^\(<C-R>1$\)\#!<CR>
It maps F2 to:
copy the current line into register 1
search for (and move to) the first line that does not match the contents of register 1
This seems to work well, unless the text of your copied line has escaped characters that will confuse the search regexp. This is because register 1 is just dropped into the search expression without escaping. This would be tricky to fix reliably, but for normal log files, it shouldn't be much of a problem.
Also: if you're not married to vim and just need to read the non-consecutively-duplicated lines of a file, the canonical UNIX way is:
uniq filename
If you want to be in vim but won't need to make changes to the file, try:
:%!uniq
(If you try the latter, be sure to exit without saving)

Use vimdiff to replace entire file?

I'm using vimdiff for a git merge. Is there a quick way to select 1 file to use, right now i'm just selecting everything from one buffer, replacing the $MERGE with that, and then saving. I guess I can macro that, but was wondering if there is a better way.
Thanks!
Several ways:
:%diffput
to do 'put' all changes from the current buffer to the 'other' buffer. This makes it easy with three-way diffs:
:%diffput OURS
The 'OURS' pattern will match uniquely on buffernames participating in the current diff
All the above can be done in reverse, substituting do or :diffget
You should take a look at Tim Pope's Fugitive plugin. It's a really usefull plugin.
When you run Gdiff in a conflicted file, 3 files are opened - target, merged and working copy. You would switch to the file you want to save, and execute Gwrite! to save that file.
There is a whole Vimcast explaining how to resolve merge conflicts with this plugin(And other 5 vimcasts explaining more about Fugitive.vim).
I think :%diffget LO or :%diffget RE is what you need.
Note: you need to run it in the MERGED part of vim windows. You can move cursor around the windows using Ctrl+w;←/↑/→/↓
Make sure that all participating buffers are in diff mode (see :h start-vimdiff on how to start diff mode)
Do v for VISUAL MODE in the Base
Select the whole file (press Page Down all the way)
Write : then diffget <buffer number/name> (: ls will list all buffers, generally in vimdiff they are from right to left 1-3 or 4 if 3 way diff)
Afterwards just : wqa and you are done
Alternatively, after step 0., one could do :%diffget <buffer number> to get all changes from the specified buffer as :diffget also accepts ranges. (See :% and :diffget.)
The reverse would also work: :%diffput <buffer> will send all changes to buffer number, making the two buffers have the same content.

Resources