Pergunta
Agora eu tenho o seguinte no meu .vimrc
:
au BufWritePost *.c,*.cpp,*.h !ctags -R
Existem alguns problemas com isso:
- É lento -. Regenera etiquetas para arquivos que não foram alterados desde a última geração tag
- Eu tenho que apertar o botão de entrar novamente após gravar o arquivo por causa de uma inevitável "pressione Enter ou digite o comando para continuar".
Quando você combina essas duas questões que acabam empurrando o adicional entrar muito cedo (antes ctags -R
tem terminado), em seguida, a mensagem de erro irritante, e tem que empurrar entrar novamente.
Eu sei que não soa como um grande negócio, mas com a quantidade de arquivos grava I fazer em um determinado dia ele tende a ficar muito chato. Tem que haver uma maneira melhor de fazê-lo!
Solução
au BufWritePost *.c,*.cpp,*.h silent! !ctags -R &
A desvantagem é que você não vai ter um arquivo de tags úteis até completar. Enquanto você está em um sistema * nix que deve ser ok fazer várias gravações antes dos ctags anteriores foi concluída, mas você deve testar isso. Em um sistema Windows que não vai colocá-lo no fundo e ele vai se queixam de que o arquivo está bloqueado até que os primeiros CTags acabamentos (que não deve causar problemas no vim, mas você vai acabar com um arquivo de tags ligeiramente ultrapassada ).
Note, você pode usar a opção --append
como tonylo sugere, mas, em seguida, você terá que desativar tagbsearch
que poderia significar que pesquisas tag levar muito mais tempo, dependendo do tamanho do seu arquivo de tag.
Outras dicas
Editar : Uma solução muito ao longo das linhas da seguinte já foi registada como o
A minha solução conchas fora de awk vez, assim que deve funcionar em muitos mais sistemas.
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
Note que você só pode escrever desta maneira em um script, caso contrário, ele tem que ir em uma única linha.
Há muita coisa acontecendo lá:
-
Este auto-comando gatilhos quando um arquivo foi detectado a ser C ou C ++, e acrescenta, por sua vez um auto-comando tampão-local que é disparada pelo evento
BufWritePost
. -
Ele usa o espaço reservado
%
que é substituído pelo nome do arquivo do tampão em tempo de execução, juntamente com o modificador:gs
usado para shell de citar o nome do arquivo (rodando qualquer aspas simples incorporados Citação-escape-apóstrofo-apóstrofo ). -
Dessa forma, ele executa um comando shell que verifica se existe um arquivo
tags
, caso em que o seu conteúdo é impresso exceto para as linhas que se referem ao arquivo recém-salvo, entretantoctags
é invocado apenas na só- arquivo salvo, eo resultado é entãosort
ed e colocar de volta no lugar.
Caveat implementador: isso pressupõe que tudo está no mesmo diretório e que esse também é o diretório atual buffer local. Eu não dei qualquer pensamento para mangling caminho.
Eu escrevi easytags.vim para fazer exatamente isso: atualização automaticamente e as marcas de destaque. O plug-in pode ser configurado para atualizar apenas o arquivo que está sendo editado ou todos os arquivos no diretório do arquivo que está sendo editado (de forma recursiva). Ele pode usar um arquivo de tags global, tipo de arquivo arquivos de tags específicas e arquivos de tags específicas do projeto.
Tenho notado esta é uma discussão antiga, no entanto ... Use incron no * nix como ambientes de apoio inotify. Será sempre lançar comandos sempre que os arquivos em uma mudança de diretório. i.,
/home/me/Code/c/that_program IN_DELETE,IN_CLOSE_WRITE ctags --sort=yes *.c
É isso.
Talvez use o argumento de acréscimo para ctags como demonstrado por:
http://vim.wikia.com/wiki/Autocmd_to_update_ctags_file
Eu realmente não posso atestar isso como eu geralmente uso visão fonte para navegação de código, mas o uso vim como uma figura editor ... ir.
Que tal ter ctags programadas para serem executadas via crontab? Se a sua árvore do projeto é bastante estável em sua estrutura, que deve ser factível?
Para suprimir o "enter" prompt, use : silencioso.
No OSX este comando não vai funcionar fora da caixa, pelo menos não para mim.
au BufWritePost *.c,*.cpp,*.h silent! !ctags -R &
Eu encontrei um pós , que explica como obter a versão ctags padrão que contém a opção -R. Isso por si só não funcionou para mim. Eu tive que adicionar / usr / / bin local para a variável PATH no .bash_profile, a fim de pegar o bin onde Homebrew instala programas.
Na minha opninion, plugins indexador é melhor.
http://www.vim.org/scripts/script.php? SCRIPT_ID = 3221
Pode ser:
1) um add-on para project.tar.gz
2) um independente plug-in
- geração de etiquetas de fundo (você não esperar enquanto CTags obras)
- vários projetos apoiados
Há uma vim plugin chamado marca de formatação automática para este que funciona realmente bem.
Se você tem taglist instalado, ele também irá atualizar isso para você.
A opção --append
é realmente o caminho a percorrer. Usado com um grep -v
, podemos atualizar apenas um com a tag arquivo. Por exemplo, aqui está um trecho de um unpolished plug-in que resolve esse problema. (NB: Isso irá requerer um "externo" biblioteca de plug-in )
" 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
Este código define:
-
^Xta
para forçar a atualização da base de etiquetas para todos os arquivos no projeto atual; -
^Xtc
para forçar a atualização da base de etiquetas para o arquivo atual (não salvos); - um autocommand que atualiza as tags basear cada vez que um arquivo é salvo; e suporta e muitas opções para desativar a atualização automática, onde nós não queremos isso, para chamadas CTags ajustar dependendo tipos de arquivos, ... Não é apenas uma ponta, mas um pequeno trecho de um plugin.
HTH,
Tag Auto é um vim plugin que atualizações de arquivos de marca existente em Salvar.
Eu tenho usado por anos sem problemas, com a ressalva de que ele impõe um tamanho máximo dos arquivos etiquetas. A menos que você tem realmente um grande conjunto de código tudo indexado no mesmo arquivo tags, você não deve bater esse limite, no entanto.
Note que Tag Auto requer suporte Python no vim.