Vim genera automaticamente tag
-
03-07-2019 - |
Domanda
In questo momento ho il seguente nel mio .vimrc
:
au BufWritePost *.c,*.cpp,*.h !ctags -R
Ci sono alcuni problemi con questo:
- È lento: rigenera i tag per i file che non sono stati modificati dall'ultima generazione di tag.
- Devo premere di nuovo il pulsante Invio di nuovo dopo aver scritto il file a causa di un inevitabile "quot", premi Invio o digita il comando per continuare " ;.
Quando combini questi due problemi, finisco per inviare l'ulteriore invio troppo presto (prima che ctags -R
sia terminato), quindi vedo il fastidioso messaggio di errore e devo premere di nuovo Invio.
So che non sembra un grosso problema, ma con la quantità di scritture di file che faccio in un dato giorno, tende a diventare davvero fastidioso. Deve esserci un modo migliore per farlo!
Soluzione
au BufWritePost * .c, *. cpp, *. h silent! ! ctags -R & amp;
Il rovescio della medaglia è che non avrai un utile file tag fino al suo completamento. Finché sei su un sistema * nix dovrebbe essere ok fare più scritture prima che i tag precedenti siano stati completati, ma dovresti testarlo. Su un sistema Windows non lo metterà in background e si lamenterà che il file è bloccato fino al termine dei primi tag (il che non dovrebbe causare problemi in VIM, ma finirai con un file tag leggermente obsoleto ).
Nota, potresti usare l'opzione --append
come suggerisce tonylo, ma poi dovrai disabilitare tagbsearch
il che potrebbe significare che le ricerche di tag impiegano molto più tempo , a seconda della dimensione del file tag.
Altri suggerimenti
Modifica : una soluzione molto simile a quanto segue è stata pubblicata come the AutoTag vim script . Nota che lo script ha bisogno di un vim con supporto Python , tuttavia.
La mia soluzione si esegue invece su awk, quindi dovrebbe funzionare su molti più sistemi.
au FileType {c,cpp} au BufWritePost <buffer> silent ! [ -e tags ] && \ ( awk -F'\t' '$2\!="%:gs/'/'\''/"{print}' tags ; ctags -f- '%:gs/'/'\''/' ) \ | sort -t
viene invocato solo sul file appena salvato e il risultato viene quindiNota che puoi scrivere in questo modo solo in uno script, altrimenti deve andare su una sola riga.
Ci sono molte cose in corso lì dentro:
Questo comando automatico si attiva quando un file è stato rilevato come C o C ++ e aggiunge a sua volta un comando automatico locale buffer che viene attivato dall'evento
BufWritePost
.Utilizza il segnaposto
%
che viene sostituito dal nome file del buffer al momento dell'esecuzione, insieme al modificatore: gs
usato per shell- citare il nome del file (trasformando le virgolette singole incorporate in quote-escape-quote-quote).In questo modo esegue un comando di shell che controlla se esiste un file
tags
, nel qual caso il suo contenuto viene stampato ad eccezione delle righe che si riferiscono al file appena salvato, nel frattempo < code> ctagssort
ed ed è rimesso a posto.Implementatore Caveat: questo presuppone che tutto sia nella stessa directory e che sia anche la directory corrente buffer-local. Non ho pensato a un percorso di demolizione.
\t' -k1,1 -o tags.new && mv tags.new tags
Nota che puoi scrivere in questo modo solo in uno script, altrimenti deve andare su una sola riga.
Ci sono molte cose in corso lì dentro:
-
Questo comando automatico si attiva quando un file è stato rilevato come C o C ++ e aggiunge a sua volta un comando automatico locale buffer che viene attivato dall'evento
BufWritePost
. -
Utilizza il segnaposto
%
che viene sostituito dal nome file del buffer al momento dell'esecuzione, insieme al modificatore: gs
usato per shell- citare il nome del file (trasformando le virgolette singole incorporate in quote-escape-quote-quote). -
In questo modo esegue un comando di shell che controlla se esiste un file
tags
, nel qual caso il suo contenuto viene stampato ad eccezione delle righe che si riferiscono al file appena salvato, nel frattempo < code> ctags viene invocato solo sul file appena salvato e il risultato viene quindisort
ed ed è rimesso a posto.
Implementatore Caveat: questo presuppone che tutto sia nella stessa directory e che sia anche la directory corrente buffer-local. Non ho pensato a un percorso di demolizione.
Ho scritto easytags.vim per fare proprio questo: aggiorna automaticamente ed evidenziare i tag. Il plug-in può essere configurato per aggiornare solo il file in fase di modifica o tutti i file nella directory del file in fase di modifica (ricorsivamente). Può utilizzare un file di tag globale, file di tag specifici per tipo di file e file di tag specifici del progetto.
Ho notato che questo è un vecchio thread, tuttavia ... Usa incron in * nix come ambienti che supportano inotify. Avvierà sempre i comandi ogni volta che cambiano i file in una directory. cioè.,
/home/me/Code/c/that_program IN_DELETE,IN_CLOSE_WRITE ctags --sort=yes *.c
Questo è tutto.
Forse usa l'argomento append per ctags come dimostrato da:
http://vim.wikia.com/wiki/Autocmd_to_update_ctags_file
Non posso davvero garantirlo, dato che generalmente utilizzo informazioni sul codice sorgente per la navigazione del codice, ma uso vim come editor ... vai a capire.
Che ne dici di avere pianificato l'esecuzione dei tag tramite crontab? Se l'albero del progetto è abbastanza stabile nella sua struttura, dovrebbe essere fattibile?
Per eliminare " premi Invio " prompt, usa : silent .
Su OSX questo comando non funzionerà immediatamente, almeno non per me.
au BufWritePost *.c,*.cpp,*.h silent! !ctags -R &
Ho trovato un post , che spiega come ottenere la versione standard di ctags che contiene l'opzione -R. Questo da solo non ha funzionato per me. Ho dovuto aggiungere / usr / local / bin alla variabile PATH in .bash_profile per raccogliere il cestino in cui Homebrew installa i programmi.
A mio avviso, il plug-in Indexer è migliore.
http://www.vim.org/scripts/script.php? script_id = 3221
Può essere:
1) un componente aggiuntivo per project.tar.gz
2) un plugin indipendente
- generazione di tag in background (non hai aspettato che ctags funzioni)
- progetti multipli supportati
Esiste un plugin vim chiamato AutoTag per questo che funziona davvero bene.
Se hai installato la taglist, aggiornerà anche quella per te.
L'opzione --append
è davvero la strada da percorrere. Utilizzato con un grep -v
, possiamo aggiornare solo un file taggato . Ad esempio, ecco un estratto di un plugin non lucidato che risolve questo problema. (NB: richiederà un " external " plugin della libreria )
" Options {{{1
let g:tags_options_cpp = '--c++-kinds=+p --fields=+imaS --extra=+q'
function! s:CtagsExecutable()
let tags_executable = lh#option#Get('tags_executable', s:tags_executable, 'bg')
return tags_executable
endfunction
function! s:CtagsOptions()
let ctags_options = lh#option#Get('tags_options_'.&ft, '')
let ctags_options .= ' '.lh#option#Get('tags_options', '', 'wbg')
return ctags_options
endfunction
function! s:CtagsDirname()
let ctags_dirname = lh#option#Get('tags_dirname', '', 'b').'/'
return ctags_dirname
endfunction
function! s:CtagsFilename()
let ctags_filename = lh#option#Get('tags_filename', 'tags', 'bg')
return ctags_filename
endfunction
function! s:CtagsCmdLine(ctags_pathname)
let cmd_line = s:CtagsExecutable().' '.s:CtagsOptions().' -f '.a:ctags_pathname
return cmd_line
endfunction
" ######################################################################
" Tag generating functions {{{1
" ======================================================================
" Interface {{{2
" ======================================================================
" Mappings {{{3
" inoremap <expr> ; <sid>Run('UpdateTags_for_ModifiedFile',';')
nnoremap <silent> <Plug>CTagsUpdateCurrent :call <sid>UpdateCurrent()<cr>
if !hasmapto('<Plug>CTagsUpdateCurrent', 'n')
nmap <silent> <c-x>tc <Plug>CTagsUpdateCurrent
endif
nnoremap <silent> <Plug>CTagsUpdateAll :call <sid>UpdateAll()<cr>
if !hasmapto('<Plug>CTagsUpdateAll', 'n')
nmap <silent> <c-x>ta <Plug>CTagsUpdateAll
endif
" ======================================================================
" Auto command for automatically tagging a file when saved {{{3
augroup LH_TAGS
au!
autocmd BufWritePost,FileWritePost * if ! lh#option#Get('LHT_no_auto', 0) | call s:Run('UpdateTags_for_SavedFile') | endif
aug END
" ======================================================================
" Internal functions {{{2
" ======================================================================
" generate tags on-the-fly {{{3
function! UpdateTags_for_ModifiedFile(ctags_pathname)
let source_name = expand('%')
let temp_name = tempname()
let temp_tags = tempname()
" 1- purge old references to the source name
if filereadable(a:ctags_pathname)
" it exists => must be changed
call system('grep -v " '.source_name.' " '.a:ctags_pathname.' > '.temp_tags.
\ ' && mv -f '.temp_tags.' '.a:ctags_pathname)
endif
" 2- save the unsaved contents of the current file
call writefile(getline(1, '
Questo codice definisce:
-
^ Xta
per forzare l'aggiornamento della base di tag per tutti i file nel progetto corrente;
-
^ Xtc
per forzare l'aggiornamento della base di tag per il file corrente (non salvato);
- un comando automatico che aggiorna la base dei tag ogni volta che viene salvato un file;
e supporta e molte opzioni per disabilitare l'aggiornamento automatico dove non lo vogliamo, per ottimizzare le chiamate ctags a seconda dei tipi di file, ...
Non è solo un suggerimento, ma un piccolo estratto di un plugin.
HTH,
), temp_name, 'b')
" 3- call ctags, and replace references to the temporary source file to the
" real source file
let cmd_line = s:CtagsCmdLine(a:ctags_pathname).' '.source_name.' --append'
let cmd_line .= ' && sed "s#\t'.temp_name.'\t#\t'.source_name.'\t#" > '.temp_tags
let cmd_line .= ' && mv -f '.temp_tags.' '.a:ctags_pathname
call system(cmd_line)
call delete(temp_name)
return ';'
endfunction
" ======================================================================
" generate tags for all files {{{3
function! s:UpdateTags_for_All(ctags_pathname)
call delete(a:ctags_pathname)
let cmd_line = 'cd '.s:CtagsDirname()
" todo => use project directory
"
let cmd_line .= ' && '.s:CtagsCmdLine(a:ctags_pathname).' -R'
echo cmd_line
call system(cmd_line)
endfunction
" ======================================================================
" generate tags for the current saved file {{{3
function! s:UpdateTags_for_SavedFile(ctags_pathname)
let source_name = expand('%')
let temp_tags = tempname()
if filereadable(a:ctags_pathname)
" it exists => must be changed
call system('grep -v " '.source_name.' " '.a:ctags_pathname.' > '.temp_tags.' && mv -f '.temp_tags.' '.a:ctags_pathname)
endif
let cmd_line = 'cd '.s:CtagsDirname()
let cmd_line .= ' && ' . s:CtagsCmdLine(a:ctags_pathname).' --append '.source_name
" echo cmd_line
call system(cmd_line)
endfunction
" ======================================================================
" (public) Run a tag generating function {{{3
function! LHTagsRun(tag_function)
call s:Run(a:tag_function)
endfunction
" ======================================================================
" (private) Run a tag generating function {{{3
" See this function as a /template method/.
function! s:Run(tag_function)
try
let ctags_dirname = s:CtagsDirname()
if strlen(ctags_dirname)==1
throw "tags-error: empty dirname"
endif
let ctags_filename = s:CtagsFilename()
let ctags_pathname = ctags_dirname.ctags_filename
if !filewritable(ctags_dirname) && !filewritable(ctags_pathname)
throw "tags-error: ".ctags_pathname." cannot be modified"
endif
let Fn = function("s:".a:tag_function)
call Fn(ctags_pathname)
catch /tags-error:/
" call lh#common#ErrorMsg(v:exception)
return 0
finally
endtry
echo ctags_pathname . ' updated.'
return 1
endfunction
function! s:Irun(tag_function, res)
call s:Run(a:tag_function)
return a:res
endfunction
" ======================================================================
" Main function for updating all tags {{{3
function! s:UpdateAll()
let done = s:Run('UpdateTags_for_All')
endfunction
" Main function for updating the tags from one file {{{3
" @note the file may be saved or "modified".
function! s:UpdateCurrent()
if &modified
let done = s:Run('UpdateTags_for_ModifiedFile')
else
let done = s:Run('UpdateTags_for_SavedFile')
endif
endfunction
Questo codice definisce:
-
^ Xta
per forzare l'aggiornamento della base di tag per tutti i file nel progetto corrente; -
^ Xtc
per forzare l'aggiornamento della base di tag per il file corrente (non salvato); - un comando automatico che aggiorna la base dei tag ogni volta che viene salvato un file; e supporta e molte opzioni per disabilitare l'aggiornamento automatico dove non lo vogliamo, per ottimizzare le chiamate ctags a seconda dei tipi di file, ... Non è solo un suggerimento, ma un piccolo estratto di un plugin.
HTH,
Auto Tag è un plugin vim che aggiorna i file tag esistenti al momento del salvataggio.
Lo uso da anni senza problemi, con l'eccezione che applica una dimensione massima ai file dei tag. A meno che tu non abbia un set molto grande di codice tutti indicizzati nello stesso file di tag, non dovresti raggiungere questo limite.
Nota che Auto Tag richiede il supporto Python in vim.