From 476a1632362b39d0efed5897eab3bf28f0599391 Mon Sep 17 00:00:00 2001 From: Michael Campagnaro Date: Fri, 3 Dec 2021 14:52:32 -0500 Subject: [PATCH] Speed up and fix hangs when doing a large search and replace in vim --- vimrc | 64 ++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/vimrc b/vimrc index b526de1..24ce476 100644 --- a/vimrc +++ b/vimrc @@ -131,7 +131,7 @@ let g:campo_extensions_that_run_ctags = ['c','cpp','h','hpp','inc','cs','js','py " Default files and directories that ctags should ignore when doing a " recursive crawl. -" @note The RunCtags function will always ignore .git and node_modules +" @note The CreateCtags function will always ignore .git and node_modules " regardless of this variable's value. let g:campo_ctags_exclude = ['*.txt', '*.config', '.cache'] @@ -281,6 +281,9 @@ set numberwidth=5 set showtabline=2 set winwidth=79 + " Use abbreviations. +set shortmess=a + " Remove gvim Menubar and Toolbar "set guioptions -=m "set guioptions -=T @@ -530,7 +533,7 @@ augroup campoCmds autocmd BufWritePost *.vim source $MYVIMRC autocmd BufWritePost ~/.vimrc.private source $MYVIMRC - function! s:RunCtags() + 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") @@ -581,7 +584,7 @@ augroup campoCmds endfun " Generate ctags on save. - autocmd BufWritePost * call s:RunCtags() + autocmd BufWritePost * call s:CreateCtags() " Remove trailing whitespace when saving any file. function! s:StripTrailingWhitespaces() @@ -979,7 +982,7 @@ function! CenterPane() " Taken from https://dev.to/vinneycavallo/easily-center-content-in-vim lefta vnew wincmd w - exec 'vertical resize '. string(&columns * 0.75) + exec 'vertical resize' string(&columns * 0.75) endfunction nnoremap c :call CenterPane() @@ -1029,7 +1032,7 @@ function! ChangeBgTheme(bg, onlySetTheme) endif if !a:onlySetTheme - exec ':AirlineTheme ' . a:bg + exec 'AirlineTheme' a:bg endif endfunction @@ -1218,27 +1221,18 @@ nnoremap p (&buftype is# "quickfix" ? "\|:copen" : "p") " SEARCH & REPLACE """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" -" argdo wrapper that will disable all events for read/save. This significantly -" speeds up GlobalReplaceIt(). -command! -nargs=? Argdo call Argdo() -function! Argdo(command) - set eventignore=all - exec 'noautocmd argdo '. a:command . ' | update' - set eventignore= -endfunction - -" Replace the selected text in all files within the repo. -function! GlobalReplaceIt(confirm_replacement) +" Replace text in a git repo's committed files. +" The range identifier allows us to run this once when multiple lines are selected in a file. +function! GlobalReplaceIt(confirm_replacement) range if exists(':Ggrep') call inputsave() - if a:confirm_replacement let l:term = input('Enter search term (w/ confirmation): ') else let l:term = input('Enter search term (no confirmation): ') endif - call inputrestore() + if empty(l:term) return endif @@ -1251,14 +1245,34 @@ function! GlobalReplaceIt(confirm_replacement) endif if a:confirm_replacement - let l:confirm_opt = 'c' + let l:confirm = 'c' else - let l:confirm_opt = 'e' + let l:confirm = 'e' endif - exec 'Ggrep '.l:term - exec 'Qargs | Argdo %s/'.l:term.'/'.l:replacement.'/g'.l:confirm_opt - call s:RunCtags() " Regen ctags. + " Capture opened buffers and windows so that we can restore everything after running cdo. + exec 'mksession! _replace_session.vim' + + " Search all committed files in the current directory + " Ignoring binary files (-I) + " Only including a matching filename once (--name-only) + exec 'Ggrep --threads 4 -I --name-only' l:term '.' + + " cdo will run the command foreach file in the grep results. It opens + " the file in a window so we immediately write the changes and then + " wipe the buffer (closing the window). If we don't close it then vim + " will run out of space when modifying a lot of files. This will + " likely close buffers that were open before running the replace, but + " we will restore them below from the saved session file. + " Note that we don't run autocommands for optimization purposes! + :noautocmd exec 'cdo' '%s/'.l:term.'/'.l:replacement.'/g'.l:confirm '| write | bwipe' + + " Restore the session. + if filereadable('_replace_session.vim') + silent! exec 'source _replace_session.vim | !rm _replace_session.vim &>/dev/null' + endif + + call s:CreateCtags() else call PrintError("Unable to search since you're not in a git repo!") endif @@ -1274,8 +1288,8 @@ function! RenameFile() let l:old_name = expand('%') let l:new_name = input('New file name: ', expand('%'), 'file') if l:new_name != '' && l:new_name != l:old_name - exec ':saveas ' . l:new_name - exec ':silent !rm ' . l:old_name + exec 'saveas' l:new_name + exec '!rm' l:old_name redraw! endif endfunction