55

今、私は私の中に次のものを持っています.vimrc

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

これにはいくつかの問題があります。

  1. 遅い-最後のタグ生成以降に変更されていないファイルのタグを再生成します。
  2. 「Enterキーを押すか、コマンドを入力して続行する」という必然性があるため、ファイルを書き込んだ後、Enterボタンをもう一度押す必要があります。

これらの2つの問題を組み合わせると、(終了する前に)追加のEnterキーを押すのが早すぎctags -Rて、迷惑なエラーメッセージが表示され、Enterキーをもう一度押す必要があります。

大したことではないように思えますが、特定の日に行うファイルの書き込み量が多いと、非常に煩わしくなりがちです。それを行うためのより良い方法が必要です!

4

12 に答える 12

45

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

欠点は、完了するまで有用なタグ ファイルが得られないことです。*nix システムを使用している限り、前の ctags が完了する前に複数の書き込みを行っても問題ありませんが、それをテストする必要があります。Windows システムでは、バックグラウンドに置かれず、最初の ctags が終了するまでファイルがロックされていると不平を言うでしょう (vim で問題が発生することはありませんが、少し古いタグ ファイルになってしまいます)。 )。

--appendtonylo が示唆するようにオプションを使用することもできますが、無効tagbsearchにする必要があることに注意してください。これは、タグ ファイルのサイズによっては、タグの検索に時間がかかることを意味します。

于 2008-09-30T23:05:04.220 に答える
15

編集: 次の行に非常に沿ったソリューションがAutoTag vim scriptとして投稿されまし。ただし、スクリプトには Python をサポートする vim が必要であることに注意してください。

私のソリューションは代わりに 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 行で記述する必要があります。

そこでは多くのことが起こっています:

  1. この自動コマンドは、ファイルが C または C++ であることが検出されたときにトリガーされ、BufWritePostイベントによってトリガーされるバッファーローカル自動コマンドを追加します。

  2. %実行時にバッファのファイル名に置き換えられるプレースホルダーと、ファイル名をシェルクォートするために使用:gsされる修飾子を使用します (埋め込まれた単一引用符を引用符エスケープ引用符に変えることによって)。

  3. そのようにして、ファイルが存在するかどうかをチェックするシェルコマンドを実行しtagsます。その場合、保存したばかりのファイルを参照する行を除いてその内容が出力され、保存したばかりのファイルctagsだけで呼び出され、結果は次のようになります。sortして元の位置に戻します。

実装者の警告: これは、すべてが同じディレクトリにあり、それがバッファーローカルの現在のディレクトリでもあることを前提としています。パスマングリングについては何も考えていません。

于 2008-10-02T20:25:33.213 に答える
11

これを行うためにeasytags.vimを書きました: タグを自動的に更新して強調表示します。プラグインは、編集中のファイルのみを更新するか、編集中のファイルのディレクトリ内のすべてのファイルを (再帰的に) 更新するように構成できます。グローバル タグ ファイル、ファイル タイプ固有のタグ ファイル、およびプロジェクト固有のタグ ファイルを使用できます。

于 2012-01-14T23:14:58.677 に答える
7

しかし、これが古いスレッドであることに気付きました... inotify をサポートする *nix のような環境でincronを使用してください。ディレクトリ内のファイルが変更されるたびに、常にコマンドが起動されます。つまり、

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

それでおしまい。

于 2010-11-30T05:46:46.453 に答える
3

おそらく、次のように ctags に追加引数を使用します。

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

私は通常、コードの閲覧にはソース インサイトを使用しますが、エディターとしては vim を使用するため、これを保証することはできません。

于 2008-09-30T23:01:38.957 に答える
2

OSX では、このコマンドは、少なくとも私にとってはそのままでは機能しません。

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

-R オプションを含む標準の ctags バージョンを取得する方法を説明している投稿を見つけました。これだけではうまくいきませんでした。Homebrew がプログラムをインストールするビンを選択するために、/usr/local/bin を .bash_profile の PATH 変数に追加する必要がありました。

于 2011-09-01T10:45:09.150 に答える
2

ctags を crontab 経由で実行するようにスケジュールするのはどうですか? プロジェクト ツリーの構造がかなり安定している場合、それは可能でしょうか?

于 2008-09-30T22:55:34.057 に答える
2

「Enter キーを押してください」プロンプトを抑制するには、:silentを使用します。

于 2008-09-30T23:03:15.847 に答える
1

私の意見では、プラグイン Indexer の方が優れています。

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

かもね:

1) project.tar.gz のアドオン

2) 独立したプラグイン

  • バックグラウンド タグの生成 (ctags が機能するまで待つ必要はありません)
  • 複数のプロジェクトをサポート
于 2011-03-26T09:45:47.123 に答える
1

オプションは確かに--append行く方法です。と一緒に使用すると、タグ付けgrep -vされたファイルを 1 つだけ更新できます。たとえば、この問題に対処する洗練されていないプラグインの抜粋を次に示します。(注: 「外部」ライブラリ プラグインが必要になります)

" 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、

于 2008-10-01T09:01:28.357 に答える
1

これにはAutoTagと呼ばれる vim プラグインがあり、非常にうまく機能します。

taglist がインストールされている場合は、それも更新されます。

于 2011-02-10T20:22:22.623 に答える
0

自動タグは、保存時に既存のタグ ファイルを更新する vim プラグインです。

タグファイルに最大サイズを強制することを除いて、問題なく何年も使用しています。ただし、非常に大きなコード セットがすべて同じタグ ファイルでインデックス化されている場合を除き、その制限に達するべきではありません。

自動タグには、vim での Python サポートが必要であることに注意してください。

于 2011-10-26T22:15:27.570 に答える