vim autocomplete ctags

Vim autogenerar ctags



autocomplete (12)

¿Qué hay de tener ctags programados para ejecutarse a través de crontab? Si el árbol de su proyecto es bastante estable en su estructura, ¿debería ser factible?

En este momento tengo lo siguiente en mi .vimrc :

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

Hay algunos problemas con esto:

  1. Es lento: regenera etiquetas para archivos que no han cambiado desde la última generación de etiquetas.
  2. Tengo que presionar el botón Enter nuevamente después de escribir el archivo debido a una inevitable "presione Entrar o escriba el comando para continuar".

Cuando combinas estos dos problemas, termino presionando la ctags -R adicional para ingresar demasiado pronto (antes de que ctags -R haya terminado), luego ver el mensaje de error molesto, y tener que presionar enter nuevamente.

Sé que no suena como un gran problema, pero con la cantidad de escrituras de archivo que hago en un día determinado, tiende a ser realmente molesto. ¡Debe haber una mejor manera de hacerlo!


Auto Tag es un complemento de vim que actualiza los archivos de etiquetas existentes al guardar.

Lo he estado utilizando durante años sin problemas, con la excepción de que impone un tamaño máximo en los archivos de etiquetas. A menos que tenga un gran conjunto de códigos indexados en el mismo archivo de etiquetas, no debería alcanzar ese límite.

Tenga en cuenta que Auto Tag requiere soporte de Python en vim.


En OSX este comando no funcionará de la caja, al menos no para mí.

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

Encontré una post que explica cómo obtener la versión estándar de ctags que contiene la opción -R. Esto solo no funcionó para mí. Tuve que agregar / usr / local / bin a la variable PATH en .bash_profile para recoger el contenedor donde Homebrew instala los programas.


En mi opinión, el plugin Indexer es mejor.

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

Puede ser:

1) un add-on para project.tar.gz

2) un plugin independiente

  • generación de etiquetas de fondo (no has esperado mientras funciona ctags)
  • proyectos múltiples apoyados

Escribí easytags.vim para hacer esto: actualizar y resaltar automáticamente las etiquetas. El complemento se puede configurar para actualizar solo el archivo que se está editando o todos los archivos en el directorio del archivo que se está editando (recursivamente). Puede utilizar un archivo de etiquetas globales, archivos de etiquetas específicas de tipos de archivos y archivos de etiquetas específicas de proyectos.


Hay un complemento vim llamado AutoTag para esto que funciona realmente bien.

Si tiene taglist instalado, también lo actualizará por usted.


La opción --append es de hecho el camino a seguir. Usado con grep -v , podemos actualizar solo un archivo etiquetado . Por ejemplo, aquí hay un extracto de un complemento no pulido que aborda este problema. (NB: requerirá un complemento de biblioteca "externo")

" 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 forzar la actualización de la base de etiquetas para todos los archivos en el proyecto actual;
  • ^Xtc para forzar la actualización de la base de etiquetas para el archivo actual (no guardado);
  • un autocomando que actualiza la base de etiquetas cada vez que se guarda un archivo; y admite y muchas opciones para deshabilitar la actualización automática donde no la queremos, para sintonizar llamadas ctags según los tipos de archivos, ... No es solo un consejo, sino un pequeño extracto de un complemento.

HTH,


Me he dado cuenta de que este es un hilo viejo, sin embargo ... Use incron en * nix como entornos que soportan inotify. Siempre lanzará comandos cuando cambien los archivos en un directorio. es decir,

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

Eso es.


Para suprimir el mensaje "presionar enter", use :silent .


Tal vez use el argumento adjuntar a ctags como lo demuestra:

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

Realmente no puedo responder a esto, ya que generalmente uso la información de origen para la exploración de código, pero uso vim como editor ... imagínense.


Editar : una solución muy similar a la siguiente se ha publicado como la AutoTag comandos AutoTag vim . Sin embargo, tenga en cuenta que el script necesita un vim con soporte de Python .

Mi solución se lanza a awk en su lugar, por lo que debería funcionar en muchos más 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

Tenga en cuenta que solo puede escribirlo de esta manera en un script; de lo contrario, tiene que ir en una sola línea.

Están sucediendo muchas cosas allí:

  1. Este comando automático se desencadena cuando se detecta que un archivo es C o C ++, y agrega a su vez un BufWritePost local del búfer que se desencadena por el evento BufWritePost .

  2. Utiliza el marcador de posición % que se reemplaza por el nombre del archivo en el momento de la ejecución, junto con el modificador :gs utilizado para citar el nombre del archivo (convirtiendo cualquier comilla simple incrustada en quote-escape-quote-quote).

  3. De esta forma ejecuta un comando de shell que verifica si existe un archivo de tags , en cuyo caso se imprime su contenido, excepto las líneas que hacen referencia al archivo que acaba de guardar, mientras que ctags se invoca solo en el archivo que acaba de guardar, y el resultado luego se sort y vuelve a colocar en su lugar.

Implementador de advertencias: supone que todo está en el mismo directorio y que también es el directorio actual del buffer-local. No he pensado en el cambio de ruta.


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

El inconveniente es que no tendrá un archivo de etiquetas útil hasta que se complete. Mientras esté en un sistema * nix, debería estar bien hacer múltiples escrituras antes de que las ctags anteriores se hayan completado, pero debe probar eso. En un sistema Windows no lo pondrá en segundo plano y se quejará de que el archivo está bloqueado hasta que finalicen los primeros ctags (lo que no debería causar problemas en vim, pero terminarás con un archivo de etiquetas un poco desactualizado). )

Tenga en cuenta que puede usar la opción --append como sugiere tonylo, pero luego deberá deshabilitar tagbsearch que podría significar que las búsquedas de etiquetas tardan mucho más, según el tamaño de su archivo de etiqueta.