Refactorización en Vim

99

Por supuesto, el hecho de que pueda refactorizar en IDE no tiene precio para muchos, casi nunca lo hago cuando estoy codificando, pero puedo intentar hacerlo cuando edito la fuente de otra persona. ¿Cómo logra una tarea tan trivial en varios archivos en Vim?

Encontré este complemento para refactorizar Ruby, pero ¿qué tal "cualquier" idioma?

Helmut Granda
fuente
2
La refactorización es muy específica del idioma. Debe buscar complementos específicos para cada idioma que le interese. Es de suponer que encontrará complementos para algunos y no para otros. Si hay uno que desea y no puede encontrar, entonces, si se siente ambicioso, puede intentar escribir uno, utilizando un complemento existente para otro idioma similar como punto de partida.
Steve Jorgensen
2
VIM está diseñado para editar archivos individuales, y tal vez archivos en un directorio, no proyectos . Muchas refactorizaciones compatibles con IDE afectarán a los archivos de todo el proyecto (por ejemplo, cambiar el nombre de una clase). Creo que sería complicado hacer esto "bien" con un editor como (g) VI (m), hasta el punto en que creo que una empresa o un gran proyecto tendría que asumirlo. Básicamente, tendrían que analizar cada idioma para evitar hacer sustituciones simples de cadenas y volverse propensos a errores (ctags proporciona algo de esto), así como los tipos de proyectos correspondientes (para saber qué archivos editar).
Merlyn Morgan-Graham
1
Gracias por los comentarios, creo que aquí es donde las cosas comienzan a complicarse y tratar de convertir VIM en un IDE no es una solución elegante para usar un solo programa para editar varios idiomas. Realmente no quiero renunciar a VIM debido a que algunas de las funciones "avanzadas" están disponibles en los IDE.
Helmut Granda
@ MerlynMorgan-Graham: algunas personas simplemente guardan su código en unos pocos archivos (grandes, eso puede ser). Evita este problema por completo.
Torre
7
@ldigas: Eso solucionaría el problema. Pero va bastante en contra de las prácticas recomendadas para algunos lenguajes (por ejemplo, Java). Básicamente, el código se dobla para adaptarse a las necesidades de la herramienta, cuando realmente debería ser al revés.
Merlyn Morgan-Graham

Respuestas:

78

Estoy de acuerdo con el paradigma 'Vim no es un IDE'. Pero hay ocasiones en las que no existe un IDE. Esto es lo que uso en esas situaciones:

: grep,: vimgrep,: Ag,: Ggrep

La refactorización que tiene más que ver con los reemplazos regulares que suelo usar : grep en mi árbol de proyectos y luego grabar una macro para hacer la refactorización -: g y: s no son ideas para pensar. Por lo general, me permitirá modificar rápidamente una gran cantidad de archivos con muy poco esfuerzo. Honestamente, uso este método más que cualquier otro.

Dependiendo de su flujo de trabajo, los comandos integrados pueden ser lentos / inconvenientes. Si usa git, entonces querrá usar el excelente complemento Fugitive y su :Ggrepcomando para buscar solo archivos registrados en git. También me gusta el Silver Searcher por su rapidez.

: argdo,: cdo y: bufdo

: cdo y : argdo son útiles para ejecutar comandos vim sobre un conjunto de archivos.

línea de comando

Cuando es más difícil determinar la lista de archivos que necesitan cambios :vimgrep, recurro a los comandos grep / find de la línea de comandos para seleccionar más de cerca la lista de archivos que necesito refactorizar. Guarde la lista en un archivo de texto y use :eun mashup de grabaciones de macros para realizar los cambios que necesito hacer.

Encuentro que cuanto menos oxidado mantengo mis habilidades de grabación de macros, más útil encuentro a Vim para refactorizar: sentirme cómodo guardando / restaurando registros, incrementando / decrementando las variables del contador de registro, limpiando / guardando grabaciones de macros en un archivo para su uso posterior, etc.


Actualizar

Desde que escribí esto, se han publicado más videocasts de los métodos que describo en vimcasts.org (¡te animo a que veas TODOS los Vimcasts! ). Para refactorizar, mira estos:

Vimgolf también es una excelente forma de practicar.

La ubicuidad de los servidores de protocolo de servidor de idiomas desde que escribí esta respuesta también ha aportado cierta capacidad de refactorización a Vim (y a otros editores). En mi opinión, están muy lejos de igualar la capacidad de las capacidades de refactorización que vería en un IDE especialmente diseñado (los uso y prefiero coc y ALE). ¡Vea otras respuestas a esta pregunta para obtener más información!

