Vim automatyczne generowanie ctags

W tej chwili mam w moim .vimrc:

au BufWritePost *.c,*.cpp,*.h !ctags -R

Jest z tym kilka problemów:

  1. jest powolny -- regeneruje znaczniki dla plików, które nie zmieniły się od ostatniej generacji znaczników.
  2. muszę ponownie nacisnąć przycisk enter Po zapisaniu pliku z powodu nieuniknionego "naciśnij Enter lub wpisz polecenie, aby kontynuować".

Gdy połączysz te dwa problemy, za wcześnie naciskam dodatkowe enter( zanim ctags -R się skończy), a następnie zobacz irytujący komunikat o błędzie i ponownie naciśnij enter.

Wiem, że to nie brzmi jak wielka sprawa, ale z ilością plików, które piszę w danym dniu, zwykle robi się to naprawdę denerwujące. Musi być na to lepszy sposób!

Author: cdleary, 2008-10-01

12 answers

au BufWritePost *.c,*.cpp,*.h silent! !ctags -R &

Minusem jest to, że nie będziesz miał przydatnego pliku tagów, dopóki nie zostanie ukończony. Tak długo, jak jesteś na systemie *nix, powinno być ok, aby zrobić wiele zapisów przed poprzedni ctags został zakończony, ale powinieneś to przetestować. W systemie Windows nie będzie go umieszczać w tle i będzie narzekać, że plik jest zablokowany do czasu zakończenia pierwszych ctags (co nie powinno powodować problemów w Vimie, ale skończysz z nieco przestarzałym plikiem tags).

Uwaga, możesz użyć --append opcja jak sugeruje tonylo, ale wtedy będziesz musiał wyłączyć tagbsearch, co może oznaczać, że wyszukiwanie tagów trwa znacznie dłużej, w zależności od rozmiaru pliku tagów.

 41
Author: Zathrus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-01 00:07:22

Edit : rozwiązanie bardzo podobne do poniższych zostało opublikowane jako AutoTag skrypt vim. Zauważ, że skrypt potrzebuje Vima z obsługą Pythona.

Moje rozwiązanie zamiast tego działa na awk, więc powinno działać na wielu innych systemach.


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

Zauważ, że możesz to napisać tylko w ten sposób w skrypcie, w przeciwnym razie musi to iść w jednej linii.

Dużo się dzieje w tam:

  1. To automatyczne polecenie uruchamia się po wykryciu pliku jako C lub C++ i dodaje z kolei automatyczne polecenie bufora lokalnego, które jest wyzwalane przez zdarzenie BufWritePost.

  2. Używa symbolu zastępczego %, który jest zastępowany przez nazwę pliku bufora w czasie wykonywania, wraz z modyfikatorem :gs używanym do Shell-quote nazwy pliku (zamieniając dowolne osadzone pojedyncze cudzysłowy w quote-escape-quote-quote).

  3. W ten sposób uruchamia polecenie powłoki sprawdza, czy istnieje plik tags, w którym to przypadku jego zawartość jest drukowana z wyjątkiem linii, które odnoszą się do właśnie zapisanego pliku, tymczasem ctags jest wywoływany tylko na właśnie zapisanym pliku, a wynikiem jest sort ed i wstawiany z powrotem na miejsce.

Caveat implementor: zakłada to, że wszystko znajduje się w tym samym katalogu i że jest to również bufor-lokalny katalog bieżący. Nie zastanawiałam się nad tym.

 13
Author: Aristotle Pagaltzis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-29 19:24:01

Napisałem easytags.vim aby to zrobić: automatycznie aktualizuj i podświetl tagi. Wtyczka może być skonfigurowana tak, aby aktualizować tylko edytowany plik lub wszystkie pliki w katalogu edytowanego pliku (rekurencyjnie). Może używać globalnego pliku tagów, plików tagów specyficznych dla typu pliku i plików tagów specyficznych dla projektu.

 10
