题
现在我下面的我 .vimrc
:
au BufWritePost *.c,*.cpp,*.h !ctags -R
有几个问题:
- 这是缓慢的--重新生成标记文件没有改变,因为最后一个标签的产生。
- 我必须推动按钮 再一次 之后编写的文件,因为一个不可避免的"的新闻输入或输入命令继续"。
当你把这两个问题我最终推动额外的酒太早(前 ctags -R
已完成),然后看到的令人讨厌的错误消息,并且需要推动进入一次。
我知道这听起来不像一个大问题,但与数量的文件写道我在给定的一天,它倾向于获得真的很烦人。肯定有更好的方式来做到这一点!
解决方案
au BufWritePost * .c,*。cpp,*。h silent! !ctags -R&
缺点是在完成之前你不会有一个有用的标签文件。只要您使用的是* nix系统,就可以在之前的ctags完成之前进行多次写入,但是您应该对其进行测试。在Windows系统上,它不会把它放在后台,它会抱怨文件被锁定,直到第一个ctags完成(这不应该导致vim出现问题,但你最终会得到一个稍微过时的标签文件)。
注意,您可以使用 - append
选项作为tonylo建议,但是您必须禁用 tagbsearch
,这可能意味着标记搜索需要更长时间,具体取决于标记文件的大小。
其他提示
编辑:以下几行的解决方案已发布为 AutoTag vim脚本。但请注意,脚本需要一个支持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
,然后将结果请注意,您只能在脚本中以这种方式编写它,否则它必须在一行上。
那里发生了很多事情:
当检测到文件为C或C ++时,会触发此自动命令,并依次添加由
BufWritePost
事件触发的缓冲区本地自动命令。 / p>它使用
%
占位符,该占位符在执行时被缓冲区的文件名替换,以及用于shell的:gs
修饰符 - 引用文件名(通过将任何嵌入的单引号转换为quote-escape-quote-quote)。这样它运行一个shell命令来检查是否存在
标记
文件,在这种情况下,除了引用刚刚保存的文件的行之外,它的内容是打印的,同时<仅对刚刚保存的文件调用code> ctagssort
编辑并重新放回原位。 醇>警告实现者:这假设所有内容都在同一目录中,而且它也是缓冲区本地当前目录。我没有考虑路径损坏。
\t' -k1,1 -o tags.new && mv tags.new tags
请注意,您只能在脚本中以这种方式编写它,否则它必须在一行上。
那里发生了很多事情:
-
当检测到文件为C或C ++时,会触发此自动命令,并依次添加由
BufWritePost
事件触发的缓冲区本地自动命令。 / p> -
它使用
%
占位符,该占位符在执行时被缓冲区的文件名替换,以及用于shell的:gs
修饰符 - 引用文件名(通过将任何嵌入的单引号转换为quote-escape-quote-quote)。 -
这样它运行一个shell命令来检查是否存在
标记
文件,在这种情况下,除了引用刚刚保存的文件的行之外,它的内容是打印的,同时<仅对刚刚保存的文件调用code> ctags ,然后将结果sort
编辑并重新放回原位。
醇>
警告实现者:这假设所有内容都在同一目录中,而且它也是缓冲区本地当前目录。我没有考虑路径损坏。
我写了 easytags.vim 来做到这一点:自动更新并突出显示标签。插件可以配置为仅更新正在编辑的文件或正在编辑的文件目录中的所有文件(递归)。它可以使用全局标记文件,文件类型特定标记文件和项目特定标记文件。
我注意到这是一个旧线程,但是...... 在支持inotify的* nix环境中使用 incron 。只要目录中的文件发生更改,它就会始终启动命令。即,
/home/me/Code/c/that_program IN_DELETE,IN_CLOSE_WRITE ctags --sort=yes *.c
就是这样。
或许使用ctags的append参数,如下所示:
http://vim.wikia.com/wiki/Autocmd_to_update_ctags_file
我无法保证这一点,因为我通常使用源洞察力进行代码浏览,但是使用vim作为编辑器......去图。
如何安排ctags通过crontab运行?如果你的项目树在它的结构中相当稳定,那应该是可行的吗?
禁止“按下输入”提示,请使用:沉默。
在OSX上,这个命令不会开箱即用,至少不适合我。
au BufWritePost *.c,*.cpp,*.h silent! !ctags -R &
我找到了帖子,其中介绍了如何获取包含-R选项的标准ctags版本。仅此一点对我没有用。我必须将/ usr / local / bin添加到.bash_profile中的PATH变量中,以便获取Homebrew安装程序的bin。
在我opninion,插件索引更好。
http://www.vim.org/scripts/script.php?script_id=3221
它可以是:
1)一个附加的project.tar.gz
2)一个独立的插件
- 背景下标签的产生(你还没有等待,同时ctags工作)
- 多个项目支持
有一个名为 AutoTag 的vim插件好。
如果您安装了taglist,它也会为您更新。
的 --append
选择正确的路要走。用用 grep -v
, 我们可以更新唯一一个 标记 文件。例如,这里是一个摘录的 未经雕琢的插件 解决这个问题。(注:这将需要一个"外部" 图书馆的插件)
" 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
迫的更新的标签基于目前的(未保存)的文件;- 一个autocommand更新的标签基每一次的文件是保存;它支持和许多选项,禁止自动更新,我们不想要它,以调ctags呼吁根据档案种类,...它不只是一个小,但一个小摘录的一个插件。
禾田,
Auto Tag是一个vim插件,可以在保存时更新现有的标记文件。
我已经使用它多年没有问题,除了它在标签文件上强制执行最大尺寸。除非您在相同的标记文件中编写了一组非常大的代码,否则不应达到该限制。
请注意,Auto Tag需要在vim中支持Python。