dsummersl
fuente
12
La refactorización es MUCHO más que la coincidencia de patrones, por eso se necesitan IDE para automatizar esto de manera segura. Obviamente, puedes hacerlo manualmente, pero considerando las opciones disponibles, y que la mayoría de las veces es más seguro hacerlo manualmente, ¿por qué considerarías otra opción?
Cutberto Ocampo
1
@CutbertoOcampo Estoy de acuerdo contigo hasta cierto punto: dependiendo de la miríada de aspectos de un proyecto (estructura, idioma (s), habilidades y recursos del personal, por nombrar algunos), PUEDE haber una gran herramienta de refactorización aplicable a tu problema. Mi respuesta se aplica a situaciones en las que eso no es cierto y desea abordar el problema en Vim.
dsummersl
2
eso está bien, entiendo que las personas pueden sentirse más cómodas haciendo cosas usando sus herramientas preferidas desde hace mucho tiempo, y que hay algunos trucos que pueden funcionar realmente bien, probablemente mejor que cualquier IDE, pero para un -Solución de caja Yo diría que un IDE real funcionaría mejor para la mayoría de los usuarios. Estaría pensando en una situación del 80-20% (aún más, con el saldo a favor del IDE).
Cutberto Ocampo
1
Hay un ide para prácticamente todos los idiomas. Intentar refactorizar con vim o regex suena absolutamente loco. ¿Por qué lo intentarías?
Rollos del
1
@rolls para ser lo suficientemente potente como para agarrar la máquina necesitada de un colega aleatorio con not-your-ide o cualquier cfg con el que solo pueda vivir y dejar una buena impresión (no por "solo impresión" sino por reputación y posición futura).
sangriento
24

Protocolo de servidor de idiomas (LSP)

El protocolo del servidor de idiomas contiene la función para el cambio de nombre inteligente de símbolos en un proyecto:

https://microsoft.github.io//language-server-protocol/specifications/specification-3-14/#textDocument_rename

Por ejemplo, el siguiente servidor de idioma lo admite:

Puede encontrar más servidores de idiomas en https://langserver.org/ .

Empuje

Es necesario un cliente de editor de vim para usarlos dentro de vim. Existen las siguientes opciones:

  1. LanguageClient-neovim (requiere óxido) sugiere el mapeo:

    nnoremap <silent> <F2> :call LanguageClient_textDocument_rename()<CR>
    
  2. coc.nvim (requiere node.js) sugiere la asignación:

    " Remap for rename current word
    nmap <leader>rn <Plug>(coc-rename)
    
  3. Ale tiene

    nnoremap <silent> <Plug>(ale_rename) :ALERename<Return>
    

    Ale no define ninguna combinación de teclas. Esto debe hacerlo el usuario.

  4. vim-lsp proporciona el siguiente comando

    :LspRename
    

    Similar a Ale, no se sugiere ningún mapeo. Sin embargo, por supuesto, puede definir uno de la siguiente manera

    nmap <leader>r <plug>(lsp-rename)
    

    ( <leader>rdebe ser reemplazado por su elección; no sé uno con el que estén de acuerdo la mayoría de los complementos)

  5. vim-lsc tiene una asignación predeterminada:

    'Rename': 'gR'
    

Consulte también YouCompleteMe, que también facilita los LSP.

Neovim

Neovim tiene soporte incorporado inicial para lsp desde el 13.11.2019

Consulte las configuraciones comunes de los LSP https://github.com/neovim/nvim-lsp

Sin embargo, no pude entender cómo funciona el cambio de nombre inteligente. Si alguien sabe esto, actualice esta sección.

Otras refactorizaciones

No sé si hay planes para que el protocolo LSP admita refactorizaciones más complejas, como cambiar la estructura de clases, agregar parámetros a métodos / funciones o mover un método a una clase diferente. Para obtener una lista de refactorizaciones, consulte https://refactoring.com/catalog/ .

Hotschke
fuente
Desafortunadamente, el soporte para la refactorización en el LSP es actualmente bastante débil en comparación con el estado del arte. github.com/Microsoft/language-server-protocol/issues/61
Mickael
AFAIK que el cambio de nombre coc-renamesolo funciona en el búfer actual. No actualizó el uso del nombre exportado globalmente en el proyecto (entre archivos).
oligofren
16

Pitón

Para el lenguaje Python , los siguientes complementos proporcionan capacidades de cambio de nombre 'inteligentes' para vim:

  • jedi-vim( github )<leader>r
  • ropevim( github )CTRL-c r r
  • python-mode( github ):h pymode-rope-refactoring
Hotschke
fuente
13

Familia C

  1. Pruebe el complemento Clighter para cambiar el nombre de la familia c. Se basa en clang, pero existen limitaciones y el complemento está marcado como obsoleto.

    El mapeo sugerido por Clighter es

     nmap <silent> <Leader>r :call clighter#Rename()<CR>
    

    Tenga en cuenta que el complemento sucesor clighter8 ha eliminado la funcionalidad de cambio de nombre en el compromiso 24927db42 .

  2. Si usa neovim, puede echar un vistazo a la abrazadera del complemento . Sugiere

     nmap <silent> <Leader>r :call ClampRename()<CR>
    
BB Chung
fuente
5

Escribí este complemento para la refactorización genérica. Todavía requiere muchas mejoras. En algún momento en el futuro intentaré abandonar ctags a favor de clang para refactorizaciones de C & C ++.

Luc Hermitte
fuente
4

