From d789e8e59d42d99a7c424961fc447e509d503aff Mon Sep 17 00:00:00 2001 From: Ingo Karkat Date: Thu, 28 Mar 2013 10:53:02 +0100 Subject: ENH: Avoid tag updating when ctags output has identical fingerprint. We can avoid the lengthy and blocking update of the tags database when the ctags output returns the same information as before; i.e. nothing tag-relevant has been changed since the last update. Since 7.3.816, Vim has a sha256() function that allows us to quickly calculate a fingerprint over the ctags output. When that is not available, only handle the special case of a (covered) file that has no tags at all (as calculating a hash in Vimscript is costly and would probably defeat the intended speedup). --- autoload/xolox/easytags.vim | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/autoload/xolox/easytags.vim b/autoload/xolox/easytags.vim index 2088f48..0d6e857 100644 --- a/autoload/xolox/easytags.vim +++ b/autoload/xolox/easytags.vim @@ -99,8 +99,11 @@ function! xolox#easytags#update(silent, filter_tags, filenames) " {{{2 let tagsfile = xolox#easytags#get_tagsfile() let firstrun = !filereadable(tagsfile) let cmdline = s:prep_cmdline(cfile, tagsfile, firstrun, a:filenames, context) - let output = s:run_ctags(starttime, cfile, tagsfile, firstrun, cmdline) + let [output, has_updates] = s:run_ctags(starttime, cfile, tagsfile, firstrun, cmdline) if !firstrun + if !has_updates + return 1 + endif if have_args && !empty(g:easytags_by_filetype) " TODO Get the headers from somewhere?! call s:save_by_filetype(a:filter_tags, [], output, context) @@ -201,12 +204,41 @@ function! s:prep_cmdline(cfile, tagsfile, firstrun, arguments, context) " {{{3 return have_args ? join(cmdline) : '' endfunction +if exists('*sha256') +function! s:get_fingerprint(cfile, output) + return sha256(a:output) +endfunction +else +function! s:get_fingerprint(cfile, output) + " Don't want to re-implement a costly hashing function in Vimscript. Just + " handle files that never had any tags. + if empty(a:output) + return get(s:fingerprints, a:cfile, 1) + else + return '' + endif +endfunction +endif + +let s:fingerprints = {} +function! s:has_updates(cfile, output) + let fingerprint = s:get_fingerprint(a:cfile, a:output) + if ! empty(fingerprint) && get(s:fingerprints, a:cfile, '') ==# fingerprint + return 0 + endif + + let s:fingerprints[a:cfile] = fingerprint + return 1 +endfunction + function! s:run_ctags(starttime, cfile, tagsfile, firstrun, cmdline) " {{{3 let lines = [] + let has_updates = 1 if a:cmdline != '' call xolox#misc#msg#debug("easytags.vim %s: Executing %s.", g:xolox#easytags#version, a:cmdline) try let lines = xolox#shell#execute(a:cmdline, 1) + let has_updates = a:firstrun || s:has_updates(a:cfile, join(lines, "\n")) catch /^Vim\%((\a\+)\)\=:E117/ " Ignore missing shell.vim plug-in. let output = system(a:cmdline) @@ -215,6 +247,7 @@ function! s:run_ctags(starttime, cfile, tagsfile, firstrun, cmdline) " {{{3 throw printf(msg, fnamemodify(a:tagsfile, ':~'), strtrans(output)) endif let lines = split(output, "\n") + let has_updates = a:firstrun || s:has_updates(a:cfile, output) endtry if a:firstrun if a:cfile != '' @@ -225,7 +258,7 @@ function! s:run_ctags(starttime, cfile, tagsfile, firstrun, cmdline) " {{{3 return [] endif endif - return xolox#easytags#parse_entries(lines) + return [xolox#easytags#parse_entries(lines), has_updates] endfunction function! s:filter_merge_tags(filter_tags, tagsfile, output, context) " {{{3 -- cgit v1.2.3 From 92d1f2de0ff4d5e51f450f5fcca5fbecc09b67d6 Mon Sep 17 00:00:00 2001 From: Ingo Karkat Date: Wed, 17 Apr 2013 14:43:25 +0200 Subject: BUG: Avoid E713 when attempting fingerprinting without current file. When creating a tags file for an entire directory, the a:cfile variable is empty. In that case, the cache doesn't work. Avoid "E713: Cannot use empty key for Dictionary" by checking for that. --- autoload/xolox/easytags.vim | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/autoload/xolox/easytags.vim b/autoload/xolox/easytags.vim index 0d6e857..4bbe379 100644 --- a/autoload/xolox/easytags.vim +++ b/autoload/xolox/easytags.vim @@ -222,6 +222,11 @@ endif let s:fingerprints = {} function! s:has_updates(cfile, output) + if empty(a:cfile) + " The cache doesn't work when tags aren't created for the current file. + return 1 + endif + let fingerprint = s:get_fingerprint(a:cfile, a:output) if ! empty(fingerprint) && get(s:fingerprints, a:cfile, '') ==# fingerprint return 0 -- cgit v1.2.3