2009-07-21 14 views
32

Używam pliku znaczników vim C++ do nawigacji za pomocą Ctrl-]. Problem polega na tym, że gdy jakiś plik zostanie zmodyfikowany, linki przestają być poprawne i muszę ponownie uruchomić ctags i zaktualizować plik znacznika. Nasza baza kodu jest ogromna i generowanie pliku znacznika zajmuje sporo czasu.Jak automatycznie aktualizować plik znaczników w vim?

Czy istnieje narzędzie, które okresowo aktualizuje plik znacznika w tle? Czy mogę skonfigurować VIM, aby zrobił to samo?

Używam gvim pod Windows.

Odpowiedz

25

nawiązaniu do odpowiedzi Blixtor jest, trzeba trochę pomyśleć dokładnie o konstrukcji scenariusza. Zaleciłbym odseparowanie projektu w taki sposób, aby polecenie autokomendy korzystało z polecenia "start" systemu Windows lub podobnego do uruchomienia zewnętrznego skryptu w tle: w ten sposób uniemożliwiłoby Vimowi przestanie odpowiadać podczas generowania pliku znaczników.

Że skrypt może następnie wygenerować plik tag używając innej nazwy pliku (to znaczy nie „tagi”: ctags -R -o newtags .) oraz, gdy ctags jest kompletny, usuwać i zmieniać nazwy newtagstags do tags. Zapobiegnie to niedostępności pliku znacznika w Vimie podczas generowania.

+2

Ważne dodatkowe punkty! – Blixtor

+0

@AI, czy istnieje podobne rozwiązanie dla systemu Linux ?! – Rafid

+0

Dla systemu Linux wyobrażam sobie, że możesz uruchomić polecenie za pomocą &, aby wypchnąć go na drugi plan, nie? –

9

Pomysł:

Zastosowanie Vim autokomendy (: help autocommand), aby wywołać uruchomiony skryptu każdym razem, gdy bufor jest zapisany za pomocą zdarzenia BufWritePost.

Ten skrypt uruchamia generację ctags i zawiera dodatkową małą logikę, która nie działa, gdy jest już uruchomiona (lub uruchamia się co najwyżej 10 minut itd.).

Edit:

Coś podobnego został poproszony tutaj wcześniej, patrz Vim auto-generate ctags

1

Ta logika działa w większości przypadków: podczas otwierania nowego pliku w vim, przejdź do katalogu tego pliku i wygeneruj tam plik tagów, jeśli jeszcze nie istnieje. Podczas zapisywania zmienionego bufora wygenerować plik tagi w katalogu pliku zapisywane:


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

możesz użyć: call system() zamiast, w ten sposób byłby przenośny, możesz uzyskać dowolne wyjście przez "let l: lines = system (" cmdline ") ', a kod powrotu jest zwracane w v: shell_error. – osirisgothra

18

pisałem vim-easytags plug-in, aby dokładnie to zrobić. Zainicjuję plik tagów jeden raz, skanując cały projekt (na przykład za pomocą komendy :UpdateTags **/*.[hc]), a następnie wtyczka automatycznie zaktualizuje plik znaczników podczas edycji i :update moich plików kodu źródłowego w Vimie. Podczas aktualizacji pliku znaczników zablokuje Vima, ale ponieważ skanuje tylko bieżący plik, nie zajmuje dużo czasu.

Aktualizacja (2014-07-30): Nadal działa na wtyczce vim-easytags :-). Obecnie obsługuje tryb asynchroniczny, aby uniknąć blokowania Vima. W tym czasie napisałem, że tryb asynchroniczny nie jest jeszcze trybem domyślnym, ale po uzyskaniu większej ilości informacji prawdopodobnie przełączyłem tryb domyślny.

+0

Hmmm edytować z przyszłości. (Kiedy jestem tutaj ...) jak to się ma do [AutoTag] (http://www.vim.org/scripts/script.php?script_id=1343). – FDinoff

+0

@FDinoff: AutoTag wydaje się dużo prostszy, więc jednym z czynników różnicujących jest kompletność/konfigurowalność/złożoność. Kolejną różnicą jest to, że vim-easytags może aktualizować * i wyróżniać * znaczniki, podczas gdy Autotag wydaje się skupiać tylko na części aktualizującej. Ponadto, AutoTag wymaga Pythona, podczas gdy vim-easytags może pracować bez. – xolox

+0

"Ta wtyczka automatycznie tworzy globalny plik znaczników i aktualizuje go podczas edycji plików w Vimie." Jak mogę zachować osobne tagi dla różnych projektów zamiast pojedynczego globalnego? @xolox – Tmx

10

Już napisałem wtyczkę do wykonania całej ciężkiej pracy z ctags: Indexer.

Zapewnia bezbolesne automatyczne generowanie tagów dla całego projektu (projektów) i aktualizuje znaczniki. Tagi są generowane w tle, więc nie musisz czekać, podczas gdy ctags generuje znaczniki. Możesz go używać niezależnie lub jako dodatek do innej wtyczki project.tar.gz.

W pierwszej okazji, można zadeklarować swoje projekty w ~/.indexer_files tak:

[CoolProject] 

/home/user/cool_project 

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

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

A potem, kiedy otworzyć dowolny plik z /home/user/cool_project, cały ten projekt będą indeksowane przez ctags. Po otwarciu tagów z innego projektu generowane są również dla nich znaczniki. Tagi z różnych projektów nigdy nie są mieszane. Podczas zapisywania pliku z projektu znaczniki są dyskretnie aktualizowane. Nie musisz się tym przejmować, to po prostu działa.

Aby uzyskać szczegółowe informacje, zobacz artykuł: Vim: convenient code navigation for your projects, który dokładnie opisuje użycie Indexer + Vimprj.

Jest z powodzeniem przetestowany na vim 7.3, w następujących systemach:

  • 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() 
Powiązane problemy