2012-03-14 15 views
5

No entiendo por qué estos comandos hacen cosas diferentes.Vim: escapando de la "barra" que concatena los comandos Ex

Pegado en el archivo vimrc, activa pulsando t en condiciones normales:

nnoremap t :call search('\m\(a\|b\)', 'W')<CR> 
nnoremap t :call search('\m\(a\\|b\)', 'W')<CR> 

escribe directamente en la línea de comandos:

:call search('\m\(a\|b\)', 'W') 
:call search('\m\(a\\|b\)', 'W') 

Para ser más específicos: La "intención" comportamiento requiere un \\| en el nnoremap ejemplo, pero requiere \| en el ejemplo de búsqueda call.

Soy consciente de que el tratamiento especial de la barra (:help :bar) es una de esas trampas que Vim me ha presentado, pero que aún no tiene sentido. La documentación dice claramente "esta lista de comandos verá barra como parte de su argumento", pero ninguna de esas excepciones se aplica aquí. Todos los comandos implicados en este ejemplo tratan la barra como un carácter meta concatenado. También en esta situación, el compás está dentro de una cadena y (¿creo?) Se analiza como parte de una cadena que tiene prioridad sobre la sintaxis de metaconcatenate.

Respuesta

11

De hecho, el problema se debe a un tratamiento especial del carácter de barra mediante comandos de creación de mapas.

El mecanismo de asignación de claves en Vim es una forma de hacer que una secuencia de pulsaciones de teclas se interprete como otra secuencia de teclas; no hay interpretación semántica de El idioma de Vim-script se realiza en este nivel. Dado que para crear una asignación es necesario separar los dos argumentos de la secuencia de teclas para indicar la asignación entre los comandos de :map -family start determinando los límites de estos dos argumentos. Para utilizar caracteres que puedan interferir con este proceso en una asignación, se debe usar la sintaxis de escape provista para los caracteres (entre los que se encuentran retorno de carro, espacio, barra invertida y barra).

Debido a que el carácter de barra se puede utilizar para separar un comando de asignación del siguiente comando Ex y, por lo tanto, para definir el límite de finalización de la mano del lado derecho de la asignación, no puede ser utilizado tal cual en una secuencia de teclas. Según :help map_bar, dependiendo de la configuración, un carácter de barra puede ser escaparon como <bar>, \| o ^V| (donde ^V denota literal Ctrl +V código de la llave).

Teniendo esto en mente, vamos a seguir las asignaciones en cuestión (alrededor de la parte \|/\\|) la forma en que se interpretan en la configuración por defecto. En la primera asignación, la secuencia \| se trata como un único carácter |. Por lo tanto, después de ejecutar ese comando de asignación, al pulsar t será el mismo como escribir

:call search('\m\(a|b\)', 'W')Introduzca

Cuando se ejecuta el segundo comando de asignación, la cadena \\| se interpreta como una barra diagonal inversa literal (no es necesario escaparse \ en el lado derecho de las asignaciones , excepto las anidadas) seguido del \| especificador que representa un caracter de barra. Por lo tanto, esta mapas de comando t a la siguiente:

:call search('\m\(a\|b\)', 'W')Introduzca

Sin embargo, cuando se escribe la búsqueda asignada llamadas en el modo de línea de comandos, a diferencia de secuencias de teclas de asignaciones, se se interpretan como comandos Ex de inmediato. Esos caracteres de barra aparecen en literales de cadena, por lo que no existe la posibilidad de que los malinterprete como separadores para comandos Ex. Cuando se escribe directamente, , los comandos se envían a la ejecución a medida que se escriben. Por lo tanto, la diferencia en el trabajo entre ellos se debe al significado de las expresiones regulares \m\(a\|b\) y \m\(a\\|b\), no debido a algún comportamiento de escape.

+0

Gracias por aclarar esto. Ciertamente pasé por alto cómo los comandos ': map' tienen que analizar sus argumentos sin mirar semánticamente su contenido. – Ein

7

Cuando se utiliza *map y command comandos de vim, el motor Vimscript no interpreta el comando - lo almacena como es, como una secuencia de pulsaciones de teclas (en el caso de *map) o como una cadena (en caso de command). El comando solo se interpreta cuando lo usas.

Por eso, cuando mapea el comando, vim realmente no sabe que su personaje de tubería está dentro de una cadena, porque no sabe ni le importa si hay cadenas en su comando, al menos no en esa etapa .

Si desea utilizar | en un *map, necesita usar <bar> en su lugar.

Cuestiones relacionadas