Volver a sangrar el código mal sangrado

39

Me gusta la función de sangría inteligente de Vim, me permite crear bloques de código bien sangrados.

Copio / pego código regularmente en buffers, pero ese código a menudo está mal formateado.

Lo ideal sería "volver a procesar" el código a través del sistema de sangría inteligente.

¿Es posible tal cosa?

Por ejemplo, ¿cómo 'arreglaría' el siguiente código (un extracto de un bloque más grande? No quiero arreglar cada línea manualmente ...):

    else 
                {
                        m[c] = 5;
                Finished = true;
std::cout<<"(ID,R,E)"<<"-->"<<"("<<g[c]<<","<<r[c]<<","<<E1 <<")"<< std::endl;
std::cout << "\n"<<"finish-->" << r[c] << "\t" <<"E1-->"<< E1 <<"\n" ;
                }
        }
rolfl
fuente
1
¿Está hablando de pegar código que originalmente tenía un código mal sangrado o bien sangrado que cambia cuando lo pega en Vim?
jamessan
El código pegado está mal sangrado para empezar. Permítanme incluyo un ejemplo ....
rolfl

Respuestas:

48

Hago esto de dos maneras.

Pasta ajustada con sangría

Primero, si el código en el búfer está formateado, pero a un nivel diferente de sangría, uso en ]plugar de p, que pega el código tal como está, pero con la sangría desplazada de modo que la primera línea pegada tenga la misma profundidad que la línea I 'Lun.

Fuente de EG copiada al búfer

while (1) {
    dostuff();
}

EG resultado de pegarlo con ]p

int myfunc() {
    int i = 5; /* Cursor on this line before paste */
    while (1) {
        dostuff();
    }
 }

vim pone el while en el mismo nivel de sangría que int i. Esto es rápido, pero solo funciona si el código copiado está sangrado correctamente dentro de sí mismo.

Reformatear después de pegar

El =operador en vim reformatea el código según las reglas de formato configuradas. Para fragmentos cortos de pegado, iré al modo visual con v, seleccionaré las líneas que acabo de pegar y luego presionaré =para formatearlas.

Para pastas más grandes, aprovecho el hecho de que el cursor va a la primera línea pegada, y que vim dice algo así como "84 líneas más". Luego puedo ingresar 84==para refluir esas 84 líneas (por supuesto, sustituir 84 con el número de líneas que realmente pega).

Referencias

:help ]p para pasta de sangría ajustada

:help =cubiertas ={motion}, [count]==y {Visual}=para filtrar a través de la costumbre o incorporado reglas de sangría

John O'M.
fuente
66
Puede seleccionar muy bien el código que pegó en modo visual usando `[v`]
craigp
1
@Badger Solo para aclarar, ¿es eso backtick-bracket-v-backtick-bracket?
Phatskat
1
sí ... el área de texto se asustó por los backticks, así que no pude ponerlo en un bloque de código: P
craigp
El operador = en vim reformatea el código en función de las reglas de formato configuradas que le daría +100 si pudiera. Podría haber ahorrado días.
Wossname
1
Uso <control + R> "para pegar, de modo que no tenga que abandonar el modo de inserción. ¿Cuál es] p equivalente para <control + R>"?
A --- B
15

El =comando se puede utilizar para reindent.

Al igual que la mayoría de los comandos de modo normal, se puede aplicar a un movimiento, por lo que puede reindentificar el código recién pegado con =']. Esto reinventa desde la posición actual del cursor hasta la ']marca, que es la última línea de la pasta.

= También se puede utilizar desde el modo visual.

Otro comando útil es ]p, que pega en el mismo nivel de sangría que la línea actual. Esto puede ayudar a pegar texto sangrado correctamente, aunque a una profundidad de sangría diferente, de acuerdo con el texto circundante.

jamessan
fuente
7

El uso de =ap (mnemonic es 'formatear un párrafo') hará que vim intente formatear automáticamente el párrafo actual.

Si desea prestar mucha atención a lo que está reformateando potencialmente, es posible que le resulte más sensato y rápido usarlo vappara seleccionar visualmente el párrafo actual (que le da una indicación visual de lo que se está reformateando), seguido de =. Esto me resulta útil en archivos en los que sé que vim se formateará incorrectamente y no quiero formatear incorrectamente otras líneas.

