2009-07-21 11 views
32

J'utilise le fichier vim C++ pour la navigation en utilisant Ctrl-]. Le problème est que chaque fois qu'un fichier est modifié, les liens ne sont plus valides et je dois relancer ctags et mettre à jour le fichier de balises. Notre base de code est énorme et il faut beaucoup de temps pour générer un fichier de balises.Comment mettre à jour automatiquement le fichier de marqueurs dans vim?

Existe-t-il un outil qui met périodiquement à jour le fichier d'étiquettes en arrière-plan? Puis-je configurer VIM pour faire la même chose?

J'utilise gvim sous Windows.

Répondre

25

Suite à la réponse de Blixtor, vous aurez besoin de penser un peu attentivement à la conception du script. Je recommande de séparer la conception de sorte que l'autocommande utilise la commande Windows "start" ou similaire pour exécuter un script externe en arrière-plan: empêchant ainsi Vim de ne pas répondre lorsque le fichier de balise est généré.

Ce script peut alors générer le fichier d'étiquette en utilisant un nom de fichier différent (à savoir non « tags »: ctags -R -o newtags .) et, lorsque ctags est terminée, supprimez tags et renommer newtags-tags. Cela empêchera le fichier de balise d'être indisponible dans Vim tant que la génération est terminée.

+2

points supplémentaires importants! – Blixtor

+0

@AI, existe-t-il une solution similaire pour Linux ?! – Rafid

+0

Pour Linux, j'imagine que vous pouvez exécuter la commande avec & pour la pousser en arrière-plan, non? –

9

Une idée:

vim (autocommandes: aide autocommand) pour déclencher l'exécution 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 de ctags et contient une petite logique supplémentaire pour ne pas s'exécuter alors qu'il est déjà en cours d'exécution (ou pour s'exécuter au maximum toutes les 10 minutes, etc.).

Edit:

Quelque chose a été demandé similaire ici auparavant, voir Vim auto-generate ctags

1

Cette logique fonctionne dans la plupart des cas: Lors de l'ouverture d'un nouveau fichier dans vim, placez-vous dans le répertoire de ce fichier et générez un fichier de tags s'il n'existe pas déjà. Lors de l'enregistrement d'un tampon modifié, générer un fichier de balises dans le répertoire du fichier en cours d'enregistrement:


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() 
+0

vous pouvez utiliser: call system() à la place, de cette façon il serait portable, vous pouvez obtenir une sortie via 'let l: lines = system ("cmdline")' et le code retour est retourné dans v: shell_error. – osirisgothra

18

j'ai écrit le plug-in vim-easytags pour faire exactement cela. J'initialise mon fichier de tags une fois en balayant un projet entier (en utilisant la commande :UpdateTags **/*.[hc] par exemple) et après le plug-in mettra automatiquement à jour le fichier de tags alors que j'édite et :update mes fichiers de code source dans Vim. Bien qu'il mette à jour le fichier des balises, il bloquera Vim, mais comme il ne fait que balayer le fichier actuel, il ne prendra pas longtemps.

Mise à jour (2014-07-30): Fonctionne toujours sur le plug-in vim-easytags :-). De nos jours, il supporte 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 quelques commentaires, je vais probablement changer le mode par défaut.

+0

Hmmm éditer à partir du futur. (Pendant que je suis là ...) comment cela se compare-t-il à [AutoTag] (http://www.vim.org/scripts/script.php?script_id=1343). – FDinoff

+0

@FDinoff: AutoTag semble beaucoup plus simple, donc un facteur de différenciation est l'exhaustivité/la configurabilité/la complexité. Une autre différence est que vim-easytags peut mettre à jour * et mettre en surbrillance * les balises alors que AutoTag semble se concentrer uniquement sur la partie mise à jour. En outre, AutoTag nécessite Python alors que vim-easytags peut fonctionner sans. – xolox

+0

"Ce plug-in crée automatiquement un fichier de tags global et le maintient à jour lorsque vous éditez des fichiers dans Vim." Comment puis-je conserver des tags séparés pour différents projets au lieu d'un unique global? @xolox – Tmx

10

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

Il fournit une génération automatique d'étiquettes indolore pour l'ensemble du (des) projet (s) et maintient les étiquettes à jour. Les balises sont générées en arrière-plan, donc, vous n'avez pas à attendre que ctags génère des balises. Vous pouvez l'utiliser indépendamment ou en tant que module complémentaire pour un autre plugin project.tar.gz.

Dans la première façon, vous pouvez déclarer vos projets ~/.indexer_files comme ceci:

[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 un fichier à partir /home/user/cool_project, tout ce projet sera indexé par ctags. Lorsque vous ouvrez des balises d'un autre projet, des balises sont générées pour celui-ci. Les tags de différents projets ne sont jamais mélangés. Lorsque vous enregistrez un fichier à partir du projet, les balises sont mises à jour silencieusement. Vous n'avez pas à vous en soucier, ça marche.

Pour des informations détaillées, voir l'article: Vim: convenient code navigation for your projects, qui explique de manière approfondie l'utilisation d'Indexer + Vimprj.

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

1

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() 
Questions connexes