If you have any NERDTree instances open when you quit VIM then when you open your session again you get a number of errors:
Error detected while processing BufLeave Autocommands for "NERD_tree_*":
E121: Undefined variable: b:NERDTree
Error detected while processing WinLeave Autocommands for "NERD_tree_*":
Error detected while processing BufLeave Autocommands for "NERD_tree_*":
E121: Undefined variable: b:NERDTree
Error detected while processing WinLeave Autocommands for "NERD_tree_*":
I am trying to execute :tabdo NERDTreeClose automatically when vim exits (e.g. with qa or wqa or qa! etc)
I am adding:
autocmd VimLeave * tabdo NERDTreeClose<CR> or
autocmd VimLeave * :tabdo NERDTreeClose<CR>
with or without <CR> at the end but I can't make it work.
Any suggestions?
I have previously encountered the exact same issue with the combination of
creating (and reentering) [neo]Vim-sessions and multiple NERDTree-instances.
My solution, which might not be the precise answer that you are looking for
due to the reason that will be explained later, was to first close all NERDTree
instances before creating or updating the [neo]Vim-Session for later usage.
What you have been trying so far with the tabdo is thus a few "stages" too
late, as the triggering event for auto-command is VimLeave.
My primary suggestion (also my personal resort) is to create a quick
key-bind that performs the two procedures I stated above combined with a quick
save-all in serial:
cnoremap W tabdo NERDTreeClose <bar> wa <bar> mksession! ~/.vim/My_Session.vim
which can be comfortably remembered as the bigger brother of the default w in
commandline-mode for saving (a single buffer).
The one caveat of this method is that all instances of NERDTree will be closed
when reentering the session saved from above. This, however, can be somewhat
remedied by calling NERDTreeToggle with VimEnter as the triggering event for
autocmd.
If you insist on utilising autocmd for this, I would suggest putting the two
procedures enlisted above into a function and use autocmd to call that
function (with the [neo]Vim command: call) upon VimLeave just like you have
tried before, of course under the assumption that you feel compelled to save the session during every exit. I personally do not endorse this, as instances were abundant where
I would quickly fire up [neo]Vim for a quick note of something inconsequential
and swiftly exit, which certainly does not require that the session be saved.
As a sidenote: the syntax of autocmd:
:au[tocmd] [group] {event} {pat} [++once] [++nested] {cmd}
thus, substitute cmd with a command directly, i.e., the prefixing colon as you
have tried in your original post is a malpractice.
Related
I use MacVim and in my .vimrc file I have map ,V :source $MYVIMRC<CR> binding that allows me to apply the newest version of .vimrc in a case it was recently modified.
However I noticed that strange things can happen, relaunch can slow down vim and some plugins can start to conflict after pressing ,V, when everything works fine if I just close and relaunch MacVim from the scratch.
I'd be very thankful if you could give me a hint on the reason of this behavior as I'd like to have a possibility to update .vimrc file that will completely clear internal vim state and grab new configuration file
The only viable way to re-apply your config to a pristine Vim is actually to restart it.
But the most likely cause of slow downs is the overuse/misuse of autocommands.
Autocommands are added without checking for existing ones. One consequence is that they tend to pile-up if you don't manage them properly and every individual autocommand corresponding to a specific event is executed when that event is triggered, leading to dreadful slow downs.
Here are the two ways you are supposed to use autocommands in your vimrc:
Method #1
" anywhere
augroup nameofthegroup
autocmd!
autocmd EventName pattern commandtoexecute
autocmd AnotherEventName anotherpattern anothercommandtoexecute
augroup END
Method #2
" near the top of your vimrc
augroup nameofthegroup
autocmd!
augroup END
" anywhere
autocmd nameofthegroup EventName pattern commandtoexecute
autocmd nameofthegroup AnotherEventName anotherpattern anothercommandtoexecute
The idea is to create a group of autocommands that clears itself whenever it is invoked and thus prevents them from piling-up.
I want to execute system("cp /home/currently_opened_file.txt /somewhere/else") when I exit vim with :wq. Is there an autocmd event for that? Or any other way to do it?
Update:
The OP noted in comments that this combination did exactly what was wanted (execute the command only on :wq).
:autocmd BufWritePost * :autocmd VimLeave * :!cp % /somewhere/else
Original answer:
You can hook the BufWritePost event. This will run the command on every write, not only when you use :wq to leave the file.
:autocmd BufWritePost * :!cp % /somewhere/else
I suppose you could try hooking the BufDelete event (before deleting a buffer from the buffer list), but that seems like it would be problematic, as buffers are used for more than file editors. They are also used for things like quicklists, the help viewer, etc.
There are some events that take place when you are quitting, which could be an option.
QuitPre when using :quit, before deciding whether to quit
VimLeavePre before exiting Vim, before writing the viminfo file
VimLeave before exiting Vim, after writing the viminfo file
You can see the full list using :help autocmd-events.
Also note that you can restrict what matches the event. For instance, if you only want this to happen for HTML files and CSS files, you could use this:
:autocmd QuitPre *.html,*.css :!cp % /somewhere/else
I suspect you will need to experiment and see what works for you.
It looks like you need to automatically cascade the writing of a file to another location. My DuplicateWrite plugin provides comfortable commands to set up such. (The plugin page has links to alternative plugins.)
:DuplicateWrite /somewhere/else
I would like to do some code reformatting whenever :update command is executed, is this possible?
I can't find any autocommand hook for updating, only for :w command.
:update basically is execute :write if buffer is modified, else do nothing. The same BufWritePre / BufWrite events apply to it (when the former case is true). That should be perfectly suitable for your reformatting trigger.
To only trigger on :update, but not on :write would require re-writing the :update command itself. For interactive use, that could be done via the cmdalias.vim plugin, which allows redefinition of lowercase built-in commands.
From vimdoc:
:checkt[ime] Check if any buffers were changed outside of Vim.
This checks and warns you if you would end up with two
versions of a file.
If this is called from an autocommand, a ":global"
command or is not typed the actual check is postponed
until a moment the side effects (reloading the file)
would be harmless.
How can I use it from an autocmd without delay?
EDIT
I somtimes use vim and an IDE to edit the same file, and I want to changes in one of them to be loaded into the other automatically.
Here is a possible solution:
autocmd CursorHold * checktime
function! Timer()
call feedkeys("f\e")
" K_IGNORE keycode does not work after version 7.2.025)
" there are numerous other keysequences that you can use
endfunction
But since checktime will be delayed, the effect may not be satisfactory.
As the quoted documentation explains, you can't, and for good reason (the reload might trigger other autocmds, the change might confuse following commands).
To work around this, you have to leave the current :autocmd, and re-trigger your code somehow. One idea is an :autocmd BufRead, which will fire if the buffer is actually reloaded. If you need to always retrigger, an :autocmd CursorHold (maybe with a temporarily reduced 'updatetime') can be used, or call feedkeys(":call Stage2()\<CR>") might be worth a try.
I ended up doing this:
autocmd CursorHold * call Timer()
function! Timer()
checktime
call feedkeys("f\e")
endfunction
It works quite well.
The 'autowriteall' option makes Vim save all buffers when quitting. I want to be able to use this option only for one specific buffer (a temp file which will be discarded soon) but not for the other buffers.
How do I get Vim to automatically save changes only for one specific buffer?
It's not quite perfect, but one option would be to use the VimLeavePre autocmd:
:autocmd VimLeavePre <buffer> w
However, you'll have to quit with :q! or :qa! for this to work, otherwise it'll never get as far as initiating the autocmd.
:help autocmd
:help VimLeavePre
:help autocmd-buffer-local
You're going to have to use a combination of autocommands. The immediately obvious relevant ones are:
BufHidden
BufLeave
BufUnload
BufDelete
This will cover hiding buffers, leaving them for other buffers or windows, closing Vim, and deleting buffers. (I think BufDelete is redundant given BufUnload but I'm not totally sure I've considered all cases). Note that VimLeavePre will only work if the buffer you're trying to save is the active one, so it's not what you want.
The template autocommand is going to be
:autocommand {event} {filename} w
Or, if you don't have an easy filename pattern to match or it might not have one at all (in which case the w command will need a filename argument) you can use buffer-local autocommands. These would probably have to be set somehow when creating the buffer, like if it's one spawned by some script to show some certain information. For information on this, see:
:help autocmd-buffer-local
You can get information about the multitude of autocommand events from
:help autocommand-events
maybe what you want is:
setlocal autowriteall
setlocal only enables a function for the specified buffer.
autowriteall is autowrite + save on quit, enew, e and others (h autowriteall)