En ce moment, j'ai ce qui suit dans mon .vimrc
:
au BufWritePost *.c,*.cpp,*.h !ctags -R
Il y a quelques problèmes avec ceci:
Lorsque vous combinez ces deux problèmes, je finis par pousser l'entrée supplémentaire trop tôt (avant ctags -R
est terminé), puis voyez le message d'erreur gênant et appuyez de nouveau sur Entrée.
Je sais que cela ne semble pas être un gros problème, mais avec la quantité d'écritures de fichiers que je fais un jour donné, cela a tendance à devenir vraiment ennuyeux. Il doit y avoir une meilleure façon de le faire!
au BufWritePost *.c,*.cpp,*.h silent! !ctags -R &
L'inconvénient est que vous n'aurez pas de fichier de balises utile jusqu'à ce qu'il soit terminé. Tant que vous êtes sur un système * nix, il devrait être possible de faire plusieurs écritures avant la fin des ctags précédents, mais vous devriez le tester. Sur un système Windows, il ne le mettra pas en arrière-plan et se plaindra que le fichier est verrouillé jusqu'à la fin des premiers ctags (ce qui ne devrait pas causer de problèmes dans vim, mais vous vous retrouverez avec un fichier de balises légèrement obsolète). ).
Notez que vous pouvez utiliser le --append
comme le suggère tonylo, mais vous devrez ensuite désactiver tagbsearch
, ce qui pourrait signifier que les recherches de balises prennent beaucoup plus de temps, selon la taille de votre fichier de balises.
Éditer: Une solution très similaire à la suivante a été publiée sous la forme du script vim AutoTag. Notez que le script a cependant besoin d'un vim avec Python ).
Ma solution se résume à awk à la place, elle devrait donc fonctionner sur de nombreux autres systèmes.
au FileType {c,cpp} au BufWritePost <buffer> silent ! [ -e tags ] &&
\ ( awk -F'\t' '$2\!="%:gs/'/'\''/"{print}' tags ; ctags -f- '%:gs/'/'\''/' )
\ | sort -t$'\t' -k1,1 -o tags.new && mv tags.new tags
Notez que vous ne pouvez l'écrire de cette façon que dans un script, sinon il doit aller sur une seule ligne.
Il se passe beaucoup de choses là-dedans:
Cette commande automatique se déclenche lorsqu'un fichier a été détecté comme étant C ou C++, et ajoute à son tour une commande automatique de tampon local qui est déclenchée par l'événement BufWritePost
.
Il utilise le %
espace réservé qui est remplacé par le nom de fichier du tampon au moment de l'exécution, avec le :gs
modificateur utilisé pour citer entre guillemets le nom de fichier (en transformant les guillemets simples incorporés en guillemets-d'échappement-guillemets).
De cette façon, il exécute une commande Shell qui vérifie si un fichier tags
existe, auquel cas son contenu est imprimé à l'exception des lignes qui se réfèrent au fichier qui vient d'être enregistré, tandis que ctags
est invoqué sur juste le fichier qui vient d'être enregistré, et le résultat est alors sort
ed et remis en place.
Implémenteur Caveat: cela suppose que tout se trouve dans le même répertoire et que c'est également le répertoire courant du tampon local. Je n'ai pas songé au cheminement.
J'ai écrit easytags.vim pour faire exactement cela: mettre à jour et surligner automatiquement les balises. Le plug-in peut être configuré pour mettre à jour uniquement le fichier en cours de modification ou tous les fichiers du répertoire du fichier en cours de modification (récursivement). Il peut utiliser un fichier de balises global, des fichiers de balises spécifiques au type de fichier et des fichiers de balises spécifiques au projet.
J'ai remarqué que c'est un vieux fil, cependant ... Utilisez incron dans * nix comme des environnements supportant inotify. Il lancera toujours des commandes chaque fois que les fichiers d'un répertoire changent. c'est à dire.,
/home/me/Code/c/that_program IN_DELETE,IN_CLOSE_WRITE ctags --sort=yes *.c
C'est tout.
Utilisez peut-être l'argument append pour ctags comme démontré par:
http://vim.wikia.com/wiki/Autocmd_to_update_ctags_file
Je ne peux pas vraiment garantir cela car j'utilise généralement les informations de source pour la navigation dans le code, mais j'utilise vim comme éditeur ... allez comprendre.
Que diriez-vous d'avoir des ctags planifiés pour s'exécuter via crontab? Si votre arborescence de projet est assez stable dans sa structure, cela devrait être faisable?
Sur OSX, cette commande ne fonctionnera pas hors de la boîte, du moins pas pour moi.
au BufWritePost *.c,*.cpp,*.h silent! !ctags -R &
J'ai trouvé un post , qui explique comment obtenir la version standard de ctags qui contient l'option -R. Cela seul n'a pas fonctionné pour moi. J'ai dû ajouter/usr/local/bin à la variable PATH dans .bash_profile afin de récupérer le bac où Homebrew installe les programmes.
Pour supprimer l'invite "appuyez sur Entrée", utilisez : silencieux .
Le --append
l'option est en effet la voie à suivre. Utilisé avec un grep -v
, nous ne pouvons mettre à jour qu'un seul fichier balisé . Par exemple, voici un extrait d'un plugin non poli qui résout ce problème. (NB: Il faudra un "externe" plugin de bibliothèque )
" 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, '$'), 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
Ce code définit:
^Xta
pour forcer la mise à jour de la base de balises pour tous les fichiers du projet en cours;^Xtc
pour forcer la mise à jour de la base de balises pour le fichier actuel (non enregistré);HTH,
Il existe un plugin vim appelé AutoTag pour cela qui fonctionne vraiment bien.
Si vous avez installé la liste de balises, elle sera également mise à jour pour vous.
À mon avis, le plugin Indexer est meilleur.
http://www.vim.org/scripts/script.php?script_id=3221
Ça peut être:
1) un module complémentaire pour project.tar.gz
2) un plugin indépendant
Auto Tag est un plugin vim qui met à jour les fichiers de balises existants lors de l'enregistrement.
Je l'utilise depuis des années sans problème, à l'exception qu'il impose une taille maximale sur les fichiers de balises. À moins que vous n'ayez un très grand ensemble de code indexé dans le même fichier de balises, vous ne devriez pas atteindre cette limite.
Notez que la balise automatique nécessite Python support dans vim.