texto - Cambiar los nombres de las variables en Vim
vim tutorial (7)
Estoy tratando de leer una gran cantidad de código c / perl a través de vim que contienen muchos nombres de variable de una sola letra.
Sería bueno tener algún comando que podría ayudarme a cambiar el nombre de una variable a algo más significativo mientras estoy en el proceso de leer el código para poder leer el resto más rápido.
¿Hay algún comando en vim que me permita hacer esto rápidamente?
No creo que las expresiones regulares funcionen porque
1) el mismo nombre de letra única podría tener diferentes propósitos en diferentes bloques de scoping
2) la misma combinación de letras podría formar parte de otro nombre var más grande, o en una cadena o comentario ... no querría modificar esos
¿Alguna solución conocida?
AFAIK, no hay soporte de refactorización real en VIM. Al hacer un cambio de nombre con la intención de un refactor, generalmente tomo las siguientes precauciones.
- Limite el alcance del cambio de mis marcas de uso.
- Al ingresar la expresión regular, corchetee el nombre con / <y>. Esto hará que coincida con una palabra completa, lo que reduce los tipos de cambio de nombre incorrectos que se producirán.
- No haga una sustitución de varias líneas para reducir las posibilidades de un mal reemplazo
- Mire atentamente el código diff si se trata de algo más que un pequeño cambio.
Mi cambio final parece algo así
:''a,''bs//<foo/>/bar
Me encantaría estar equivocado sobre que no haya una herramienta de refactorización para VIM, pero no lo he visto.
En c, es posible que pueda progresar usando cscope. Hace un intento de entender la sintaxis, por lo que tendría una posibilidad de saber cuándo la letra era una variable.
Podría usar el modificador ''c'' en la búsqueda global y reemplazar que le pediría confirmación para cada reemplazo. Tardaría más tiempo, pero podría funcionar para un archivo de código no exhaustivo:
%s//$var//$foo/gc
La c significa confirmar.
Pon esto en tu .vimrc
" Function to rename the variable under the cursor
function! Rnvar()
let word_to_replace = expand("<cword>")
let replacement = input("new name: ")
execute ''%s//(/W/)'' . word_to_replace . ''/(/W/)//1'' . replacement . ''/2/gc''
endfunction
Llámalo con :call Rnvar()
expand("<cword>")
obtiene la palabra debajo del cursor. La cadena de búsqueda usa %
para el alcance del archivo, y los patrones /(/W/)
buscan caracteres que no sean palabras en el límite de la palabra que se va a reemplazar, y los guarda en las variables /1
y /2
para volver a ser insertado en el patrón de reemplazo.
Si se trata de varios archivos, puede considerar echar un vistazo a sed. Utilice find para tomar sus archivos y xargs plus sed para reemplazarlos. Digamos que quiere reemplazar un a_better_name en todos los archivos que coincidan con * .c, podría hacer
encontrar . -name "* .c" | xargs sed -i-e ''s / a / a_better_name / g''
Tenga en cuenta que esto reemplazará TODAS las apariciones de a, por lo que es posible que desee una expresión regular más robusta.
Sé que es una vieja pregunta, y obviamente la forma de @ mykola-golubyev ES la mejor respuesta para el caso particular en la pregunta OP (que, supongo que está pasando por un código ofuscado donde es probable que tengas varios bloques con los mismos nombres var) ; pero con el nombre de la pregunta, así muchas personas que vienen aquí de las búsquedas de Google probablemente busquen maneras menos específicas de cambiar el nombre de las variables en VIM, y esas pueden ser más concisas
Me sorprende que nadie sugiriera de esta manera:
*
:s//
NEWNAME/gc
El *
es lo mismo que gn
- busca la siguiente ocurrencia de la palabra bajo el cursor Y se convierte en el último patrón buscado, por lo que cuando se omite el patrón de búsqueda en el comando de sustitución, VIM asume que este es el patrón para buscar.
Para pequeñas cantidades de var var copias, una aún más rápida:
*
cw
NEWNAME<esc>
luego repetirn.
para otras ocurrencias
Buscar ocurrencia, cw
es el comando para cambiar la palabra , n
va a la siguiente aparición para la última búsqueda y .
repite el último comando (que es cambiar palabra a NEWNAME )
(Créditos para que sepa todo esto vaya a @doomedbunnies en Reddit )
Otro truco genial es este: ( créditos a @ nobe4 )
*
cgn
NEWNAME<esc>
luego repita.
para otras ocurrencias
cgn
es "cambiar lo que sea el resultado de (encuentre la siguiente ocurrencia)". Ahora que este es el último comando, no necesita la n
para ir a la siguiente ocurrencia, por lo que hay menos trazos de nuevo y, lo que es más importante, no es necesario alternar n
.
. Pero, obviamente, este tiene el inconveniente de no tener una forma de omitir una ocurrencia.
Aquí hay algunos beneficios:
- sin mapeo, no .vimrc (o init.vim), para que pueda usarlo en cualquier copia de VIM que encuentre (por ejemplo, una tarea rápida en algún VPS o la máquina de su amigo, configurar VIM a su manera sería derrotar el propósito de ''rápido'' )
- usar
*
ogn
para seleccionar palabras es muy rápido, solo una pulsación de tecla (bueno, digamos 1.5) - el uso de
*
ogn
asegura que no haya coincidencias dentro de otras palabras, tal como lo hace:%s/<CR>//gc
.:%s//<OLDNAME/>/NEWNAME/gc
escribir a mano:%s//<OLDNAME/>/NEWNAME/gc
: Personalmente, tiendo a olvidarme de usar las/<
cosas para limitar las coincidencias a palabras completas solamente. - Si no se utiliza el alcance, solo se obtendrán unos pocos golpes de
n
para saltarse las coincidencias no deseadas, probablemente incluso menos que los trazos adicionales necesarios para limitar el alcance. En circunstancias normales, las variables probablemente estén un tanto localizadas en cierto bloque de código de todos modos.
A continuación se muestra cómo cambiar el nombre de una variable que se define en el ámbito actual {}
.
Mueva su cursor al uso variable. Presione gd
. Lo que significa que mueve el cursor a la definición. Ahora presione [{
- esto lo llevará al alcance del comienzo. Presione V
- activará la selección de línea visual. Presione %
- saltará al opuesto }
por lo tanto, seleccionará el alcance completo. Presione :s/
- inicio del comando sustituto. <CR>/
- insertará el patrón que coincida con el nombre de la variable (ese nombre estaba antes de presionar gd
). /newname/gc<CR>
- iniciará la búsqueda y reemplazará con la confirmación en cada coincidencia.
Ahora tiene que grabar una macro o incluso mejor: mapee una clave.
Aquí están las asignaciones finales:
" For local replace
nnoremap gr gd[{V%::s/<C-R>///gc<left><left><left>
" For global replace
nnoremap gR gD:%s/<C-R>///gc<left><left><left>
Pon esto en tu .vimrc
o simplemente ejecuta. Después de presionar en gr
la variable local lo llevará al comando :s
donde simplemente debe ingresar new_variable_name
y presionar Enter .