web-dev-qa-db-fra.com

Comment mettre à jour automatiquement le fichier de balises dans Vim?

J'utilise un fichier d'étiquette VIM C++ pour la navigation à l'aide de CTRL-]. Le problème est chaque fois que certains fichiers sont modifiés, les liens ne sont plus valides et je dois réexécuter les CTAG et mettre à jour le fichier de balises. Notre base de code est énorme et prend tout à fait un moment pour générer un fichier de balise.

Y a-t-il un outil qui met à jour périodiquement le fichier de balise en arrière-plan? Puis-je configurer VIM pour faire de même?

J'utilise gvim sous Windows.

35
Canopus

Suite à la réponse de Blixtor, vous devrez réfléchir un peu soigneusement sur la conception du script. Je recommanderais de séparer la conception de sorte que l'autocommand utilise la commande Windows "Démarrer" ou similaire pour exécuter un script externe en arrière-plan: empêchant ainsi Vim d'être insensible au fil du fichier de balise.

Ce script pourrait alors générer le fichier de balise à l'aide d'un nom de fichier différent (c'est-à-dire pas "Tags": ctags -R -o newtags .) et, lorsque CTAGS est terminé, supprimez tags et renommez newtags à tags. Cela empêchera que le fichier de balise ne soit pas disponible dans VIM tandis que la génération est terminée.

26
DrAl

J'ai écrit le Vim-EasyTags Plug-in pour faire exactement cela. J'initialise mon fichier de balises une fois en analysant tout un projet (en utilisant la commande :UpdateTags **/*.[hc] Par exemple) et ensuite, le plug-in mettra automatiquement à jour le fichier Tags comme je modifierai et :update Mes fichiers de code source dans VIM. Pendant que cela met à jour le fichier Tags, il bloquera Vim, mais parce que cela ne scanne que le fichier actuel qu'il ne prend pas longtemps.

Mise à jour (2014-07-30): Travailler toujours sur le plug-in Vim-EasyTags :-). De nos jours, il prend en charge un mode asynchrone pour éviter de bloquer Vim. Au moment où j'écris cela, le mode asynchrone n'est pas encore le mode par défaut, mais après plus de commentaires, je changerai probablement le mode par défaut.

21
xolox

Je l'ai déjà écrit un plugin pour faire tout le travail dur avec ctags: Indexer .

Il fournit une génération de balises automatiques sans douleur pour l'ensemble de projets et conserve les balises à jour. Les balises sont générées en arrière-plan , vous n'avez donc pas à attendre pendant que CTAG génère des balises. Vous pouvez l'utiliser indépendamment ou comme un complément pour un autre plugin projet.tar.gz .

Dans la première voie, vous pouvez déclarer vos projets en ~/.indexer_files comme ça:

[CoolProject]

/home/user/cool_project

[AnotherProject]
option:ctags_params = "--languages=c++"

/home/user/another_project/src
/home/user/another_project/lib 

Et puis, lorsque vous ouvrez n'importe quel fichier de /home/user/cool_project, tout ce projet sera indexé par CTAGS. Lorsque vous ouvrez des balises d'un autre projet, les balises sont générées pour cela. Mots-clés de différents projets ne sont jamais mélangés. Lorsque vous enregistrez le fichier de projet, les balises sont mises à jour en silence. Vous n'avez pas à vous soucier de cela, cela fonctionne simplement.

Pour plus d'informations, voir l'article: VIM: Navigation de code pratique pour vos projets , ce qui explique l'utilisation de l'indexeur + VIMPRJ à fond.

Il est testé avec succès sur VIM 7.3, sur les systèmes suivants:

  • Archlinux

  • Ubuntu 10.4

  • Windows XP

  • Mac OS X Lion

11
Dmitry Frank

Une idée:

Utilisez Vim Autocommands (: Aide Autocommand) pour déclencher la course d'un script à chaque fois qu'un tampon est enregistré à l'aide de l'événement BufwritePost.

Ce script démarre la génération CTAGS et contient une petite logique supplémentaire pour ne pas fonctionner lorsqu'elle fonctionne déjà (ou pour fonctionner au plus toutes les 10 minutes, etc.).

Éditer:

Quelque chose de similaire a été demandé au préalable, voir VIM Auto-générer des CTAGS

9
Blixtor

De son référentiel: vim-gutentags est un plugin qui prend soin de la gestion bien nécessaire des fichiers de balises dans Vim. Il (RE) générera des fichiers de balises lorsque vous travaillez tout en restant complètement hors de votre chemin. Il fera même de son mieux pour garder ces fichiers de tags hors de votre chemin. Il n'a pas de dépendances et fonctionne simplement.

Vous pouvez essayer d'essayer à https://github.com/ludovicchabant/vim-gutentalgs .

3
Huy Vo

Cette logique fonctionne pour la plupart des cas: lors de l'ouverture d'un nouveau fichier dans VIM, passez au répertoire de ce fichier et générez un fichier de balises là-bas s'il n'existe pas déjà. Lors de la sauvegarde d'un tampon modifié, générez un fichier de balises dans le répertoire du fichier étant enregistré:


function! GenerateTagsFile()
  if (!filereadable("tags"))
    exec ":!start /min ctags -R --c++-kinds=+p --fields=+iaS --extra=+q --sort=foldcase ."
  endif
endfunction

" Always change to directory of the buffer currently in focus.
autocmd! bufenter *.* :cd %:p:h
autocmd! bufread  *.* :cd %:p:h

" Generate tags on opening an existing file.
autocmd! bufreadpost *.cpp :call GenerateTagsFile()
autocmd! bufreadpost *.c   :call GenerateTagsFile()
autocmd! bufreadpost *.h   :call GenerateTagsFile()

" Generate tags on save. Note that this regenerates tags for all files in current folder.
autocmd! bufwritepost *.cpp :call GenerateTagsFile()
autocmd! bufwritepost *.c   :call GenerateTagsFile()
autocmd! bufwritepost *.h   :call GenerateTagsFile()
1
user15071

http://vim.wikia.com/wiki/autocmd_to_update_ctags_file

function! DelTagOfFile(file)
  let fullpath = a:file
  let cwd = getcwd()
  let tagfilename = cwd . "/tags"
  let f = substitute(fullpath, cwd . "/", "", "")
  let f = escape(f, './')
  let cmd = 'sed -i "/' . f . '/d" "' . tagfilename . '"'
  let resp = system(cmd)
endfunction

function! UpdateTags()
  let f = expand("%:p")
  let cwd = getcwd()
  let tagfilename = cwd . "/tags"
  let cmd = 'ctags -a -f ' . tagfilename . ' --c++-kinds=+p --fields=+iaS --extra=+q ' . '"' . f . '"'
  call DelTagOfFile(f)
  let resp = system(cmd)
endfunction
autocmd BufWritePost *.cpp,*.h,*.c call UpdateTags()
1
Sergei Struk