Saltar a la definición de función en vim

241

¿Cómo puedo saltar a una definición de función usando vim? Por ejemplo, con Visual Assist, puedo escribir Alt+ gdebajo de una función y se abre un menú contextual que enumera los archivos con definiciones.

¿Cómo puedo hacer algo así en vim?

Jon Clegg
fuente
2
GNU Global es mejor que los ctags.
Jichao
66
@Jichao, ¿puedes darnos un poco más de información sobre tu experiencia? ¿Con qué idiomas gnu global funcionó mejor para usted? ¿Hay algo más sobre el contexto en el que lo preferiste que me sea importante? ¿O tal vez lo ha usado en muchos escenarios diferentes y parece preferirlo en su mayoría / siempre? ¿Qué te gusta más? Gracias.
still_dreaming_1
@Jichao Convertí tu comentario en una respuesta wiki comunitaria. Agradecería sus cambios y aportes para esta respuesta.
still_dreaming_1

Respuestas:

213

Usa etiquetas. Genere un archivo de etiquetas y dígale a vim dónde está usando el comando: etiquetas. Luego puede saltar a la definición de la función usando Ctrl-]

Hay más trucos de etiquetas y consejos en esta pregunta .

Paul Tomblin
fuente
2
php es lo suficientemente similar a C que las "etiquetas exuberantes" deberían funcionar con él. No sé si tiene un modo python.
Paul Tomblin
55
No hay experiencia con Cscope. ¿Qué es?
Paul Tomblin el
10
La similitud con C no tiene nada que ver con el soporte de CTags PHP. Es compatible con PHP y Python. Eche un vistazo a ctags.sourceforge.net/languages.html para ver el soporte completo.
datos del
2
¿Cómo genero ctags?
dwaynemac
44
Sería genial obtener una referencia de dónde es mejor aprender cómo operar esos ctags.
Fzs2
138

Si todo está contenido en un archivo, está el comando gd (como en 'ir a la definición'), que lo llevará a la primera aparición en el archivo de la palabra debajo del cursor, que a menudo es la definición.

Scottie T
fuente
1
¿Qué pasa si no tengo la palabra debajo del cursor (prefiero escribirla)?
Fuad Saud
@FuadSaud solo búscalo usando/
LucasB
66
/Casi siempre no es preciso, ya que coincidirá con todas las ocurrencias. Descubrí que realmente puedes hacer :tag <function_name>para saltar a la definición a través de ctags.
Fuad Saud
La función @Faud Jump To Definition se basa en señalar un identificador con un cursor (en cada IDE). Escribir / buscar es otra característica, los estás confundiendo.
sangriento
101

g* hace un trabajo decente sin configurar ctags.

Es decir, el tipo g, *(o simplemente *- véase más adelante) para buscar la palabra bajo el cursor (en este caso, el nombre de la función). Luego presione npara ir al siguiente (o Shift-n para) ocurrencia anterior.

No salta directamente a la definición, dado que este comando solo busca la palabra debajo del cursor, pero si no desea lidiar con la configuración de etiquetas en este momento, al menos puede evitar tener que volver a -tipee el nombre de la función para buscar su definición.

--Editar-- Aunque he estado usando g * durante mucho tiempo, ¡recientemente descubrí dos atajos para estos atajos!

(a) *saltará a la siguiente aparición de la palabra debajo del cursor. (No es necesario escribir el gcomando 'goto' en vi).

(b) #va a la ocurrencia anterior, de manera similar.

N yn todavía funcionan, pero '#' a menudo es muy útil para comenzar la búsqueda inicialmente en la dirección inversa, por ejemplo, cuando se busca la declaración de una variable debajo del cursor.

Brent Fausto
fuente
10
La diferencia entre *y g*es el límite de palabras en la búsqueda. *realiza una \<keyword\>búsqueda (igual que \bkeyword\ben la expresión regular regular), mientras g*busca keywordsin límites de palabras.
Nicolai S
si tiene cientos de apariciones de una función en un archivo, * le llevará un promedio de 50 visitas antes de encontrar la definición.
naught101
49

Use gdo gDmientras coloca el cursor sobre cualquier variable en su programa.

  1. gd te llevará a la declaración local.
  2. gD te llevará a la declaración global.

Más opciones de navegación se pueden encontrar aquí .

