Can I create an autocommand to be launched when I execute :update? - vim

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.

Related

Close all NERDtree instances on VIM exit

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.

autocmd event to execute a command on :wq - vimscript?

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

vim function only works properly the first time

I wrote a function in vim to insert text in "paste"-mode. If I leave the insert mode, the script also leaves the paste mode (set nopaste). Therefore I used the autocommand InsertLeave.
The Problem is, that the "set paste" command works only the first time I call the function. If I want to call it once more I have to restart vim.
This is the vim function:
function Paste_from_clipboard()
execute "normal! :set paste\<CR>\<Esc>o"
execute "startinsert"
autocmd InsertLeave * execute "normal! :set nopaste\<CR>"
endfunction
map <Leader>p :call Paste_from_clipboard()<CR>
What did I do wrong?
I think you are misunderstanding how VimScript works. Every line (be it
on .vimrc, a plugin, a syntax file) is just an ex command, where the
starting : is not needed. So when you write this:
execute "normal! :set paste\<CR>\<Esc>o"
You're basically calling a ex command (:exec) which calls another ex
command (:normal) which then simulates normal mode to what? To call
yet another ex command (:set) and using key codes to execute it. Why?
You can just use the final ex command directly:
set paste
This is also happening in your auto command. Also, it is important to
notice that you're recreating an auto command every time you call your
function. A simple fix is then to remove your extra commands and move
the auto command outside the function, so it is created only once. The
execution will then happen every time the event is triggered (without
another event listener being created over and over.
function Paste_from_clipboard()
set paste
startinsert
endfunction
autocmd InsertLeave * set nopaste
map <Leader>p :call Paste_from_clipboard()<CR>
Check the :h pt for the pastetoggle option. It might be an
alternative to what you are doing.

Use checktime with autocmd without delay in vim

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.

Error in Vim with autocmd: No matching autocommands

I'm using the Vim plugin clang_complete and I want to update the compilation errors in the QuickFix window whenever I save the file. So as the doc says, I must call the function g:ClangUpdateQuickFix().
The thing is that the next autocmd gives me the next message whenever it is executed despite it seems to work:
No matching autocommands
The autocmd I use is:
autocmd BufWritePost *.c,*.cpp,*.cxx,*.cc call g:ClangUpdateQuickFix()
What is the meaning of that message?
The displayed message come from clang_complete itself. Some vim plugins (not clang_complete) are reparsing the quickfix window whenever it changes. Fortunately, vim provide an autocmd for that: QuickFixCmdPost, so these plugins are using this to reparse the quickfix messages.
In clang_complete, since we're modifiying the quickfix window and we don't want to break existing plugins, we need to trigger this autocmd manually. What you get is the No matching autocommands message when you don't use those plugins.

Resources