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

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

Related

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

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.

How to automatically run a command after saving a file

I want vim to run g++ after saving a .cpp file to compile it. How can I achieve this? I know how to map an external command to keys, but I want to know how to map a command to another command.
You use :autocmd for that. After a :write, the BufWritePost event is fired. See :h autocmd-events for what's available.
:autocmd BufWritePost <buffer> !g++ %
The % represents the current file (that is written).
A better alternative might be to invoke :make instead; this can also handle more than single file compiles.
To install that for all C++ files, you could just replace <buffer> with *.cpp, but then you're duplication the filetype detection built into Vim. Better put the above :autocmd into e.g. ~/.vim/ftplugin/cpp_autocompile.vim. (This requires that you have :filetype plugin on. Alternatively, you could define an :autocmd FileType cpp autocmd BufWritePost... directly in your ~/.vimrc, but this tends to become unwieldy once you have many customizations.
I wouldn't do that. Most of the time we save files that are not fully compilable (because we want to update tags database, make sure the file is saved before going home). Moreover most of the projects are not made of single files.
But anyway. You are looking for BufWritePost autocommands. For instance,
aug AutoCompileCppFiles
au!
au BufWritePost *.cpp,*.c make
aug END
BTW, :make shall do the work as it'll call gnumake on most systems, and gnumake already knows how to compile single isolated files. If you want to parametrize the compilation, just set $LDFLAGS and $CXXFLAGS ; e.g.:
:let $CXXFLAGS='-std=c++0x -Wall -pedantic'

Possible to access the NERDTree buffer in vimscript?

I'm working on a plugin for NERDTree that I asked about here.
I've got a proof of concept plugin working up on Github and a pull request in to NERDTree with the hooks I need to edit the display strings.
The next thing I'd like to get working is refreshing the NERDTree buffer whenever a file is saved. I was thinking that the NERDTree api function "NERDTreeRender()" would be all I needed - something like:
autocmd BufWrite * call NERDTreeRender()
would work, but it called NERDTreeRender() on the buffer that was written, instead of the NERDTree one. Is there any way to have an autocmd run on bufwrite to that specific buffer? Running :buffers in vim doesn't give me any indication that NERDTree has a numbered buffer unfortunately.
Barring firing the autocmd on write to that specific buffer, does anyone have any other suggested ways to go about this?
You can switch to the NERDTree buffer by setting switchbuf to useopen and calling sbuf NERD*
Something like:
autocmd BufWrite * call DoRender()
function! DoRender()
set switchbuf+=useopen
sbuf NERD*
call NERDTreeRender()
endfunction

Vim 'autowriteall' option only for specific buffers

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)

How to perform File Extension based Actions in VIM?

I want to perform rubyf action in VIM when I press F5 if the file is of .rb extension.
Right now I just have
map <F5> :rubyf % <CR>.
But I also want to interpret scheme files if its .scm or compile tex etc using the same F5. How do I check the file extension and perform the correct binding? How do you guys compile different files in G/VIM?
You could create a different autocmd for each file extension. eg:
au BufEnter,BufNew *.rb map <F5> :rubyf % <CR>.
See :help autocmd for info about autocmds.
A better approach for your specific problem would be to map <F5> to always invoke :make % and then have a autocmd that set the makeprg option for each file type (use setlocal when you do this for best results). This wouldn't be for loading ruby into Vim (as you seem to be doing) but instead for invoking an external compiler/interpreter/linter. This is essentially what I do. The nice thing about doing it this way is that Vim can interpret the errors and warnings and automatically jump to the problems in your code. You can also bring up a list of the errors/warnings. See :help quickfix for info about this, as well as the help topics for 'makeprg', :make, :copen and 'errorformat'.
A slight variation on this would be to not use autocmds at all, but instead to have an external script that when given a source filename figures out what to run (ruby, your scheme compiler, pychecker, your C compiler, whatever). Then just set makeprg to always run that script.
Use filetype plugins.
Create a file ~/.vim/ftplugin/ruby/custom.vim
In that file, put any commands you want included only when the filetype of the current buffer is ruby. They'll be sourced appropriately.
If you want to do the same thing from scheme, create another file ~/.vim/ftplugin/scheme/custom.vim`` and do the same thing.
Each time you load a file in vim, it will detect the filetype, and load all the plugins corresponding to your filetype.
Autocommands is your friend.
it is defined as followed:
:au[tocmd] [group] {event} {pat} [nested] {cmd}
in your case the following line in .vimrc will do what you want.
autocmd BufRead,BufNewFile *.rb map <F5> :rubyf % <CR>.
for more information se:
http://www.ph.unimelb.edu.au/~ssk/vim/autocmd.html
This is answered fairly well in the answers for this question.

Resources