Utilizar cscope para hacer referencia cruzada a proyectos grandes como el kernel de Linux.

0x90
fuente
14

Como Paul Tomblin mencionó, tienes que usar ctags . También podrías considerar usar complementos para seleccionar uno apropiado o para obtener una vista previa de la definición de la función debajo del cursor. Sin complementos, tendrá un dolor de cabeza al intentar seleccionar uno de los cientos de métodos 'doAction' sobrecargados, ya que el soporte integrado de ctags no tiene en cuenta el contexto, solo un nombre.

También puede usar cscope y su función 'buscar símbolo global'. Pero su vim debe compilarse con soporte + cscope, que no es una opción predeterminada de compilación.

Si sabe que la función está definida en el archivo actual, puede usar las teclas 'gD' en un modo normal para saltar a la definición del símbolo debajo del cursor.

Aquí está el complemento más descargado para la navegación
http://www.vim.org/scripts/script.php?script_id=273

Aquí hay uno que he escrito para seleccionar el contexto mientras salto a la etiqueta
http://www.vim.org/scripts/script.php?script_id=2507

Mykola Golubyev
fuente
Hola @ mykola-golubyev, el enlace que proporcionaste en la Detailed descriptionsección del #2507script está roto. ¿Puedes proporcionar otro por favor?
FelikZ
12

Otra técnica común es colocar el nombre de la función en la primera columna. Esto permite encontrar la definición con una simple búsqueda.

int
main(int argc, char *argv[])
{
    ...
}

La función anterior se puede encontrar /^maindentro del archivo o :grep -r '^main' *.cdentro de un directorio. Siempre que el código esté sangrado correctamente, la única vez que el identificador ocurrirá al comienzo de una línea es en la definición de la función.

Por supuesto, si no estás usando etiquetas desde este punto, ¡deberías avergonzarte de ti mismo! Sin embargo, este estándar de codificación también me parece una adición útil.

