diff --git a/vimrc b/vimrc index c892fd2..5f2d290 100644 --- a/vimrc +++ b/vimrc @@ -385,65 +385,16 @@ augroup campoCmds autocmd BufReadPre *.asm let g:asmsyntax = "fasm" " Auto reload VIM when settings changed. + " Need to use silent! now because the save commands call a custom function + " and without the silent we would see an error after sourcing saying that + " we can't redefine the function that initiated the save. :ReloadVimrcError + " " @fixme Reload lvimrc after sourcing this file on a save. I tried calling " a function that does the source and a call to lvimrc's API but got an " error complaining that the function cannot be created while it's in use. - autocmd BufWritePost .vimrc source $MYVIMRC - autocmd BufWritePost *.vim source $MYVIMRC - autocmd BufWritePost ~/.vimrc.private source $MYVIMRC - - function! s:CreateCtags() - " Only allow one instance of ctags to run in this directory at any given time. - let l:lock_file = "ctags.lock" - if filereadable(l:lock_file) || filereadable("newtags") - " Don't print a warning because this will always show when saving multiple files at the same time with a :wa or :xa - return - endif - - let l:extension = tolower(expand('%:e')) - if (g:campo_force_ctags_regardless_of_extension == 0) && (index(g:campo_extensions_that_run_ctags, l:extension) < 0) - echo "Skipping ctags generation" - return - endif - - " Abort if we're editing a text file. This won't be an exhaustive - " filter. We can restrict what goes into the tag file - " First determine if we're in a root drive directory. If we are then - " we bail because we don't want to recurse across the entire drive! - let l:path = expand('%:p:h') - let l:path_without_slashes = substitute(l:path, "/", "", "g") - if (strchars(l:path) - strchars(l:path_without_slashes)) <= 1 - call PrintError("Not going to run ctags because the file is in a root drive directory") - return - endif - - " Always ignore .git and node_modules - let g:campo_ctags_exclude = g:campo_ctags_exclude + ['.git', 'node_modules'] - let l:exclude_list = "" - for name in g:campo_ctags_exclude - let l:exclude_list = l:exclude_list . "--exclude=" . name . " " - endfor - - " Include local variables for C-like languages. - let l:ctags_cmd = 'ctags '.l:exclude_list.' '.g:campo_custom_ctags_args.' --c-types=+l --c++-types=+l -o newtags' - - " Add the filename to the ctags command if not running in recursive mode. - let l:recursive = matchstr(g:campo_custom_ctags_args, '\(-R\s\)\|\(-R$\)\|\(--recurse=yes\)\|\(--recurse\s\)\|\(--recurse$\)') - if l:recursive == '' - let l:ctags_cmd = l:ctags_cmd . ' ' . expand('%:t') - echo "Creating non-recursive ctags" - else - echo "Creating recursive ctags" - endif - - " The ampersand at the end is to make this run in the background. I had to group the - " commands in parens to make the chained commands run in the background. - let l:cmd = '!(touch '.l:lock_file.'; '.l:ctags_cmd.'; mv newtags tags &>/dev/null; rm '.l:lock_file.') &' - silent! exec l:cmd - endfun - - " Generate ctags on save. - autocmd BufWritePost * call s:CreateCtags() + autocmd BufWritePost .vimrc silent! source $MYVIMRC + autocmd BufWritePost *.vim silent! source $MYVIMRC + autocmd BufWritePost ~/.vimrc.private silent! source $MYVIMRC " Remove trailing whitespace when saving any file. function! s:StripTrailingWhitespaces() @@ -603,6 +554,10 @@ augroup END """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " MISC KEY MAPS """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +" Lowercase the e (have a habit of making it uppercase). +:ca E e + " Mapping ESC in insert mode and command mode to double i. imap jj @@ -619,27 +574,107 @@ nnoremap rv :source $MYVIMRC " the full %/ quickly otherwise it won't replace it. cmap %/ %:p:h/ +"------------------------------------------------------------ " Remap saving and quiting. -nnoremap w :w! +" +" I used to have a BufWritePost autocommand that ran the ctags generator but +" it ends up running multiple times when saving multiple buffers at once. In +" order to only call it once for a group of saves I've had to remap the +" various save commands to a function call. + +function! s:CreateCtags() + " Only allow one instance of ctags to run in this directory at any given time. + let l:lock_file = "ctags.lock" + if filereadable(l:lock_file) || filereadable("newtags") + " Don't print a warning because this will always show when saving multiple files at the same time with a :wa or :xa + return + endif + + let l:extension = tolower(expand('%:e')) + if (g:campo_force_ctags_regardless_of_extension == 0) && (index(g:campo_extensions_that_run_ctags, l:extension) < 0) + echo "Skipping ctags generation" + return + endif + + " Abort if we're editing a text file. This won't be an exhaustive + " filter. We can restrict what goes into the tag file + " First determine if we're in a root drive directory. If we are then + " we bail because we don't want to recurse across the entire drive! + let l:path = expand('%:p:h') + let l:path_without_slashes = substitute(l:path, "/", "", "g") + if (strchars(l:path) - strchars(l:path_without_slashes)) <= 1 + call PrintError("Not going to run ctags because the file is in a root drive directory") + return + endif + + " Always ignore .git and node_modules + let g:campo_ctags_exclude = g:campo_ctags_exclude + ['.git', 'node_modules'] + let l:exclude_list = "" + for name in g:campo_ctags_exclude + let l:exclude_list = l:exclude_list . "--exclude=" . name . " " + endfor + + " Include local variables for C-like languages. + let l:ctags_cmd = 'ctags '.l:exclude_list.' '.g:campo_custom_ctags_args.' --c-types=+l --c++-types=+l -o newtags' + + " Add the filename to the ctags command if not running in recursive mode. + let l:recursive = matchstr(g:campo_custom_ctags_args, '\(-R\s\)\|\(-R$\)\|\(--recurse=yes\)\|\(--recurse\s\)\|\(--recurse$\)') + if l:recursive == '' + let l:ctags_cmd = l:ctags_cmd . ' ' . expand('%:t') + echo "Creating non-recursive ctags" + else + echo "Creating recursive ctags" + endif + + " The ampersand at the end is to make this run in the background. I had to group the + " commands in parens to make the chained commands run in the background. + let l:cmd = '!(touch '.l:lock_file.'; '.l:ctags_cmd.'; mv newtags tags &>/dev/null; rm '.l:lock_file.') &' + silent! exec l:cmd +endfun + +" @note We have an autocmd that reloads the vimrc files after they're saved. +" These write functions below will not be reloaded because they initiate the +" save. So if you make changes to them then you need to manually reload this +" file using rv or whatever. :ReloadVimrcError +function! DoSingleWrite() + write + call s:CreateCtags() +endfunction + +function! DoSingleWriteThenQuit() + write + call s:CreateCtags() + quit +endfunction + +function! DoMultiWrite() + let l:current_buffer = bufnr("%") + bufdo wa + " Restore the last buffer because it may have changed. + exec "buffer " . l:current_buffer + call s:CreateCtags() +endfunction + +cnoreabbrev w :call DoSingleWrite() +cnoreabbrev W :call DoSingleWrite() +cnoreabbrev wa :call DoMultiWrite() +cnoreabbrev Wa :call DoMultiWrite() +cnoreabbrev WA :call DoMultiWrite() +cnoreabbrev wq :call DoSingleWriteThenQuit() +cnoreabbrev Wq :call DoSingleWriteThenQuit() +cnoreabbrev WQ :call DoSingleWriteThenQuit() + +nnoremap w :call DoSingleWrite() +nnoremap x :call DoSingleWriteThenQuit() nnoremap q :q -nnoremap qq :q! -nnoremap x :x -:ca Wa wa! -:ca WA wa! -:ca WQ wq -:ca Wq wq -:ca W w! -:ca Q q -" Lowercase the e (have a habit of making it uppercase). -:ca E e - -command! Q q " Bind :Q to :q -command! Qall qall +cnoreabbrev Q q command! Qa qall " Disable Ex mode. noremap Q +"------------------------------------------------------------ + " Open a terminal within vim. Use `exit` to close it. if exists(':terminal') noremap t :terminal