Cómo simplemente quitar llaves

8

Uno de mis amigos me dijo que puedo usar el siguiente truco para quitar un par de llaves.

Coloque el cursor dentro del par de llaves que desea eliminar.

y i {para tirar del texto entre llaves, v a {luego pegar p.

Funciona bien como:

for(int i = 0; i < s.length(); i++) {
        int index = s[i] - c;
        if(root->next[index] == NULL)
            root->next[index] = new TrieNode;
        root = root->next[index];
}

Después de ejecutar el comando:

for(int i = 0; i < s.length(); i++)
    int index = s[i] - c;
    if(root->next[index] == NULL)
        root->next[index] = new TrieNode;
    root = root->next[index];

hasta que conocí esta situación (falta el espacio antes del primer soporte rizado).

for(int i = 0; i < s.length(); i++){
        int index = s[i] - c;
        if(root->next[index] == NULL)
            root->next[index] = new TrieNode;
        root = root->next[index];
}

Después de ejecutar esos comandos, el bloque de texto se convierte en

for(int i = 0; i < s.length(); i++
        int index = s[i] - c;
        if(root->next[index] == NULL)
            root->next[index] = new TrieNode;
        root = root->next[index];
)

El área que selecciono en el modo visual parece buena, pero ¿por qué desaparecen los paréntesis?

MrDwZ
fuente
¿Estás seguro del código de muestra que publicaste? No entiendo cómo return -1;viene el. ¿También podría precisar dónde coloca el cursor antes de ejecutar cada secuencia de teclas?
statox
@statox Perdón por eso ... He corregido el último bloque y agregué una descripción sobre dónde puse el cursor. Gracias por su recomendación :-)
MrDwZ
No puedo replicar esto. yi{tira entre las llaves y vapselecciona visualmente el párrafo (el texto completo en este caso) pero no veo cómo esto cambia el texto en absoluto. ¿Estás seguro de que no estás haciendo yi{+ va{+ p?
jjaderberg
2
Acabo de intentar yi{+ va{+ pen su texto en una sesión limpia (sin vimrc, -u NONE) y eso reproduce su resultado. No estoy seguro de por qué, por ejemplo p, y Pambos dan este resultado, a pesar i{y a{characterwise en movimiento. Sería útil si pudiera a) dar un texto de ejemplo en el que su técnica funciona yb) confirmar en qué parte de su técnica ocurre el 'cambio'. @Ben indica una buena solución en su respuesta (uso ese complemento) pero no me importaría saber por qué sucede esto en primer lugar.
jjaderberg
Soy como @jjaderberg No puedo reproducir el comportamiento que describe. Dar los detalles solicitados en sus comentarios sería una muy buena idea.
statox

Respuestas:

6

Instale el complemento "envolvente" . Entonces puedes simplemente hacer d s B .

Desde la página del proyecto:

Surround.vim tiene que ver con los "alrededores": paréntesis, corchetes, comillas, etiquetas XML y más. El complemento proporciona asignaciones para eliminar, cambiar y agregar fácilmente ese entorno en pares.

El comando dsseguido de cualquier objeto de texto ( Ben este caso, para "Bloquear", como en el objeto aBo iBtexto) eliminará los caracteres circundantes que definen el objeto de texto. Por lo tanto, d s B en su caso logra lo que quería.

Otros comandos incluyen c s B b, si desea cambiar el entorno {...}en (...), o y s {cualquier movimiento del cursor o el texto objeto} B añadir que rodea {...}al texto seleccionado por el cursor.

Consulte la página del complemento y la documentación para obtener más detalles.

Ben
fuente
Esta es una buena solución. ¿Consideraría agregar una o dos oraciones que expliquen cómo funciona este complemento y por qué la asignación particular realiza la tarea?
jjaderberg
¿Hay alguna forma elegante de eliminar esas llaves sin un complemento? : (
MrDwZ
Tal vez. Pero surround es realmente ligero y uno de los complementos "esenciales". Así que bien podría instalarlo ...
Ben
6

Resumen

Es un error y hay un parche (743). El error afecta a ambos ejemplos, pero no lo ve en un caso porque el carácter que se mueve hacia abajo es un (espacio en blanco). La solución es instalar el parche, pero también hay muchas soluciones alternativas o métodos alternativos, no afectados por el error.

NB : {, }y Btodos se refieren al mismo objeto de texto: Block ( :help aB, :help iB). Si esta u otras respuestas usan un signo diferente al que se usó en la pregunta, puede ser por eso.

El bicho

No lo entiendo completamente, pero aquí hay una explicación, si alguien está interesado.

El comportamiento que ve se debe a un error mencionado por Yukihiro Nakadaira en vim_dev y su parche se publica como 7.4.743: "p" en modo Visual provoca una división de línea inesperada .

:help v_pSe supone que el modo visual put ( ) reemplaza el texto seleccionado visualmente con el texto de un registro. El fallo sucede cuando a) el registro es de tipo linewise ( :help linewise-register), pero la selección visual es de tipo characterwise y b) los extremos de selección visuales en la última columna de una línea. En su caso, si tira del Bloque interno y luego selecciona visualmente un Bloque y lo pega, el registro arrancado será en línea y la selección visual será en forma de caracteres. Podemos tirar tanto del Bloque interno como de un Bloque a registros con nombre e inspeccionar:

En

for(int i = 0; i < s.length(); i++){  
    int index = s[i] - c;  
    if(root->next[index] == NULL)  
        root->next[index] = new TrieNode;  
    root = root->next[index];  
}

hacemos

"ayi{
"bya{
:registers ab

que muestra

--- Registers ---
"a       int index = s[i] - c;^J    if(root->next[index] == NULL)^J        root->next[index] = new TrieNode;^J    root = root->next[index];^J
"b   {^J    int index = s[i] - c;^J    if(root->next[index] == NULL)^J        root->next[index] = new TrieNode;^J    root = root->next[index];^J}

y

:echo getregtype('a') " displays 'V' for linewise
:echo getregtype('b') " displays 'v' for characterwise

Para reemplazar una selección visual por caracteres con un registro lineal, las líneas que contienen el principio y el final de la selección visual deben dividirse en dos, de modo que el texto pueda insertarse en el medio. Esto generalmente funciona bien:

Ejecutando vim as vim -u NONE -U NONEy escribiendo
( a )

iaaa
bbb
ccc
ddd<Esc>ggYjlvp

resultados en

aaa
b
aaa
b
ccc

y ( b )

iaaa
bbb
ccc
ddd<Esc>ggYjvjp

en

aaa

aaa
cc
ddd

Pero cuando la selección visual de caracteres termina en la última columna de una línea (y no incluye la nueva línea /n/ ^J) algo sale mal. Tiene que ver con la posición del cursor, que de repente se desactiva en -1 y debe incrementarse especialmente, que es lo que hace el parche. Compare ( a ) con el comando <Esc>ggYjllvp, es decir, el mismo comando, excepto que mueva una columna más hacia la derecha para que el cursor esté en la última "b" de la línea. ¡El resultado es el mismo que antes!

Ahora tome el siguiente texto:

if (TIRED){
    goto bed;
} else {
    goto work;
}

Con el cursor en la segunda línea, yi{va{pfunciona bien y da

if (TIRED)
    goto bed;
 else {
    goto work;
}

El registro de arrastre sigue en línea y la selección visual en forma de caracteres, pero la selección visual ya no termina en la última columna y todo está bien.

Ejemplos de textos de la pregunta

Para los dos textos de ejemplo, donde la única diferencia es un espacio en blanco entre el cierre del paréntesis y la apertura del corchete en la primera línea, puede parecer que su comando se comporta de manera diferente, pero realmente no lo hace. En el primer caso, el que parece exitoso, debe haber un espacio en blanco al final de la primera línea una vez que se eliminan los corchetes. Ese espacio en blanco al final está en la última línea. Conyi{va{p

for(int i = 0; i < s.length(); i++) {
    int index = s[i] - c;
    if(root->next[index] == NULL)
        root->next[index] = new TrieNode;
    root = root->next[index];
}

se convierte

for(int i = 0; i < s.length(); i++)
    int index = s[i] - c;
    if(root->next[index] == NULL)
        root->next[index] = new TrieNode;
    root = root->next[index];
␣

al igual que

for(int i = 0; i < s.length(); i++){
    int index = s[i] - c;
    if(root->next[index] == NULL)
        root->next[index] = new TrieNode;
    root = root->next[index];
}

se convierte

for(int i = 0; i < s.length(); i++
    int index = s[i] - c;
    if(root->next[index] == NULL)
        root->next[index] = new TrieNode;
    root = root->next[index];
)

Soluciones

La solución sería instalar el parche, pero hay muchas otras formas de eliminar los corchetes circundantes que no sufren el error. La mejor solución es la respuesta de @Gilles, pero la más fácil puede ser seleccionar visualmente antes de tirar, para mantener el registro con carácter.

El complemento de sonido envolvente de Tim Pope es excelente, pero (al menos para mí) hace más que quitar los corchetes: une la segunda línea a la primera, elimina la sangría y mueve el cursor al comienzo de la primera línea. Esto deja una limpieza no trivial que hacer. Ingo Karkat y Luc Hermitte tienen complementos que se ocupan de los registros y el pegado (estoy seguro de que hay muchos otros) y que deberían poder hacerlo. No estoy muy familiarizado con ellos, pero creo que con los corchetes lh que podrías hacer <M-b>xpara eliminar los corchetes circundantes y para una colocación más poderosa (especialmente en modo visual) podrías mirar Reemplazar con registro y UnconditionalPaste .

La mejor manera es la que da respuesta @Gilles, [{x]}x. Es rápido, maneja bien los bloques anidados y no une líneas inapropiadamente ni ensucia con sangría. Si hay un espacio en blanco antes del corchete de apertura, puede agregar fácilmente un xcomando para eliminarlo:[{xx]}x

Otros comandos de vainilla

Una vez más, el comando más apropiado que se me ocurre es el de la respuesta de @Gilles, [{x]}xo [{xx]}x, pero aquí hay dos alternativas específicamente a la luz de este error.

Yank personaje

Dado que el error ocurre solo para el registro visual en línea sobre la selección de caracteres, y dado que es solo accidental en su bloqueo interno de Bloqueo que sea en línea, puede optar por tirarlo en su lugar. Una forma fácil es seleccionar visualmente el interior de manzana antes de tirar de ella, y para asegurarse de que la selección visual es characterwise (es decir, el uso vno V): vi{yva{p. Esta puede ser la forma más fácil porque es muy similar a cómo realiza actualmente la operación.

No uses visual put

Otros comandos, como cambiar y eliminar, no se ven afectados por este error. Puede tirar como antes, pero luego eliminar un Bloque en el registro de agujeros negros ( :help quote_) y colocar, o eliminar un Bloque y colocar desde el registro 0 ( :help quote0): yi{"_da{poyi{da{"0p

Generalidad

Finalmente, hay formas similares a la respuesta de @Gilles: mover al comienzo de un bloque, eliminar el carácter, mover al final de un bloque, eliminar el carácter, pero que son más genéricos. La única razón para usarlos sería si el "bloque" que está eliminando es excéntrico y no tiene movimientos asociados que funcionen tan bien como [{para un bloque delimitado por llaves. Existe la posibilidad de que el complemento vim-surround pueda manejar bien estos bloques excéntricos, pero dos formas vanas serían

  1. Seleccione visualmente el bloque excéntrico y salga del modo visual. El cursor está en el último carácter de la selección. Elimínelo, luego vaya al comienzo de la última selección ( :help `<) y elimine el carácter.va{<Esc>x`<x
  2. Busque hacia atrás el comienzo del bloque excéntrico y elimine el carácter, luego busque hacia el final del bloque excéntrico y elimine el carácter. ?{<CR>x/}<CR>xEsto puede no funcionar bien con bloques anidados.

Número de letras

+----+------------------------+----------------------------+------------+
|    | method                 |          command           | characters |
+----+------------------------+----------------------------+------------+
| 1. | vim-surround           | ds{                        |          3 |
| 2. | @Gilles answer         | [{x]}x                     |          6 |
| 3. | Characterwise yank     | vi{yva{p                   |          8 |
| 4. | Delete, not visual put | yi{"_da{p or yi{da{"0p     |          9 |
| 5. | Visual mark            | va{<Esc>x`<x               |          8 |
| 6. | Search                 | ?{<CR>x/}<CR>x             |          8 |
+----+------------------------+----------------------------+------------+
jjaderberg
fuente
5

Como no está pidiendo que el cursor regrese a su posición original, [{x]}xhace el trabajo. Tiene 6 caracteres de largo con dos pulsaciones, Shiftpero el principio es sencillo, por lo que es fácil de recordar.

Si desea volver a la posición original, puede usar [{x``]}x``

Gilles 'SO- deja de ser malvado'
fuente