Подтвердить что ты не робот

Vim автоматически генерирует ctags

Сейчас у меня есть следующее в .vimrc:

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

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

  • Он медленный - регенерирует теги для файлов, которые не изменились с момента создания последнего тэга.
  • Мне нужно нажать кнопку ввода еще раз после записи файла из-за неизбежного "нажмите Enter или введите команду для продолжения".

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

Изменить. Решение, очень похожее на следующие строки, было опубликовано как AutoTag vim script. Обратите внимание, что script требуется 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

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

Там происходит много событий:

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

  • Он использует placeholder %, который заменяется именем файла буферов во время выполнения вместе с модификатором :gs, используемым для shell-quote filename (путем превращения любых встроенных одиночных кавычек в escape-код цитаты -quote кавычка).

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

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

Ответ 3

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

Ответ 4

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

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

Что это.

Ответ 5

Возможно, используйте аргумент append для ctags, как показано на рисунке:

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

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

Ответ 6

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

Ответ 7

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

Ответ 8

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

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

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

Ответ 9

Опция --append действительно способ. При использовании grep -v мы можем обновить только один файл с тегами. Например, вот фрагмент неполированного плагина, который решает эту проблему. (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 в зависимости от типов файлов,... Это не только подсказка, но и небольшой фрагмент плагина.

НТН,

Ответ 10

Существует плагин vim, называемый AutoTag, который работает очень хорошо.

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

Ответ 11

В моем опыте лучше использовать плагин Indexer.

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

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

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

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

  • генерация фоновых тегов (вы не ждете, пока работает ctags)
  • поддержка нескольких проектов

Ответ 12

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

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

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