Quizás no sea la solución más elegante, pero la encontré muy útil: uso ECLIM para conectar VIM y Eclipse. Por supuesto, toda la edición de mi código fuente se realiza en VIM, pero cuando llega el momento de refactorizar, uno puede aprovechar las capacidades superiores de Eclipse en este asunto.

Darle una oportunidad.

fjrg76
fuente
4

Plugin YouCompleteMe (YCM) (20k estrellas en GitHub)

http://ycm-core.github.io/YouCompleteMe/#the-refactorrename-new-name-subcommand

:h RefactorRename-new-name

En los tipos de archivos admitidos, este comando intenta realizar un cambio de nombre semántico del identificador debajo del cursor. Esto incluye el cambio de nombre de declaraciones, definiciones y usos del identificador, o cualquier otra acción apropiada para el idioma. El comportamiento específico está definido por el motor semántico en uso.

De forma similar FixIt, este comando aplica modificaciones automáticas a sus archivos de origen. Las operaciones de cambio de nombre pueden implicar cambios en varios archivos, que pueden estar abiertos o no en los búferes de Vim en ese momento. YouCompleteMe se encarga de todo esto por ti. El comportamiento se describe en la siguiente sección.

Compatible con tipos de archivo: c, cpp, objc, objcpp, cuda, java, javascript, mecanografiado, rust, cs

Por defecto no hay mapeo.

Hotschke
fuente
Entonces, por ahora, ¿esto solo funciona para javascript, mecanografiado y java?
SR
3

Plugin Factorus

Hay otro complemento de vim dedicado a la refactorización llamado factorus que está disponible en github .

Actualmente (2017-12), admite los idiomas

  • C,
  • java y
  • pitón.
Hotschke
fuente
2

Coloque el cursor en el nombre para refactorizar y escribir

gd(o gDsi está refactorizando una variable global).

Luego

cgn nuevo nombre esc

y

. una o más veces para refactorizar la próxima (s) ocurrencia (s)

o

:%norm . para refactorizar todas las apariciones en el búfer a la vez.

Geremia
fuente
1

Escribo mucho código C / C ++ en vim. La refactorización más común que hago es cambiar el nombre de las variables, los nombres de las clases, etc. Por lo general, utilizo :bufdo :%s/source/dest/gpara hacer una búsqueda / reemplazo en archivos, que es casi lo mismo que el cambio de nombre proporcionado por los IDE grandes.
Sin embargo, en mi caso, descubrí que generalmente cambio el nombre de entidades similares, deletreadas en diferentes casos (es decir, CamelCase, snake_case, etc.), así que decidí escribir una pequeña utilidad para ayudar con este tipo de búsqueda de "casos inteligentes" / reemplazar, está alojado aquí . Es una utilidad de línea de comandos, no un complemento para vim, espero que le resulte útil.

dkrikun
fuente
0

Para la refactorización, si está utilizando Unite (y debería hacerlo), puede utilizar vim-qfreplace y hacerlo extremadamente fácil. Mira este video que demuestra cómo funciona. Una vez que su flujo de trabajo está configurado, puede hacer algunas asignaciones para optimizarlo (en lugar de escribir la mayoría de las cosas como en el video).

BenC
fuente
0

Una combinación de dos complementos: vim-ripgrep , para buscar archivos y colocar los resultados en la ventana de corrección rápida, y quickfix-reflector para guardar los cambios directamente en la ventana de corrección rápida y guardar automáticamente cada cambio en los archivos.

Jason
fuente
0

Consideraría usar la versión spacemacs de emacs. Utiliza los mismos modos y la mayoría de las pulsaciones de teclas que Vim, pero tiene muchos más complementos debido a su naturaleza lisp. Si desea programar en C ++, simplemente agregue la capa c ++ y la mayor parte del IDE ya está configurado para usted. Para otros lenguajes interpretados como python o bash, no es necesario dejar spacemacs para usarlos. Incluso tienen una forma de ejecutar bloques de código directamente dentro de su texto, lo que funciona de manera fantástica para la programación alfabetizada o la programación reproducible donde el código y los datos están en el mismo archivo. Ambos hechos como texto.

Spacemacs es mucho más pesado en su carga inicial, pero las cosas adicionales que puede hacer con él valen la pena los pocos segundos del costo de inicio. Vale la pena echarle un vistazo al modo de organización de una capa. Es el mejor esquema, programador, temporizador diario / lista de tareas que he usado.

C. Kelly Osborn
fuente
0

Vamos

  1. La herramienta godoctor ( github ) admite varias capacidades de refactorización
  • Rebautizar
  • Función de extracción
  • Extraer variable local
  • Alternar var ⇔: =
  • Agregar talones de Godoc

Hay un complemento de vim https://github.com/godoctor/godoctor.vim que los hace disponibles

Con el cursor en la cosa para cambiar el nombre:

:Rename <newname>

Destacando bloque para extraer:

:Refactor extract newfunc
  1. vim-go

    • Cambio de nombre preciso y seguro de tipos de identificadores con :GoRename.
  2. Servidor de idiomas gopls

Hotschke
fuente