¿Cómo puedo mapear d [cuenta] d?

18

Nota: este no es un duplicado de ¿Cómo funciona el comando "d3fg"? ¡Léalo antes de votar para cerrar!

Llegué a un punto muerto en mi búsqueda para que las pequeñas eliminaciones funcionen como las grandes . El problema que tengo es que no puedo entender cómo reasignar comandos como d3d. De hecho, ni siquiera puedo entender cómo funcionan en primer lugar, ni encontrar ninguna mención de ellos en la ayuda de Vim. *

d3jes sencillo: aplica el doperador al 3jmovimiento,

3ddtambién es sencillo: ejecuta el ddcomando con un "conteo" de 3.

d3d parece que debería ser sencillo, aplica el doperador a ... pero ¿qué es 3d? No es una moción. Si escribe 3dsolo, Vim lo trata como un recuento seguido de un operador, y espera pacientemente por más información.

Y no puede aplicar operadores a otros operadores. ddno se describe en la ayuda como una secuencia de dos operadores. Es un comando separado de dos teclas. (cf. dc, que no hace nada)

Tampoco parece ser que el posicionamiento del conteo sea flexible para comandos que requieren dos pulsaciones de teclas: 2gjmueve el cursor hacia abajo dos líneas de pantalla, pero g2jdescarta las dos primeras pulsaciones de teclas por completo y mueve el cursor una línea hacia abajo.

¿Entonces, cómo funciona? ¿Es este un caso especial en el código interno de Vim? ¿Hay alguna forma de crear un d[count]dmapeo?

EDITAR : ¿Es un objeto de texto? :h text-objectsno lo incluye en la lista de "comandos de selección de objetos de texto", pero incluye dd en una lista de eliminaciones "agrupadas de objetos pequeños a grandes". Y d2awborra la palabra debajo del cursor y la siguiente. Por otro lado, c2dno hace nada.

* Estoy seguro de que debe existir alguna mención de ellos, pero no puedo encontrarlo. He leído :help deleting, :help motion.txty probado :helpgrep dNdpara todos los valores de N de 1-9 .

Rico
fuente
2
Creo que el último dactúa como una confirmación; Entonces es lo mismo que d3<CR>. y3yy c3ctambién funciona igual ... No puedo encontrar ningún documento sobre esto en Vim: help, vi (1), nvi (1) o la especificación POSIX ... Se comporta igual en viy por nvicierto .
Martin Tournoij
1
En cierto modo, ddes idéntico a d_. _lleva el cursor a la primera línea que no está en blanco en la ( [count]-1) línea hacia abajo, pero está en línea, por lo que cuando se combina con un operador, opera en líneas completas. Por esa razón, tiene sentido que pueda aparecer un recuento entre los dos ds.
Tommcdo

Respuestas:

28

Modo pendiente de operador

Entre escribiendo un operador (como d, c, o gU) y un movimiento (como w, i}, o /foo<CR>), Vim está en modo de operador-pendiente. Puede crear asignaciones para esto usando :omapy :onoremap.

En mis ejemplos, voy a asignar el operador pendiente da w. Esta es una elección aleatoria, porque no sé para qué querías usarla.

Crea un omap

Creemos una asignación para el dmodo pendiente del operador. Asumiré que estamos escribiendo VimScript aquí (como en su .vimrc), así que omitiré los :s iniciales .

onoremap d w

Esto hace ddactuar como dw. También hace d[count]dactuar como d[count]w. Pero apuesto a que no quería afectar el comportamiento de dd(es decir, no [count]suministrado).

Mapeos de expresiones

Las asignaciones de expresión le permiten evaluar una expresión de VimScript para producir el lado derecho de la asignación. La expresión debe evaluar a una cadena. Las asignaciones de expresiones se denotan por la <expr>palabra clave.

Vim también tiene algunas variables integradas que se completan en varios momentos y, a menudo, son útiles durante las asignaciones. Uno de ellos es v:count, que se [count]suministra a un operador o movimiento.

Pongamos todo junto. Si no [count]se suministra, v:countserá 0. Podemos decirle a nuestro mapeo que solo use den ese caso.

onoremap <expr> d v:count == 0 ? 'd' : 'w'

Ahora se ddcomporta como el predeterminado (elimina una línea), pero se d[count]dcomporta como d[count]w. ¡Frio!

Restrinja su uso después del doperador

Sin embargo, es posible que notes algo. Ahora cdtambién se comporta como cw. Esto puede no ser un problema, pero para completar, restringámoslo para que solo funcione después del doperador.

Vim tiene otra variable, v:operatorque contiene el operador utilizado más recientemente. Vamos a ver eso también, antes de hacer algo especial.

onoremap <expr> d (v:count == 0 \|\| v:operator != 'd') ? 'd' : 'w'

NOTA: Dado que los :mapcomandos se pueden encadenar |, tenemos que escapar de ellos en nuestra expresión aquí. Entonces el operador lógico OR se ||convierte \|\|.

Fresco, así cdy c[count]dhan vuelto a hacer nada, al igual que lo hacían antes. Esto es bueno para que otros complementos puedan definir cd.

No quiero simplemente borrar algún otro movimiento

Si desea asignar d[count]dalgo totalmente diferente, nada que ver con la eliminación de texto, también podemos hacer que eso funcione.

Cuando está escribiendo comandos en modo Normal, y comienza a escribir un comando por error, puede presionar <Esc>para cancelar ese comando. Lo mismo se aplica a sus asignaciones.

Hagamos d[count]dcambiar la línea actual a lo que sea [count].

onoremap <expr> d (v:count == 0 \|\| v:operator != 'd') ? 'd' : '<Esc>cc' . v:count . '<Esc>'

La última parte de la asignación es una expresión Vimscript: <Esc>cc' . v:count . '<Esc>'. Eso es <Esc>para cancelar el dcomando pendiente , luego ccpara cambiar la línea actual, v:countescribir el valor de [count](en modo Insertar) y <Esc>volver al modo Normal. Tenga en cuenta que estamos construyendo una cadena aquí usando el operador de concatenación Vimscript, ..


Su caso de uso real probablemente será diferente de lo que he esbozado aquí, pero espero que esto lo ayude a poner la pelota en marcha.

Feliz Vimming!

tommcdo
fuente
¡Gran respuesta! Votado Hice un enlace a mi caso de uso (también en vi.SE) al comienzo de la pregunta, pero supongo que debe haberse perdido. Básicamente necesito hacer :omap d d(!), Pero desafortunadamente el modo pendiente del operador nunca se alcanza debido a mi mapeo para d que establece la función de operador personalizada. Sin embargo, con suerte es posible ajustar las cosas para que d3dfuncione como debería. (Avíseme si tiene alguna idea, o siéntase libre de publicar una solución completa a la otra pregunta si lo prefiere). Si no puedo resolverlo pronto, aceptaré esto y publicaré otra pregunta más específica. ¡Gracias!
Rich
1
En realidad, pensándolo bien, estoy aceptando esto ahora. Usted explicó tanto cómo crear tal mapeo, como también cómo funciona debajo del capó, que fueron las dos cosas que le pregunté.
Rich