Vim автоматически генерирует ctags
прямо сейчас у меня есть следующее в моем .vimrc
:
au BufWritePost *.c,*.cpp,*.h !ctags -R
есть несколько проблем с этим:
- это медленно -- восстанавливает теги для файлов, которые не изменились с момента последнего поколения тегов.
- Я должен нажать кнопку Enter снова после записи файла из-за неизбежного "нажмите Enter или введите команду для продолжения".
когда вы объединяете эти две проблемы, я в конечном итоге нажимаю дополнительные введите слишком рано (до ctags -R
закончил), затем см. раздражающее сообщение об ошибке и снова нажмите enter.
Я знаю, что это не звучит как большое дело, но с количеством записей файлов, которые я делаю в данный день, это, как правило, очень раздражает. Должен быть лучший способ сделать это!
12 ответов:
au BufWritePost *.c,*.cpp,*.h silent! !ctags -R &
недостатком является то, что у вас не будет полезного файла тегов, пока он не завершится. Пока вы находитесь в системе *nix, должно быть нормально делать несколько записей до завершения предыдущих ctags, но вы должны проверить это. В системе Windows он не будет помещать его в фоновом режиме, и он будет жаловаться, что файл заблокирован до завершения первого ctags (что не должно вызывать проблем в vim, но вы получите немного устаревший файл тегов).
Примечание., вы могли бы использовать
--append
опция, как предлагает тонило, но тогда вам придется отключитьtagbsearch
что может означать, что поиск тегов занимает намного больше времени, в зависимости от размера вашего файла тегов.
Edit: решение, очень похожее на следующее, было опубликовано как the AutoTag скрипт для Vim. Обратите внимание, что скрипт требуется vim с поддержкой Python однако.
вместо этого мое решение выходит на awk, поэтому оно должно работать на многих других системах.
au FileType {c,cpp} au BufWritePost <buffer> silent ! [ -e tags ] && \ ( awk -F'\t' '\!="%:gs/'/'\''/"{print}' tags ; ctags -f- '%:gs/'/'\''/' ) \ | sort -t$'\t' -k1,1 -o tags.new && mv tags.new tags
обратите внимание, что вы можете написать его только таким образом в скрипте, иначе он должен идти на одном линия.
там много чего происходит здесь:
эта автоматическая команда запускается, когда файл был обнаружен как C или C++, и добавляет в свою очередь буферную локальную автоматическую команду, которая запускается
BufWritePost
событие.использует
%
заполнитель, который заменяется именем файла буфера во время выполнения, вместе с:gs
модификатор, используемый для оболочки-цитировать имя файла (путем превращения любых встроенных одинарных кавычек в цитата-побег-Цитата-Цитата).таким образом он запускает команду оболочки, которая проверяет, если
tags
файл существует, и в этом случае его содержимое печатается, за исключением строк, которые относятся к только что сохраненному файлу, между темctags
вызывается только на только что сохраненный файл, и результат тогдаsort
Эд и поставить на место.Caveat implementor: это предполагает, что все находится в том же каталоге и что это также буфер-локальный ток справочник. Я не думал о том, чтобы искалечить путь.
Я писал easytags.ВИМ чтобы сделать именно это: автоматически обновлять и выделять теги. Плагин может быть настроен для обновления только редактируемого файла или всех файлов в каталоге редактируемого файла (рекурсивно). Он может использовать файл глобальных тегов,файлы тегов определенного типа и файлы тегов проекта.
Я заметил, что это старый нить,... Используйте incron в *nix, как среды, поддерживающие inotify. Он всегда будет запускать команды при изменении файлов в каталоге. то есть,
/home/me/Code/c/that_program IN_DELETE,IN_CLOSE_WRITE ctags --sort=yes *.c
вот и все.
возможно, используйте аргумент append для ctags, как показано:
http://vim.wikia.com/wiki/Autocmd_to_update_ctags_file
Я не могу поручиться за это, поскольку я обычно использую source insight для просмотра кода, но использую vim в качестве редактора... иди разберись.
Как насчет того, чтобы ctags планировалось запускать через crontab? Если ваше дерево проектов достаточно стабильно в своей структуре, это должно быть выполнимо?
чтобы подавить запрос "нажмите enter", используйте : silent.
на OSX эта команда не будет работать из коробки, по крайней мере, не для меня.
au BufWritePost *.c,*.cpp,*.h silent! !ctags -R &
Я нашел post, который объясняет, как получить стандартную версию ctags, которая содержит параметр-R. Это само по себе не сработало для меня. Мне пришлось добавить /usr/local / bin в переменную PATH in .bash_profile для того, чтобы забрать корзину, где Homebrew устанавливает программы.
в моем opninion, плагин индексатор лучше.
http://www.vim.org/scripts/script.php?script_id=3221
Это могут быть:
1) надстройка для проекта.смола.ГЗ
2) независимый плагин
- генерация фоновых тегов (вы не ждете, пока ctags работает)
- несколько проектов, поддержанных
есть плагин vim под названием AutoTag для этого, что работает очень хорошо.
Если у вас установлен taglist, он также обновит его для вас.
The
--append
вариант действительно путь. Используется сgrep -v
, мы можем обновить только один tagged. Например, вот выдержка из неполированный плагин это решает эту проблему. (NB: для этого потребуется "внешний"плагин библиотека)" 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
этот код определяет:
^Xta
принудительно обновить базу тегов для всех файлов в текущем проекте;^Xtc
в силу обновление базы тегов для текущего (несохраненного) файла;- автокоманда, которая обновляет базу тегов при каждом сохранении файла ; и он поддерживает и много вариантов, чтобы отключить автоматическое обновление, где мы не хотим, чтобы настроить ctags вызовы в зависимости от типов файлов, ... Это не просто подсказка, а небольшой отрывок из плагина.
HTH,
Auto Tag-это плагин vim, который обновляет существующие файлы тегов при сохранении.
Я использую его в течение многих лет без проблем, за исключением того, что он обеспечивает максимальный размер файлов тегов. Если у вас нет действительно большого набора кода, индексированного в одном файле тегов, вы не должны нажимать этот предел.
обратите внимание, что Auto Tag требует поддержки Python в vim.