Vim 'autowriteall' option only for specific buffers - vim

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)

Related

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 auto save current file when focus is lost

How to make vim automatically save only current buffer when focus is lost, not all files as described here http://vim.wikia.com/wiki/Auto_save_files_when_focus_is_lost
Based on your comments I can say that you have wrong question: you want not to “save only current buffer when focus is lost” (focus tends to have a meaning of “currently focused window”), but to “write buffer when switching to another one: when it is no longer in your focus of attention”. To complete this you may use
augroup AutoWrite
autocmd! BufLeave * :update
augroup END
, maybe combined with
set autowrite
and
set autowriteall
(sets of situations where first and second two variants are triggered intersect, but neither is a superset of another one).
Instead of :wa (write all), use :w.
Also you can try this
set updatetime=1000
autocmd CursorHoldI * silent w
just put it in your .vimrc

Vim: Resolve ambiguity of key mappings in a specific buffer to avoid timeout

I use plugin "Buffet", and there's local-to-buffer mapping "d" to delete buffer under cursor.
I also use plugun Surround, and there's global mapping "ds" that means "delete surround".
So, when i press "d" in the Buffet's window, Vim waits for a second before execute mapping "d". I know about &timeoutlen, but i don't want to change it. So that I want to resolve ambiguity of key mappings for "d" in the Buffet's window to avoid timeout to delete a buffer.
To resolve the problem, I want to unmap in Buffet window all the mappings that start with "d", but except Buffet's own mappings. How can i do that?
P.S. I have read about maparg() and mapcheck(), but they seem not to be what i need, unfortunately.
It seems like i found the solution myself:
au BufEnter buflisttempbuffer* nunmap ds
au BufLeave buflisttempbuffer* nmap ds <Plug>Dsurround
I hoped that there's more universal approach (to remove really all mappings starting from "d"), but at this moment i failed to find it.
Even if i found out how to get all these mappings, unfortunately i can't do unmap <buffer> ds, because ds is a global mapping. I'm sure that i should be able to disable global mapping for some buffer, though. Vim is great but not perfect.
Well, it works for me now.
Now that the question has been "rephrased", this solution is no longer relevant, but I'll post it anyway since I spent a few minutes on it.
Here's a function that grabs the output of map <letter> and extracts the individual maps. Then it unmaps them all.
function! Unmap(leader)
redir => maps
sil exe "map " . a:leader
redir END
let maps_list = split(strtrans(maps),'\^#')
if len(maps_list) > 1
for this in maps_list
let mapn = matchstr(this,"^\\w\\s*\\zsd\\w*\\>")
exe "unmap " . mapn
endfor
endif
endfunction
Example usage: call Unmap("d"). This will remove all mappings that begin with d, leaving only Vim's defaults.
Disclaimer: this has not been rigorously tested. In particular I don't know how portable the \^# character is, but that's how it looks on my (Win32) machine.
The easiest way to do it is:
:e /WHERE/YOU/HAD/INSTALLED/buffet.vim
:%s:map <buffer> <silent> d:"&:
:wq
$ vim # Restart Vim to take effect...
Generally you can't unmap based on a pattern.
If you want to use another key (e.g. with <leader>, just change this line in the plugin:
map <buffer> <silent> d :call <sid>deletebuffer(0)<cr>
This question is rather old, but if you're still interested, you might want to give Bufstop a try.
This issue is handled by the plugin, you can press the d key to delete a buffer, and you won't get any timeout if you installed other plugins which have global mappings.
A cheap trick that worked for me was to make the timeoutlen so short it becomes pretty much instantaneous. As long as you don't use multiple key mappings yourself, that will cover all plugins in one shot.
We don't want that setting to stay however, so we remove it every time we leave the buffer.
Add this so that it runs inside your custom buffer:
augroup no_map_chords
autocmd!
autocmd BufEnter <buffer> let g:bak_timeoutlen = &timeoutlen | set timeoutlen=1
autocmd BufLeave <buffer> let &timeoutlen = g:bak_timeoutlen | unlet g:bak_timeoutlen
augroup END
A similar technique could be used for a specific file type, or other such "global" settings.
Buffet is a very young plugin, I don't think it's used by as many people as Command-T or NERDTree so you may not receive lots of answers. Its author has been very responsive on the numerous threads he created there about it you should contact him directly or create an issue on Buffet's github.

How to set the default to unfolded when you open a file?

In my .vimrc I've put set foldmethod=syntax to enable folding of methods etc. However, I don't like the default that everytime I open a file, the whole thing is folded. Is there a way to enable foldmethod, yet have files unfolded when I open them?
set foldlevel=99
should open all folds, regardless of method used for folding. With foldlevel=0 all folded, foldlevel=1 only somes, ... higher numbers will close fewer folds.
You can put this in your .vimrc:
au BufRead * normal zR
It declares an automatic command (au), triggered when a buffer is read (BufRead), matching all files (*) and executes the zR (opens all folds) command in normal mode.
set nofoldenable
Adding this to your .vimrc will temporarily disable folding when you open the file, but folds can still be restored with zc
In .vimrc add an autocmd for BufWinEnter to open all folds automatically like this:
autocmd BufWinEnter * silent! :%foldopen!
That tell vim to execute the silent :%foldopen! after opening BunWinEnter event (see :h BufWinEnter). The silent %foldopen! will execute foldopen on the whole buffer thanks to the % and will open all folds recursively because of the !. Any eventual error message will be suppressed by silent. (You could get error messages like E490: No fold found if the buffer actually didn't contain any fold yet)
Note: You could use BufRead instead of BufWinEnter but then if the file has a modeline that enables the folding that will override this autocmd. I mean BufRead autocmds run before the modeline is processed and BufWinEnter will run them after. I find the later to be more useful
You can add
set foldlevelstart=99
to your .vimrc file, and it will start editing any new file with all folds open.
If you want a way to have it display unfolded as soon as it is opened, you can use set foldlevelstart=99 as a lot of answers explained.
But, if you just want to see them unfolded, you can just press zi and it will unfold everything. Another, zi will close them back.
You could map it to keys to enable it.
For example,
nmap ,f :set foldmethod=syntax<CR>
Then while in normal mode hit the ",f" key combination
You can open unfolded file when you put set nofoldenable into your .vimrc file.
autocmd BufReadPost * silent! :%foldopen!
This worked best for me. After a buffer gets opened all folds are opened. This opens them to the correct level.
The set foldenable method was not good, because if I choose to close one fold level, it enabled folding again, and folded every thing to 0 level, instead of just going down one level on the one I activated.

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