From e690a5e97da00bfd3d9a6d757f9016f49d016893 Mon Sep 17 00:00:00 2001 From: Jan Larres Date: Sun, 22 Jul 2012 21:49:17 +1200 Subject: [PATCH] Cache files locally for parsing Files are now cached locally in a temporary file, and the parsing happens on that file. This allows displaying tags for remote (Netrw) files, and it will also make access to files on remote filesystems like NFS and sshfs faster. Additionally, tags are now always updated when the files are saved, deprecating the tagbar_updateonsave_maxlines option. Otherwise checking for changes in remote files would not have been possible. --- autoload/tagbar.vim | 73 +++++++++++++++++++++++++++------------------ doc/tagbar.txt | 12 +------- plugin/tagbar.vim | 4 --- 3 files changed, 45 insertions(+), 44 deletions(-) diff --git a/autoload/tagbar.vim b/autoload/tagbar.vim index 6d73d47..52b9210 100644 --- a/autoload/tagbar.vim +++ b/autoload/tagbar.vim @@ -890,7 +890,7 @@ function! s:RestoreSession() abort call s:InitWindow(g:tagbar_autoclose) - call s:AutoUpdate(curfile) + call s:AutoUpdate(curfile, 0) if !in_tagbar call s:winexec('wincmd p') @@ -951,12 +951,10 @@ function! s:CreateAutocommands() abort autocmd BufEnter __Tagbar__ nested call s:QuitIfOnlyWindow() autocmd CursorHold __Tagbar__ call s:ShowPrototype() - autocmd BufWritePost * - \ if line('$') < g:tagbar_updateonsave_maxlines | - \ call s:AutoUpdate(fnamemodify(expand(''), ':p')) | - \ endif + autocmd BufWritePost * call + \ s:AutoUpdate(fnamemodify(expand(''), ':p'), 1) autocmd BufEnter,CursorHold,FileType * call - \ s:AutoUpdate(fnamemodify(expand(''), ':p')) + \ s:AutoUpdate(fnamemodify(expand(''), ':p'), 0) autocmd BufDelete,BufUnload,BufWipeout * call \ s:known_files.rm(fnamemodify(expand(''), ':p')) @@ -1431,6 +1429,8 @@ function! s:FileInfo.New(fname, ftype) abort dict " The complete file path let newobj.fpath = a:fname + let newobj.bufnr = bufnr(a:fname) + " File modification time let newobj.mtime = getftime(a:fname) @@ -1629,7 +1629,7 @@ function! s:OpenWindow(flags) abort call s:InitWindow(autoclose) - call s:AutoUpdate(curfile) + call s:AutoUpdate(curfile, 0) call s:HighlightTag(1, curline) if !(g:tagbar_autoclose || autofocus || g:tagbar_autofocus) @@ -1809,22 +1809,6 @@ function! s:ProcessFile(fname, ftype) abort return endif - let ctags_output = s:ExecuteCtagsOnFile(a:fname, a:ftype) - - if ctags_output == -1 - call s:LogDebugMessage('Ctags error when processing file') - " put an empty entry into known_files so the error message is only - " shown once - call s:known_files.put({}, a:fname) - return - elseif ctags_output == '' - call s:LogDebugMessage('Ctags output empty') - " No need to go through the tag processing if there are no tags, and - " preserving the old fold state also isn't necessary - call s:known_files.put(s:FileInfo.New(a:fname, a:ftype), a:fname) - return - endif - " If the file has only been updated preserve the fold states, otherwise " create a new entry if s:known_files.has(a:fname) @@ -1834,6 +1818,29 @@ function! s:ProcessFile(fname, ftype) abort let fileinfo = s:FileInfo.New(a:fname, a:ftype) endif + let tempfile = tempname() + + call writefile(getbufline(fileinfo.bufnr, 1, '$'), tempfile) + let fileinfo.mtime = getftime(tempfile) + + let ctags_output = s:ExecuteCtagsOnFile(tempfile, a:ftype) + + call delete(tempfile) + + if ctags_output == -1 + call s:LogDebugMessage('Ctags error when processing file') + " Put an empty entry into known_files so the error message is only + " shown once + call s:known_files.put({}, a:fname) + return + elseif ctags_output == '' + call s:LogDebugMessage('Ctags output empty') + " No need to go through the tag processing if there are no tags, and + " preserving the old fold state isn't necessary either + call s:known_files.put(s:FileInfo.New(a:fname, a:ftype), a:fname) + return + endif + let typeinfo = fileinfo.typeinfo " Parse the ctags output lines @@ -2948,7 +2955,7 @@ endfunction " Helper functions {{{1 " s:AutoUpdate() {{{2 -function! s:AutoUpdate(fname) abort +function! s:AutoUpdate(fname, force) abort call s:LogDebugMessage('AutoUpdate called on ' . a:fname) " Get the filetype of the file we're about to process @@ -2974,14 +2981,22 @@ function! s:AutoUpdate(fname) abort let updated = 0 - " Process the file if it's unknown or the information is outdated + " Process the file if it's unknown or the information is outdated. " Also test for entries that exist but are empty, which will be the case - " if there was an error during the ctags execution + " if there was an error during the ctags execution. + " Testing the mtime of the file is necessary in case it got changed + " outside of Vim, for example by checking out a different version from a + " VCS. if s:known_files.has(a:fname) && !empty(s:known_files.get(a:fname)) - if s:known_files.get(a:fname).mtime != getftime(a:fname) + let curfile = s:known_files.get(a:fname) + " if a:force || getbufvar(curfile.bufnr, '&modified') || + if a:force || + \ (filereadable(a:fname) && getftime(a:fname) > curfile.mtime) call s:LogDebugMessage('File data outdated, updating ' . a:fname) call s:ProcessFile(a:fname, sftype) let updated = 1 + else + call s:LogDebugMessage('File data seems up to date: ' . a:fname) endif elseif !s:known_files.has(a:fname) call s:LogDebugMessage('New file, processing ' . a:fname) @@ -3006,7 +3021,7 @@ function! s:AutoUpdate(fname) abort endif " Call setCurrent after rendering so RenderContent can check whether the - " same file is redisplayed + " same file is being redisplayed if !empty(fileinfo) call s:LogDebugMessage('Setting current file to ' . a:fname) call s:known_files.setCurrent(fileinfo) @@ -3219,7 +3234,7 @@ function! s:IsValidFile(fname, ftype) abort return 0 endif - if !filereadable(a:fname) + if !filereadable(a:fname) && getbufvar(a:fname, 'netrw_tmpfile') == '' call s:LogDebugMessage('File not readable') return 0 endif diff --git a/doc/tagbar.txt b/doc/tagbar.txt index 26fb2bf..0531650 100644 --- a/doc/tagbar.txt +++ b/doc/tagbar.txt @@ -473,19 +473,9 @@ Example: *g:tagbar_updateonsave_maxlines* g:tagbar_updateonsave_maxlines~ -Default: 5000 -If the current file has fewer lines than the value of this variable, Tagbar -will update immediately after saving the file. If it is longer then the update -will only happen on the |CursorHold| event and when switching buffers (or -windows). This is to prevent the time it takes to save a large file from -becoming annoying in case you have a slow computer. If you have a fast -computer you can set it to a higher value. +Deprecated. Tagbar will now always get updated when the file is being saved. -Example: -> - let g:tagbar_updateonsave_maxlines = 10000 -< *g:tagbar_systemenc* g:tagbar_systemenc~ diff --git a/plugin/tagbar.vim b/plugin/tagbar.vim index cc2fa8a..4d20f16 100644 --- a/plugin/tagbar.vim +++ b/plugin/tagbar.vim @@ -91,10 +91,6 @@ if !exists('g:tagbar_autoshowtag') let g:tagbar_autoshowtag = 0 endif -if !exists('g:tagbar_updateonsave_maxlines') - let g:tagbar_updateonsave_maxlines = 5000 -endif - if !exists('g:tagbar_systemenc') let g:tagbar_systemenc = &encoding endif