2009-07-21 14 views
32

Utilizo el archivo de etiqueta vim C++ para la navegación usando Ctrl-]. El problema es que cada vez que se modifica algún archivo, los enlaces ya no son válidos y tengo que volver a ejecutar ctags y actualizar el archivo de etiqueta. Nuestra base de código es enorme y lleva bastante tiempo generar archivos de etiquetas.¿Cómo actualizar automáticamente el archivo de etiqueta en vim?

¿Hay alguna herramienta que actualice periódicamente el archivo de etiqueta en segundo plano? ¿Puedo configurar VIM para hacer lo mismo?

Uso gvim en Windows.

Respuesta

25

con la respuesta de Blixtor, usted tendrá que pensar un poco cuidado en el diseño de la secuencia de comandos. Recomiendo segregar el diseño de manera que Autocommand utilice el comando "start" de Windows o similar para ejecutar un script externo en el fondo: evitando así que Vim no responda mientras se genera el archivo de etiqueta.

Ese guión podría entonces generar el archivo de etiquetas utilizando un nombre de archivo diferente (es decir, no "tags": ctags -R -o newtags .) y, cuando ctags es completa, eliminar y cambiar el nombre tagsnewtags a tags. Esto evitará que el archivo de etiqueta no esté disponible en Vim mientras se completa la generación.

+2

puntos adicionales importantes! – Blixtor

+0

@AI, ¿hay una solución similar para Linux? – Rafid

+0

Para Linux, imagino que podrías ejecutar el comando con & para llevarlo al fondo, ¿no? –

9

Una idea:

autocommands uso Vim (: ayuda AutoCommand) para activar funcionamiento de un guión cada vez que un tampón se guarda utilizando el evento BufWritePost.

Este script se inicia la generación ctags y contiene alguna pequeña lógica adicional para no correr mientras que ya está corriendo (o para funcionar en la mayoría de cada 10 minutos, etc.).

Editar:

Algo similar fue preguntado aquí con anterioridad, ver Vim auto-generate ctags

1

Esta lógica funciona para la mayoría de los casos: Cuando se abre un nuevo archivo en vim, cambie al directorio de ese archivo y generar un archivo de etiquetas de allí si no existe ya. Al guardar un tampón cambiado, generar un archivo de etiquetas en el directorio del archivo que se guarda:


function! GenerateTagsFile() 
    if (!filereadable("tags")) 
    exec ":!start /min ctags -R --c++-kinds=+p --fields=+iaS --extra=+q --sort=foldcase ." 
    endif 
endfunction 

" Always change to directory of the buffer currently in focus. 
autocmd! bufenter *.* :cd %:p:h 
autocmd! bufread *.* :cd %:p:h 

" Generate tags on opening an existing file. 
autocmd! bufreadpost *.cpp :call GenerateTagsFile() 
autocmd! bufreadpost *.c :call GenerateTagsFile() 
autocmd! bufreadpost *.h :call GenerateTagsFile() 

" Generate tags on save. Note that this regenerates tags for all files in current folder. 
autocmd! bufwritepost *.cpp :call GenerateTagsFile() 
autocmd! bufwritepost *.c :call GenerateTagsFile() 
autocmd! bufwritepost *.h :call GenerateTagsFile() 
+0

es posible que desee utilizar: call system() en su lugar, de esa manera sería portátil, puede obtener cualquier salida a través de 'let l: lines = system ("cmdline")' y el código de retorno es devuelto en v: shell_error. – osirisgothra

18

escribí el vim-easytags plug-in para hacer exactamente esto. Inicializo mi archivo de etiquetas una vez escaneando un proyecto completo (usando el comando :UpdateTags **/*.[hc] por ejemplo) y luego el complemento actualizará automáticamente el archivo de etiquetas mientras edito y :update mis archivos de código fuente en Vim. Mientras actualiza el archivo de etiquetas, bloqueará Vim, pero como solo escanea el archivo actual, no tarda mucho.

Actualización (2014-07-30): Todavía trabajando en el complemento vim-easytags :-). Hoy en día es compatible con un modo asincrónico para evitar el bloqueo de Vim. En el momento en que escribo esto, el modo asíncrono no es el modo predeterminado todavía, pero después de un poco más de retroalimentación probablemente cambie el modo predeterminado.

+0

Hmmm edit from the future. (Mientras estoy aquí ...) ¿cómo se compara esto con [AutoTag] (http://www.vim.org/scripts/script.php?script_id=1343). – FDinoff

+0

@FDinoff: AutoTag parece mucho más simple, por lo que un factor de diferenciación es la completitud/configurabilidad/complejidad. Otra diferencia es que vim-easytags puede actualizar * y resaltar * etiquetas, mientras que AutoTag parece enfocarse solo en la parte de actualización. Además, AutoTag requiere Python, mientras que vim-easytags puede funcionar sin él. – xolox

+0

"Este complemento crea automáticamente un archivo de etiquetas globales y lo mantiene actualizado a medida que edita los archivos en Vim". ¿Cómo puedo mantener etiquetas separadas para diferentes proyectos en lugar de solo uno global? @xolox – Tmx

10

ya había escrito un plugin para hacer todo el trabajo duro con ctags: Indexer.

Proporciona indolora generación de etiquetas automáticas para todo el proyecto (s) y mantiene las etiquetas de arriba-hasta la fecha. Las etiquetas se generan en el fondo, por lo tanto, no tiene que esperar mientras ctags genera etiquetas. Puede usarlo de manera independiente o como un complemento para otro complemento project.tar.gz.

En la primera forma, se puede declarar sus proyectos en ~/.indexer_files así:

[CoolProject] 

/home/user/cool_project 

[AnotherProject] 
option:ctags_params = "--languages=c++" 

/home/user/another_project/src 
/home/user/another_project/lib 

Y luego, cuando se abre cualquier archivo desde /home/user/cool_project, todo este proyecto será indexado por ctags. Cuando abre etiquetas de otro proyecto, las etiquetas también se generan. Las etiquetas de diferentes proyectos nunca se mezclan. Cuando guarda el archivo del proyecto, las etiquetas se actualizan de manera silenciosa. No tiene que preocuparse por eso, simplemente funciona.

Para obtener información detallada, consulte el artículo: Vim: convenient code navigation for your projects, que explica exhaustivamente el uso de Indexer + Vimprj.

Se probó con éxito en Vim 7.3, en los siguientes sistemas:

  • Archlinux

  • Ubuntu 10.4

  • Windows XP

  • Mac OS X Lion

1

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

function! DelTagOfFile(file) 
    let fullpath = a:file 
    let cwd = getcwd() 
    let tagfilename = cwd . "/tags" 
    let f = substitute(fullpath, cwd . "/", "", "") 
    let f = escape(f, './') 
    let cmd = 'sed -i "/' . f . '/d" "' . tagfilename . '"' 
    let resp = system(cmd) 
endfunction 

function! UpdateTags() 
    let f = expand("%:p") 
    let cwd = getcwd() 
    let tagfilename = cwd . "/tags" 
    let cmd = 'ctags -a -f ' . tagfilename . ' --c++-kinds=+p --fields=+iaS --extra=+q ' . '"' . f . '"' 
    call DelTagOfFile(f) 
    let resp = system(cmd) 
endfunction 
autocmd BufWritePost *.cpp,*.h,*.c call UpdateTags() 
Cuestiones relacionadas