Crear automáticamente llaves coincidentes en vim


17

¿Cómo creo automáticamente llaves en vim?

Debería funcionar de la siguiente manera: si ingreso una llave abierta, la de cierre debería aparecer automáticamente y el cursor debería colocarse en el medio. Para saltar del par de llaves Ctrl-jse usa la combinación .

Hay muchos complementos que proporcionan inserción automática de llaves. Pero ellos

  • use una combinación de teclas diferente Ctrl-ja la de saltar del par de llaves o
  • interferir con las asociaciones de teclas de UltiSnips .

Lo siguiente funciona como se esperaba

:inoremap ( ()<Esc>:let leavechar=")"<CR>i
:imap <C-j> <Esc>:exec "normal f" . leavechar<CR>a

Pero con esta configuración, los fragmentos de UltiSnips ya no funcionan. Así que usé UltiSnips para insertar la llave de cierre:

inoremap ( (<C-R>=UltiSnips_Anon('($1)$0', '(')<CR>

Esto casi funciona. Se inserta el corsé correspondiente y puedo omitir el cierre con Ctrl-j. Esto, sin embargo, funciona solo si hay un espacio delante de la llave abierta.

main () // works, the closing parentheses is added
main(   // fails without a space

Mis soluciones requieren una combinación de teclas diferente para saltar sobre la llave de cierre o requieren un espacio delante de la llave abierta. ¿Cómo arreglar esto?

Nota: Usé paréntesis como ejemplo. Debería funcionar con paréntesis, llaves, corchetes y signos que no sean, y no interferir con el complemento UltiSnips.


1
¿Has probado el cierre automático ? Puede saltar de pares con ), reasignar c-ja eso podría funcionar.
Kevin

Respuestas:


4

¿Cómo creo automáticamente llaves en vim?

Este problema no es trivial, como verá. La respuesta es simple: El uso de un plugin, como autoclose o smartinput . Simplemente reasignando ingenuamente las teclas ([.. le presentará las mayúsculas y minúsculas en un par de líneas, es por eso que estos complementos están hechos y por qué generalmente son bastante complejos (si son buenos).

Así que usé UltiSnips para insertar la llave de cierre

Podría intentar esto en su lugar (que es diferente de mi sugerencia original):

inoremap ( ()<CR>=UltiSnips_Anon('$1)$0', ')')<CR>

Donde UltiSnips dividirá la línea en (lugar de incluirla mainen el partido. El problema con el uso de un complemento de fragmento para esto es que (por lo general) no admiten la anidación, por lo que olvidarán cualquier posición de salto cuando se inserte el siguiente fragmento (anidado).

Para saltar del par de llaves Ctrl-jse usa la combinación .

Puede reasignar Ctrl-jpara UltiSnips o el complemento en conflicto. Si las asignaciones no figuran en la documentación, puede usar :map/imap/nmap <key>para mostrar la asignación. Si desea Ctrl-jelegir y elegir y hacer el trabajo de ambos complementos, está solicitando:

  1. algo mucho más avanzado de lo que sospecho que podrías pensar
  2. algo que sospecho que realmente no quieres

Considere este bucle bash:

while (( ${arr1[i]} < ${arr2[i<CURSOR>]} )); do
  [next_snippet_position_marker]
done

En este caso, deberá presionar Ctrl-j5 veces para llegar al cuerpo del bucle. El uso de las llaves de cierre para saltar de un par correspondiente le brinda mucho más control sobre dónde realmente quiere que se mueva el cursor. Puede implementar una pila para realizar un seguimiento de los pares insertados y usar Ctrl-jpara hacer estallar y moverse, pero luego se encontrará con problemas si comienza a eliminar llaves manualmente sin eliminarlas de la pila. Entonces comenzará a resolver problemas que los complementos de llaves están tratando de resolver. Esta es una rueda difícil de reinventar.

Ampliando esto, puede obtener lo que inicialmente solicitó, usar Ctrl-jpara saltar de llaves y fragmentos. Si usa algún valor ficticio para representar posiciones de fragmentos y los empuja a la pila además de los corchetes de cierre, con una reasignación dinámica Ctrl-jpara corresponder a la entrega de fragmentos o llaves. Pero luego necesitará implementar algunas heurísticas bastante avanzadas para descubrir qué magia debería suceder, ya que esencialmente está asumiendo dos problemas a la vez, que actualmente están siendo resueltos por los creadores de complementos de inserción de fragmentos y complementos de coincidencia de llaves por separado, y resuelve estos problemas nuevamente, además de sus soluciones, para lograr conveniencia y, bueno, magia.

Todo se reduce a control vs conveniencia. Creo que el control le servirá mejor en este caso, lo que significa que debe mantener estos problemas y sus complementos y mapeos de teclas asociados por separado. Si aún desea conveniencia, es factible, pero es difícil.


1

Creo que delimitMate hace lo que necesitas.

Cierra automáticamente paréntesis o comillas y coloca el cursor en el medio. Para saltar de un par de paréntesis (mientras está en modo de inserción) haría Ctrl-g+ gpero puede reasignar esto Ctrl-jagregando esto a su vimrc:

% Jump out of a block of parentheses (uses delimitMate)
imap <C-j> <C-g>g

Es mejor proporcionar más detalles aquí, y usar el enlace como referencia para leer más. De esa manera, su respuesta no pierde todo su valor cuando el enlace deja de ser válido.
Anthon

1

He encontrado que el cierre automático agrega un poco de retraso y también interfiere con mi configuración (Ultisnips y Supertab), pero me gusta su enfoque de emular Eclipse CDT.

Utilizo delimitMate con los siguientes mapas para ayudar con la navegación y la sangría, tratando de obtener los mismos resultados:

imap <C-F> <C-G>g           " To jump out brackets in same line.
inoremap <C-K> <ESC>ki<TAB> " To move and insert an indent on the line before the current cursor (assuming empty line)

Lo uso de esta manera: inserte la apertura { <CR><CR><C-K>y comience a escribir en la línea interna con sangría.


Encontré que delimitMate también está agregando un ligero retraso
icc97

1

Personalmente uso smartinput para la inserción automática de corchetes y comillas. Por ejemplo, escribir en {cualquier lugar producirá {}con el cursor en el medio. Para abandonar el {grupo de corchetes, simplemente escriba }cuando esté al lado del insertado }.

Sin embargo, esto es compatible con su requisito de tabstops y saltar fuera del soporte. Tampoco crea una nueva entre sus corchetes, pero de todos modos solo necesita una clave adicional para eso <CR>.

Podrías mapear <C-J>para saltar a la siguiente línea hacia abajo:

:inoremap <C-J> <C-O>j

o si desea pasar al inicio de la siguiente línea:

:inoremap <C-J> <C-O>+

0

Algo como esto podría funcionar para usted.

inoremap {      {}<Left>
inoremap {<CR>  {<CR>}<Esc>O
inoremap {{     {
inoremap {}     {}

Lo que sugiere es un mapeo simple que no permita saltar sobre la llave de cierre.
Marco

0

En realidad, Ultisnips puede hacerlo casi perfectamente (esto puede ser nuevo). Modificando ligeramente las respuestas dadas anteriormente, tengo buen éxito con

inoremap () ()<C-R>=UltiSnips#Anon('($1)$0', '()', 'double parentheses', 'i')<CR>

Uno tiene que escribir ()cuál encuentra mejor pero que también se puede cambiar (. Luego, los argumentos opcionales adicionales para UltiSnips#Anonson una descripción y el modificador ique permite la expansión en palabras.

Saltar de los paréntesis con <c-j>obras, también anidadas dentro de otros fragmentos. Sin embargo, invocar ()paréntesis anidados parece romper esta característica, que no es gran cosa.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.