davidlowryduda
fuente
4

Para volver a sangrar un archivo que ya está en el búfer, use gg=G: Vea Reparar sangría

Para volver a sangrar una parte de un archivo, se pueden aplicar varios límites al =filtro (por ejemplo, ==corrige solo la línea actual).

Para mantener la sangría sin cambios al pegar el texto que pueda :set pasteantes de pegar el texto en el búfer, esto evitará que vim sangra automáticamente el texto que acaba de pegar. Después de pegar cosas, puede volver a usarlas set :nopastecuando haya terminado. Ver vimdoc aquí .

Si te encuentras pegando cosas con frecuencia, sería una buena idea usar este consejo en VimWiki y configurar una tecla para alternar el "modo pegar" agregando estas líneas a tu .vimrc:

nnoremap <F2> :set invpaste paste?<CR>
set pastetoggle=<F2>
set showmode

Luego puede presionar <F2>para alternar el modo pegar. vim mostrará las palabras "PEGAR" en la línea de estado cuando el modo pegar esté activo.

Bhargav Bhat
fuente
2
Esta pregunta no se trata de pegar código con sangría, se trata de arreglar código mal sangrado.
rolfl
44
No vi el comentario que publicaste. Sin embargo, aún puede usar gg=Gpara reindentar todo el archivo.
Bhargav Bhat
@rolfl Ahí es donde generalmente empiezo en tales casos:, gg=Gluego mira las partes que vimse equivocaron.
muru
Si desea más control (o reducir la molestia repetida) considere agregar un comando automático para invocar una herramienta de formateo de código como astylecuando guarda un búfer. Vea esta pregunta en SO para los detalles.
Bhargav Bhat
2

Para volver a sangrar todo el bloque de un bloque entre corchetes o corchetes automáticamente, coloque el cursor en la misma línea donde hay un corchete e intente =%. Para cambiar el ancho de su turno, use eg :set sw=2.

Si esto no funciona como se esperaba, para disminuir la sangría manualmente ( sangría ), intente <%y repita con .(si es necesario). Usar >%para opuesto.

Asi que:

else
       {
         // some code
       }

se convierte en:

else
{
  // some code
}

Para un código específico, para volver a sangrar una o varias líneas automáticamente, intente:

  • == volver a sangrar la línea actual
  • 5== volver a sangrar 5 líneas

Para aumentar / disminuir la sangría manualmente para una o varias líneas, intente:

  • << para sangrar la línea actual por espacios de ancho de desplazamiento
  • 5<< para sangrar 5 líneas por espacios de ancho de desplazamiento
  • >> para sangrar la línea actual por espacios de desplazamiento de ancho
  • 5>> sangrar 5 líneas por espacios de desplazamiento de ancho
  • . repetir si es necesario

También puede sangrar en modo visual ( v) seleccionando texto y presionando =(sangría automática), <(sangría) o >(sangría).

Otro truco es correcta sangría de todo el archivo por: gg=G.

Si tiene pestañas en lugar de espacios, use: :retabque reemplazará todas las pestañas con espacios (consulte: ¿Cómo reemplazar pestañas con espacios? ).


Para métodos externos, puedes probar:

  • pythonTidy para reformatear el código de Python, por ejemplo:

    :%!pythonTidy
    

Relacionado:

kenorb
fuente
1

Recientemente instalé vim-pasta ( https://github.com/sickill/vim-pasta ), y eso parece mejorar la sangría del código cuando pego. El archivo README también tiene una buena discusión sobre varias estrategias de pegado de código.

Rob Warner
fuente
1

Ya hay muchas cosas cubiertas en las respuestas existentes. Simplemente me gusta agregar una asignación que uso muy a menudo para sangrar.

nnoremap <Leader>i  mzgg=G`z

He visto algunos vimrc con esto mapeado ===.

De cualquier manera, este es un gran mapeo y lo uso casi siempre, especialmente cuando pego código copiado de otro lugar.

O incluso mejor, póngalo de autocmdmanera que Vim lo sangra justo antes de escribir los cambios en el disco.

Durga Swaroop
fuente