2008-09-30 3 views
52

Сейчас я следующий в моем .vimrc:Vim автоматически генерировать Ctags

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

Есть несколько проблем с этим:

  1. Это медленно - регенерирует тег для файлов, которые гавань» t с момента создания последнего тэга.
  2. Я должен нажать кнопку ввода снова после записи файла из-за неизбежного «нажмите Enter или введите команду для продолжения».

Когда вы объедините эти два вопроса, я в конечном итоге толкает дополнительный ввести слишком рано (до ctags -R закончил), то появляется сообщение об ошибке раздражает, и нужно нажать снова войти.

Я знаю, что это не похоже на большое дело, но с объемом файлов, которые я делаю в определенный день, он становится очень раздражающим. Там должен быть лучший способ сделать это!

ответ

41

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

Недостатком является то, что вы не будете иметь полезный теги файл, пока он не закончит. Пока вы находитесь в системе * nix, должно быть хорошо сделать несколько записей до того, как предыдущие ctags завершились, но вы должны проверить это. В системе Windows он не будет помещен в фоновом режиме, и он будет жаловаться на то, что файл заблокирован до тех пор, пока не закончится первый ctags (что не должно вызывать проблем в vim, но в итоге вы получите немного устаревший файл тегов).

Примечание: вы можете использовать опцию --append, как предлагает Tonylo, но тогда вам придется отключить tagbsearch, что может означать, что поиск тегов занимает намного больше времени, в зависимости от размера вашего файла тега.

+0

А ... хорошее решение. Я молчал! ctags -R и не понимал, почему ничего не происходит ... Думаю, вам нужен этот второй удар. – cdleary 2008-10-01 00:54:20

+2

В окнах вы всегда можете использовать «start ctags -R». Он запустит ctags в backgroud. – devemouse 2011-09-01 11:12:40

2

Как насчет того, что ctags планируется запустить через crontab? Если ваше дерево проектов довольно стабильно в своей структуре, это должно быть выполнимо?

+0

+1, KISS. Вот пример cronjob, который я только что создал, чтобы работать каждый день в 2:10 утра. Очевидно, вы можете иметь столько, сколько хотите. Мои параметры ctags предназначены для drupal, что, вероятно, больше, чем вам нужно. 10 2 * * * cd/var/www/yoursite/&&/usr/bin/ctags --langmap = php: .engine.inc.module.theme.install.php --php-species = cdf --languages ​​= php --recurse – roberttstephens 2012-08-09 18:50:48

3

Возможно использовать Дописывать аргумент Ctags, как показано на:

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

Я не могу ручаться за это, как я обычно используют источник знания для просмотра кода, но использовать Vim в качестве редактора .. . go рисунок.

2

Чтобы подавить запрос «нажмите ввод», используйте :silent.

1

Опция --append действительно способ пойти. Используется с grep -v, мы можем обновить только один файл с тегами. Например, вот выдержка из unpolished plugin, которая решает эту проблему.(NB: Это потребует «внешний» library plugin)

" 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 в зависимости от типов файлов, ... Это не просто подсказка, а небольшая выдержка из плагина.

НТН,

13

Edit: Раствор очень вдоль линий была размещена в AutoTag ВИМ скрипт следующее. Обратите внимание, что сценарию нужен vim с поддержкой Python.

Мое решение накладывает на awk вместо этого, поэтому оно должно работать на многих других системах.


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 

Обратите внимание, что вы можете только написать его таким образом в сценарии, в противном случае он должен идти по одной линии.

Там это много там происходит:

  1. Эта автоматическая команда запускает, когда файл был обнаружен быть C или C++, и добавляет в свою очередь буферную локального автоматического команды, который срабатывает событие BufWritePost.

  2. Он использует % заполнитель, который заменяется названием файла буфера во время выполнения, вместе с :gs модификатором, используемого для оболочки кавычки имени файла (поворачивая внедренные одинарные кавычки в кавычках-спусковой цитата кавычки) ,

  3. Таким образом, он выполняет команду оболочки, которая проверяет, существует ли tags файла, в этом случае его содержание печатаются для линий, которые ссылаются на только что сохраненный файл, за исключением, тем временем ctags вызываются только раз сохраняемых файл, и результат будет sort ed и положить обратно на место.

Разработчик Caveat: это предполагает, что все находится в одном каталоге и это также является локальным каталогом буфера. Я не думал о путях.

7

Я заметил, что это старая нить, однако ... Использование incron in * nix как окружающая среда, поддерживающая inotify. Он всегда запускает команды всякий раз, когда файлы в каталоге меняются. т.е.

/home/me/Code/c/that_program IN_DELETE,IN_CLOSE_WRITE ctags --sort=yes *.c 

Все права сохранены.

1

Для этого есть плагин vim, который называется AutoTag, который работает очень хорошо.

Если у вас есть установленный taglist, он также обновит его для вас.

1

В моем варианте, плагин Indexer лучше.

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

Это может быть:

1) надстройка для project.tar.gz

2) независимый плагин генерации

  • фона метки (у вас есть не ждать, пока работает ctags)
  • поддерживается несколько проектов
2

В OSX эта команда не будет работать из коробки, по крайней мере, не для меня.

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

Я нашел post, который объясняет, как получить версию стандарта Ctags, который содержит опцию -R. Только это не помогло мне. Мне пришлось добавить/usr/local/bin в переменную PATH в .bash_profile, чтобы забрать bin, где Homebrew устанавливает программы.

0

Auto Tag - это плагин vim, который обновляет существующие файлы тегов при сохранении.

Я использую его в течение многих лет без проблем, за исключением того, что он обеспечивает максимальный размер в файлах тегов. Если у вас нет действительно большого набора кода, все индексированные в одном файле тегов, вы не должны бить этот лимит.

Обратите внимание, что для автоматического тега требуется поддержка Python в vim.

10

Я написал easytags.vim, чтобы сделать это: автоматически обновлять и выделять теги. Плагин может быть настроен для обновления только редактируемого файла или всех файлов в каталоге редактируемого файла (рекурсивно). Он может использовать файлы глобальных тегов, файлы тегов с конкретными тегами и файлы тегов, специфичных для проекта.

Смежные вопросы