when I use this script in my .vimrc:
"Save and restore folds when a file is closed and re-opened
autocmd BufWinEnter ?* if(!empty(glob(expand("%:p")))) | silent loadview | endif
autocmd BufWritePost,BufLeave,WinLeave ?* if(!empty(glob(expand("%:p")))) | mkview | endif
It creates errors when I open the command line window via q: (which opens up all the previous commands that I typed):
How can I fix that, and make sure that this error does not occur?
Certain commands are not allowed in the command-line-window; :help E11 explains that.
To deal with this in your :autocmd, there are several options:
suppress any error by prepending :silent! to the :mkview command
surrounding the call with :try ... catch /^E11:/ to just selectively ignore this error, but report anything else
add a check for the command-line window in your :if condition; in recent Vim versions, you can use getcmdwintype(); it returns an empty String in other windows; for a check that also works with older Vim versions, see ingo#compat#window#IsCmdlineWindow() in my ingo-library plugin
Related
I would like to always open a vertical split with Explore whenever I open a file in vim. So I added the following list to my init.vim
topleft vsplit | :vertical resize 30 | :Ex
however I get the following error message.
Not an editor command: :Ex
however I get the following error message.
So the command is invalid. :Ex is provided by a plugin (usually netrw). The message means that netrw is not loaded (yet).
I added the following list to my init.vim
Please, take your time reading :h startup. To put it short, vimrc (or init.vim) is processed long before any plugin is loaded. You really should delay your command until VimEnter event. Kind of
if v:vim_did_enter
DoSomethingIfSourcedManually
else
autocmd VimEnter * ++once ++nested DoSomethingOnStartup
endif
mkview and loadview are fantastic ways to save state in vim, and many people use .vimrc commands such as this to automatically save state on all files.
au BufWinLeave ?* mkview
au BufWinEnter ?* silent loadview
This creates the state files (in a location such as ~/.vim/view)
Sometimes, though, you want to clear the view information so the file starts in a fresh state.
The only ways I can see doing this are:
Find and remove the corresponding .vim/view/ file from the command-line
Temporarily edit your .vimrc to turn off the loadview, open the file, and restore the .vimrc
Those are both cumbersome and involve doing things outside of vim. Isn't there some way to either:
Open a file without doing loadview (or perhaps a way to pass an option to the vimrc to skip the loadview?) so when we close we will have a clear mkview
Remove/clear any state set by loadview or else erase the corresponding loadview file for a given file from inside vim
I suppose you could write a shell script that took the file path and tried to figure out vim's '=+' encoding of paths in the .vim/view directory and remove that and then call the shell script from inside vim, but it seems like vim should have some sort of support for this.
User #pkeu pointed out that if you have automatic view creations then you need to turn these off if you are currently viewing the file that you want to delete the view for, otherwise when you exit it will just create it again, you can ensure this by changing your mkview autocommands from:
au BufWinLeave ?* mkview
au BufWinEnter ?* silent loadview
to be bundled in a group called "keepview" - which makes them easy to turn off:
:augroup keepview
: autocmd BufWinLeave ?* mkview
: autocmd BufWinEnter ?* silent loadview
:autogroup END
Then they can they be turned off by adding this line before the endfunction:
:autocmd! keepview
The only problem with this approach is that MyDeleteView isn't smart enough to check whether you are currently viewing the file you are deleting or not, and if not, then you won't save a view of the current file. The other option is to not add this at all, and just delete views of files that aren't currently open. Or write a smarter MyDeleteView() that checks if you're currently in the file.
It looks like vim doesn't have this ability, so I needed to write a vimscript that does the proper quoting (thanks to inspiration and the note about '&viewdir' from Ingo).
Here is the vimscript, you can add this to your .vimrc to add the command to vim:
" # Function to permanently delete views created by 'mkview'
function! MyDeleteView()
let path = fnamemodify(bufname('%'),':p')
" vim's odd =~ escaping for /
let path = substitute(path, '=', '==', 'g')
if empty($HOME)
else
let path = substitute(path, '^'.$HOME, '\~', '')
endif
let path = substitute(path, '/', '=+', 'g') . '='
" view directory
let path = &viewdir.'/'.path
call delete(path)
echo "Deleted: ".path
endfunction
" # Command Delview (and it's abbreviation 'delview')
command Delview call MyDeleteView()
" Lower-case user commands: http://vim.wikia.com/wiki/Replace_a_builtin_command_using_cabbrev
cabbrev delview <c-r>=(getcmdtype()==':' && getcmdpos()==1 ? 'Delview' : 'delview')<CR>
After adding this, you can simply do:
:delview
From the commandline and it will delete the view created for the current buffer/file
Your $HOME environment variable must be set to whatever vim thinks '~' is
As the automatic view handling is triggered by :autocmd, you can temporarily disable the loading of the view via
:noautocmd edit myfile
Note that this also turns off any hooks done by other plugins / customizations.
To delete a file from within Vim, you can use delete() to define a custom command:
:command! -nargs=1 DeleteView call delete(&viewdir . '/' . <q-args>)
This could be further improved by building globbing or even Vim's filespec escaping into it.
I'm using vim 7.3 and Rainbow Parentheses plugin. When opening multiple tabs with vim -p file1 file2 or with vim -S session.vim, or even with tabnew file or any other method, my parenthesis are colored in only one file.
I just put this into my .vimrc : au VimEnter * RainbowParenthesesToggle
as said here. I tried to use :RainbowParenthesesToggle on the other tabs once opened but it only toggles in the parenthesis-activated tab.
What should I do to make things work in all tabs ?
I made it work by adding the same instructions as here in my .vimrc, thanks to FDinoff. I replaced the last instruction to make it work using tab, as I intended first.
function! Config_Rainbow()
call rainbow_parentheses#load(0)
call rainbow_parentheses#load(1)
call rainbow_parentheses#load(2)
endfunction
function! Load_Rainbow()
call rainbow_parentheses#activate()
endfunction
augroup TastetheRainbow
autocmd!
autocmd Syntax * call Config_Rainbow()
autocmd VimEnter,BufRead,BufWinEnter,BufNewFile * call Load_Rainbow()
augroup END
The VimEnter flag on the autocommand tells vim to perform the command specified (in this case RainbowParenthesesToggle only when starting the editor, which is in your case when you open the first file.
If you want to extend the functionality to everytime you load a buffer you should do something like:
autocmd BufRead,BufNewFile * RainbowParenthesesToggle
According to the answer of this question, the :bd command should not quit Vim (gVim) when it is the last buffer remaining. Unfortunately, it does close gVim in my case. Did I understand something wrong about :bd?
I am also using a preconfigured vimrc file. Maybe a setting in there has that side affect, but I couldn’t find it.
Try doing the following:
:set eventignore=all | bd | set eventignore=
If this won't quit vim then you have some plugin that defines an autocommand that quits vim when no more buffers are present in the list, so after that try doing
verbose autocmd BufWinLeave,BufLeave,BufDelete,BufUnload,BufWipeout
This will show you all autocommands attached to given events (these are events that are executed when buffer is deleted) and where they were defined. Note that I do not have any autocommands attached to these events that are defined by plugins in standart vim distribution.
Update: I do not see anything bad in your output. You may also try
verbose autocmd BufNew,BufAdd,BufCreate,BufEnter,BufWinEnter
(because when you leave last buffer new empty one is created). If this does not show anything suspicious, start ignoring event types: if you are on linux try the following script:
for event in BufWinLeave BufLeave BufDelete BufUnload BufWipeout BufNew BufAdd BufCreate BufEnter BufWinEnter
do
event=$event vim file -c "set eventignore=$event | bd"
done
This script should iterate until you find event name that causes trouble. After this you can use execute "verbose autocmd" $event in vim to narrow number of plugins that should be checked. After you got list of autocmd groups (augroup names are shown just before event name in your output: railsPluginDetect is one of such groups), delete events in them (augroup {GroupName} | execute 'autocmd!' | augroup END) and find out which plugin to claim.
Alternatively, you can use debugger:
debug bd
, then s<CR>n<CR><CR><CR>... until vim quits; don't forget to remember what vim have shown above > prompt before quiting.
what I am using now is ,
autocmd BufWritePost *.py !python PythonTidy.py % %
It really call the tidy programe and change the file, but the vim does not reload the new file.
And I do not want to install another plugin for it.
=======================
note: I found it's dangerous about this feature, PythonTidy will will output a empty file if the command faild, it means if you have syntax error, you will lose your file unless press "u" to get it,but you can't save before you fix syntax error.
I call :!PythonTidy % % manually after pylint complete now.
Use BufWritePre instead of BufWritePost and combine Vim range filtering with PythonTidy’s stdin/stdout mode.
autocmd FileType python autocmd BufWritePre <buffer> let s:saveview = winsaveview() | exe '%!python PythonTidy.py' | call winrestview(s:saveview) | unlet s:saveview
(The use of autocmd FileType python autocmd BufWritePre <buffer> makes this a bit more accurate than matching on a glob pattern: it means “any time a Python file is detected, install this autocmd for that buffer” – so it works independently of file name.)
Unfortunately this cannot preserve your cursor position if you undo the filtering. (You are filtering a whole-file range; when undoing a filter operation, the cursor jumps to the first line in the range; so you end up at the top of the file.) I was hoping to find a way to create a no-op undo state, before, so you could hit u twice and get back to the right place, but I can’t make that work as yet. Maybe someone else knows how.
hi the following fixed the cursor postion problem
function! PythonTidySaver()
let oldpos=getpos('.')
%!PythonTidy
call setpos('.',oldpos)
endfunction
autocmd! bufwritepost *.py call PythonTidySaver()
Based on :help :e:
*:e* *:edit*
:e[dit] [++opt] [+cmd] Edit the current file. This is useful to re-edit the
current file, when it has been changed outside of Vim.
This fails when changes have been made to the current
buffer and 'autowriteall' isn't set or the file can't
be written.
Also see |++opt| and |+cmd|.
{Vi: no ++opt}
So you'd need to use :e after updating the file externally. However, :! doesn't let you use | normally (see :help :!), so you need to wrap it:
autocmd BufWritePost *.py execute "!python PythonTidy.py % %" | e
(:autocmd doesn't interpret | normally either, which is why you don't need to escape it yet again.)