El juez Maygarden
fuente
13
¡Siempre me he preguntado por qué algunos codificadores escriben sus firmas de esa manera!
Tarrasch
Además, cuando escribe sus firmas de funciones, incluyendo '{' en la primera columna, puede moverse rápidamente a cada función presionando]] para avanzar en el archivo y [[para retroceder.
BentChainRing
12

TL; DR:

La forma moderna es usar COC para completar de forma inteligente y uno o más servidores de lenguaje (LS) para saltar a la definición (y mucho más). Para una funcionalidad aún mayor (pero no es necesaria para saltar a la definición), puede instalar uno o más depuradores y obtener una experiencia IDE completa. Inicio rápido:

  1. instale vim-plug para administrar sus complementos VIM
  2. agregue COC y (opcionalmente) Vimspector en la parte superior de ~/.vimrc:
    call plug#begin()
    Plug 'neoclide/coc.nvim', {'branch': 'release'}
    Plug 'puremourning/vimspector'
    call plug#end()
    
  3. llame :source $MYVIMRC | PlugInstallpara descargar complementos VIM
  4. reiniciar vimy llamar :CocInstall coc-marketplacepara acceder fácilmente a las extensiones COC
  5. llamar :CocList marketplacey buscar servidores de idiomas, por ejemplo:
    • escriba pythonpara encontrar coc-jedi,
    • escriba phppara buscar coc-phpls, etc.
  6. (opcionalmente) vea install_gadget.py --helplos depuradores disponibles, por ejemplo:
    • ./install_gadget.py --enable-python,
    • ./install_gadget.py --force-enable-phpetc.

Respuesta completa:

Language Server (LS) es una aplicación independiente separada (una para cada lenguaje de programación) que se ejecuta en segundo plano y analiza todo su proyecto en tiempo real exponiendo capacidades adicionales a su editor (cualquier editor, no solo vim). Obtienes cosas como:

  • finalización de etiqueta consciente del espacio de nombres
  • saltar a la definición
  • saltar al error siguiente / anterior
  • encontrar todas las referencias a un objeto
  • encontrar todas las implementaciones de interfaz
  • cambiar el nombre de todo un proyecto
  • documentación al pasar el ratón
  • Fragmentos, acciones de código, formateo, linting y más ...

La comunicación con los servidores de idiomas se realiza a través del Protocolo de servidor de idiomas (LSP). Ambos nvimy vim8(o superior) admiten LSP a través de complementos, el más popular es Conquer of Completion (COC).

La lista de servidores de idiomas desarrollados activamente y sus capacidades está disponible en el sitio web de Lang Server . No todos son provistos por extensiones COC. Si desea utilizar uno de ellos, puede escribir una extensión COC usted mismo o instalar LS manualmente y usar el combo de los siguientes complementos VIM como alternativa a COC:

La comunicación con los depuradores se realiza a través del Protocolo de adaptador de depuración (DAP). El complemento DAP más popular para VIM es Vimspector .

Language Server Protocol (LSP) fue creado por Microsoft para Visual Studio Code y lanzado como un proyecto de código abierto con una licencia MIT permisiva (estandarizada por la colaboración con Red Hat y Codenvy). Más tarde, Microsoft lanzó Protocolo de adaptador de depuración (DAP) también. Cualquier lenguaje compatible con VSCode es compatible con VIM.

Personalmente, recomiendo usar los servidores de idiomas COC + proporcionados por las extensiones COC + ALE para linting adicional (pero con el soporte LSP desactivado para evitar conflictos con COC) + Vimspector + depuradores proporcionados por Vimspector (llamados "gadgets") + siguientes complementos VIM:

call plug#begin()
Plug 'neoclide/coc.nvim'
Plug 'dense-analysis/ale'
Plug 'puremourning/vimspector'
Plug 'scrooloose/nerdtree'
Plug 'scrooloose/nerdcommenter'
Plug 'sheerun/vim-polyglot'
Plug 'yggdroot/indentline'
Plug 'tpope/vim-surround'
Plug 'kana/vim-textobj-user'
  \| Plug 'glts/vim-textobj-comment'
Plug 'janko/vim-test'
Plug 'vim-scripts/vcscommand.vim'
Plug 'mhinz/vim-signify'
call plug#end()

Puedes buscar en Google cada uno para ver qué hacen.

cprn
fuente
11

1- instala etiquetas exuberantes. Si está utilizando osx, este artículo muestra un pequeño truco: http://www.runtime-era.com/2012/05/exuberant-ctags-in-osx-107.html

2- Si solo desea incluir los ctags para los archivos en su directorio solamente, ejecute este comando en su directorio:

ctags -R

Esto creará un archivo de "etiquetas" para usted.

3- Si estás usando Ruby y deseas incluir las etiquetas de tus gemas (esto me ha sido de gran ayuda con RubyMotion y las gemas locales que he desarrollado), haz lo siguiente:

ctags --exclude=.git --exclude='*.log' -R * `bundle show --paths`

crédito: https://coderwall.com/p/lv1qww (Tenga en cuenta que omití la opción -e que genera etiquetas para emacs en lugar de vim)

4- Agregue la siguiente línea a su ~ / .vimrc

set autochdir 
set tags+=./tags;

(¿Por qué el punto y coma: http://vim.wikia.com/wiki/Single_tags_file_for_a_source_tree )

5- Ve a la palabra que te gustaría seguir y presiona ctrl + ]; si desea regresar, use ctrl+o(fuente: https://stackoverflow.com/a/53929/226255 )

Abdo
fuente
El enlace al artículo Mac mencionado está roto. Aquí está el enlace actualizado: runtime-era.blogspot.com/2012/05/… Su mejor opción es instalar ctags con una herramienta como Homebrew
ZaydH
6

A la segunda respuesta de Paul: sí, ctags (especialmente exuberante-ctags ( http://ctags.sourceforge.net/ )) es genial. También he agregado esto a mi vimrc, por lo que puedo usar un archivo de etiquetas para un proyecto completo:

set tags=tags;/
David Wolever
fuente
2

Instalar cscope. Funciona muy parecido ctagspero más poderoso. Para ir a la definición, en lugar de Ctrl+ ], haz Ctrl+ \+ g. Por supuesto, puede usar ambos simultáneamente. Pero con un gran proyecto (por ejemplo, el kernel de Linux), cscope está muy por delante.

Diptendu Roy Chowdhury
fuente
1

Después de generar ctags, también puede usar lo siguiente en vim:

:tag <f_name>

Lo anterior lo llevará a la definición de la función.

Karun
fuente