Author: xolox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-19 17:52:50

Zauważyłem jednak, że jest to stary wątek... Użyj incron w * Nix podobnych środowiskach wspierających inotify. Zawsze będzie uruchamiać polecenia za każdym razem, gdy zmienią się pliki w katalogu. tzn.,

/home/me/Code/c/that_program IN_DELETE,IN_CLOSE_WRITE ctags --sort=yes *.c
To wszystko.
 7
Author: code933k,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-30 05:46:46

Być może użyj argumentu append do ctags, jak pokazano przez:

Http://vim.wikia.com/wiki/Autocmd_to_update_ctags_file

Nie mogę za to ręczyć, ponieważ zazwyczaj używam Source insight do przeglądania kodu, ale używam Vima jako edytora... pomyśl.

 3
Author: tonylo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-30 23:01:38

A może ctags będzie uruchamiany przez crontab? Jeśli twoje drzewo projektu jest dość stabilne w swojej strukturze, powinno to być wykonalne?

 2
Author: zigdon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-30 22:55:34

Aby wyłączyć monit "naciśnij enter", użyj : silent .

 2
Author: Greg Hewgill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-30 23:03:15

Na OSX to polecenie nie będzie działać po wyjęciu z pudełka, przynajmniej nie dla mnie.

au BufWritePost *.c,*.cpp,*.h silent! !ctags -R &

Znalazłem post , który wyjaśnia jak uzyskać standardową wersję ctags zawierającą opcję-R. To samo nie zadziałało. Musiałem dodać /usr / local / bin do zmiennej PATH w .bash_profile w celu pobrania kosza, w którym Homebrew instaluje programy.

 2
Author: rand_acs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-01 10:45:09

W moim opninion, Plugin Indexer jest lepszy.

Http://www.vim.org/scripts/script.php?script_id=3221

Może Być:

1) dodatek do projektu.smoła.gz

2) niezależny plugin

  • generowanie znaczników tła (nie trzeba czekać na działanie ctags)
  • obsługiwane wiele projektów
 1
Author: dimonomid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-13 05:37:29

Istnieje wtyczka vim o nazwie AutoTag , która działa naprawdę dobrze.

Jeśli masz zainstalowaną listę tagów, zaktualizuje ją również dla Ciebie.

 1
Author: Marcus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-27 17:07:10

Opcja --append jest rzeczywiście droga do zrobienia. Używany z grep -v, możemy zaktualizować tylko jeden oznaczony Plik. Na przykład, oto fragment unpolished plugin , który rozwiązuje ten problem. (Uwaga: będzie to wymagało" zewnętrznego " pluginu biblioteki )

" 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

Ten kod definiuje:

  • ^Xta aby wymusić aktualizację bazy tagów dla wszystkich plików w bieżącym projekcie;
  • ^Xtc Aby wymusić aktualizację bazy tagów dla bieżącego (niezapisanego) plik;
  • autocommand, który aktualizuje bazę tagów za każdym razem, gdy plik jest zapisywany ; i obsługuje i wiele opcji, aby wyłączyć automatyczną aktualizację tam, gdzie jej nie chcemy, aby dostroić wywołania ctags w zależności od typów plików, ... To nie jest tylko wskazówka, ale mały fragment wtyczki.

HTH,

 1
Author: Luc Hermitte,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-16 17:34:09

Auto Tag jest wtyczką vim, która aktualizuje istniejące pliki tagów podczas zapisywania.

Używam go od lat bez problemów, z wyjątkiem tego, że wymusza maksymalny rozmiar plików tagów. Jeśli nie masz naprawdę dużego zestawu kodu indeksowanego w tym samym pliku tags, nie powinieneś jednak przekraczać tego limitu.

Zauważ, że Auto Tag wymaga obsługi Pythona w Vimie.

 0
Author: Greg Jandl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-26 22:15:27