2009-07-21 14 views
32

Ich benutze vim C++ - Tag-Datei für die Navigation mit Strg -]. Das Problem ist, wenn eine Datei geändert wird, die Links nicht mehr gültig sind und ich Ctags erneut ausführen und die Tag-Datei aktualisieren muss. Unsere Codebasis ist riesig und es dauert eine ganze Weile, um eine Tag-Datei zu generieren.Wie wird die Tag-Datei in vim automatisch aktualisiert?

Gibt es ein Tool, das die Tag-Datei im Hintergrund regelmäßig aktualisiert? Kann ich VIM so konfigurieren, dass es dasselbe tut?

Ich verwende GVIM unter Windows.

Antwort

25

Zusätzlich zu Blixtor Antwort, werden Sie ein wenig vorsichtig über die Gestaltung des Skripts zu denken. Ich würde empfehlen, das Design so zu trennen, dass das Autocommand den Windows-Befehl "start" o.ä. verwendet, um ein externes Skript im Hintergrund auszuführen: Dadurch wird verhindert, dass Vim nicht reagiert, während die Tag-Datei generiert wird.

Das Skript dann die Tag-Datei erzeugen könnte einen anderen Dateinamen verwenden (das heißt nicht „Tags“: ctags -R -o newtags .), und wenn ctags abgeschlossen ist, löschen tags und benennen newtags-tags. Dies verhindert, dass die Tag-Datei in Vim nicht verfügbar ist, während die Generierung abgeschlossen ist.

+2

Wichtige zusätzliche Punkte! – Blixtor

+0

@AI, gibt es eine ähnliche Lösung für Linux ?! – Rafid

+0

Für Linux stelle ich mir vor, Sie könnten den Befehl mit & ausführen, um es in den Hintergrund zu schieben, nein? –

9

Eine Idee:

Verwenden Vim automatischen Befehle (: help automatischer Befehl) ein Skripts ein Puffer jedes Mal auszulösen läuft gespeichert wird, um das BufWritePost Ereignis verwenden.

Dieses Skript startet die ctags Generation und enthält einige zusätzliche kleine Logik nicht zu laufen, während es bereits läuft (oder höchstens alle 10 Minuten zu laufen, etc.).

Edit:

Etwas Ähnliches wurde hier vorher gefragt, siehe Vim auto-generate ctags

1

Diese Logik für die meisten Fälle funktioniert: Wenn Sie eine neue Datei in vim zu öffnen, ändern, um eine Tags-Datei dort in das Verzeichnis der Datei und erzeugt, wenn sie nicht bereits vorhanden ist. Wenn ein geänderte Puffer zu speichern, eine Tags-Datei im Verzeichnis der Datei erzeugt gespeichert werden:


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

möchten Sie vielleicht verwenden: Call-System() statt, so würde es portabel sein, können Sie jede Ausgabe über 'let l: Zeilen = System ("cmdline")' und der Rückkehrcode ist zurückgegeben in v: shell_error. – osirisgothra

18

Ich schrieb die vim-easytags Plug-In genau dies zu tun. Ich initialisiere meine Tag-Datei einmal, indem ich ein ganzes Projekt scanne (mit dem Befehl :UpdateTags **/*.[hc] zum Beispiel) und danach aktualisiert das Plug-in automatisch die Tag-Datei, während ich meine Quellcode-Dateien in Vim bearbeite und :update. Während es die Tag-Datei aktualisiert, wird es Vim blockieren, aber da es nur die aktuelle Datei scannt, dauert es nicht lange.

Update (2014-07-30): Arbeitet noch am vim-easytags Plug-in :-). Heutzutage unterstützt es einen asynchronen Modus, um Vim nicht zu blockieren. Zu der Zeit, als ich dies schreibe, ist der asynchrone Modus noch nicht der Standardmodus, aber nach etwas mehr Feedback werde ich wahrscheinlich den Standardmodus wechseln.

+0

Hmmm aus der Zukunft bearbeiten. (Während ich hier bin ...) Wie vergleicht das mit [AutoTag] (http://www.vim.org/scripts/script.php?script_id=1343). – FDinoff

+0

@FDinoff: AutoTag scheint viel einfacher zu sein, daher ist ein Differenzierungsfaktor Vollständigkeit/Konfigurierbarkeit/Komplexität. Ein weiterer Unterschied ist, dass vim-easytags * Tags aktualisieren und markieren kann, während AutoTag sich nur auf den aktualisierenden Teil zu konzentrieren scheint. Außerdem benötigt AutoTag Python, während vim-easytags ohne arbeiten kann. – xolox

+0

"Dieses Plug-in erstellt automatisch eine globale Tag-Datei und hält sie beim Bearbeiten von Dateien in Vim auf dem neuesten Stand." Wie kann ich separate Tags für verschiedene Projekte anstelle von einzelnen globalen beibehalten? @xolox – Tmx

10

Ich schrieb bereits ein Plugin all die harte Arbeit mit ctags zu tun: Indexer.

Es bietet eine automatische Generierung von automatischen Tags für das gesamte Projekt und hält die Tags auf dem neuesten Stand. Tags werden generiert im Hintergrund, so müssen Sie nicht warten, während Ctags Tags generiert. Sie können es unabhängig oder als Add-on für ein anderes Plugin project.tar.gz verwenden.

[CoolProject] 

/home/user/cool_project 

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

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

Und dann, wenn Sie eine Datei aus /home/user/cool_project, all dieses Projekt von ctags indiziert wird geöffnet:

In der ersten Weise können Sie Ihre Projekte in ~/.indexer_files wie folgt erklären. Wenn Sie Tags aus einem anderen Projekt öffnen, werden auch Tags dafür generiert. Tags aus verschiedenen Projekten werden niemals gemischt. Wenn Sie eine Datei aus einem Projekt speichern, werden die Tags automatisch aktualisiert. Sie müssen sich nicht darum kümmern, es funktioniert einfach.

Weitere Informationen finden Sie im Artikel: Vim: convenient code navigation for your projects, der die Verwendung von Indexer + Vimprj gründlich erklärt.

Es wird erfolgreich getestet auf Vim 7.3, auf den folgenden Systemen:

  • 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() 
Verwandte Themen