¿Por qué esta asignación de modo normal <Esc> afecta el inicio?

13

Estoy experimentando un problema extraño con una asignación de modo normal de Esc.

Si crea el archivo escmapvimrccon el contenido:

set nocompatible
set showcmd " Doesn't affect the problem: just makes it easier to see
nnoremap <Esc> :noh<CR><esc>

Y luego inicie vim usando este vimrc:

vim --noplugin -u escmapvimrc

Luego, vim se iniciará en el modo pendiente del operador con un ccomando en espera de entrada adicional, mostrando un archivo vacío y con la línea de comando en pantalla :noh.

Si quita la nnoremaplínea, el problema desaparece.

Si depura y recorre todo, obtendrá el siguiente resultado:

Entering Debug mode.  Type "cont" to continue.
/[...]/escmapvimrc
line 1: set nocompatible
>s
/[...]/escmapvimrc
line 2: set showcmd " Doesn't affect the problem: just makes it easier to see
>s
/[...]/escmapvimrc
line 3: nnoremap <Esc> :noh<CR><esc>
>s
/[...]/escmapvimrc
line 4: End of sourced file
>s
Press ENTER or type command to continue

Después de presionar enter, se muestra la pantalla de inicio de Vim, y debajo:

Entering Debug mode.  Type "cont" to continue.
cmd: noh
>s

La pantalla de inicio de Vim desaparece, y está en modo pendiente de operador, como se describió anteriormente.

¿Que esta pasando?

EDITAR: El comportamiento es como se describe en Vim 7.3. En Vim 7.4.52, nmaphace que Vim se inicie en modo Reemplazar cuando se inicia Vim sin un archivo. ( Sin embargo, si Vim 7.4.52 se inicia con un archivo, también se inicia con un comando c en curso). De cualquier manera, el problema desaparece cuando se elimina el nmap.

Rico
fuente
Reproduje esto con vim, pero la línea de comando no se mostró :nohpara mí. Hacer lo mismo con gvim no mostró este comportamiento.
PhilippFrank
1
Un mapeo común para borrar el resaltado de búsqueda es:nnoremap <c-l> :noh<cr><c-l>
Peter Rincker
Como nota al margen, puede usar /alksdjflaskjpara aclarar el resaltado de búsqueda, que también es bastante rápido.
Shahbaz

Respuestas:

11

Vim envía durante el inicio algunos códigos de terminal especiales (que generalmente contienen la <esc>clave) para determinar varias cosas (colores, bs, ...) Si lo mapeó, <esc>esto probablemente confundirá al analizador de los códigos de retorno y pueden suceder cosas extrañas.

Por lo tanto, use su mapa anterior solo después de que todo se haya configurado correctamente (por ejemplo, mediante un comando automático VimEnter).

Christian Brabandt
fuente
1
Bueno, se envían cada vez que 'term'se establece la opción. Eso suele ser solo durante el inicio, pero puede haber escenarios en los que se establece en tiempo de ejecución.
jamessan
En este caso particular, esto parece ser causado por may_req_ambiguous_char_width (), que solo se llama al inicio
Christian Brabandt el
Estaba planeando probar exactamente esto (por eso no acepté la otra respuesta). Sin embargo, es bueno tener confirmación de que debería funcionar.
Rico
Esto ha hecho el truco, aunque VimEnterespecíficamente no funcionó.
Rich
¿Estás bromeando, verdad? El escape utilizado para comunicarse debe estar separado de la asignación de teclas Escape.
shawnhcorey
11

El terminal de Linux utiliza secuencias de escape ANSI (es decir, cadenas de caracteres que comienzan con <Esc>) para enviar claves especiales a Vim y como parte del protocolo de comunicación con el que la aplicación consulta sus capacidades. Su mapeo interfiere con eso, y por lo tanto conduce a estos comportamientos "extraños".

Por lo<Esc> tanto, no mapees . Usa otra llave. El problema es menos pronunciado en GVIM, pero tampoco lo recomendaría allí.

Ingo Karkat
fuente
Desafortunadamente, he tenido este mapeo casi desde que comencé a usar Vim, por lo que ahora está bastante quemado en mi memoria muscular. Gracias por la explicación, sin embargo.
Rich
Probablemente debería agregar, por el bien de la posteridad, el problema descrito es el único problema que sé que definitivamente es causado por este mapeo, y el único problema extraño no resuelto que puedo recordar tener con Vim.
Rich
1
@Rich ¿qué tan difícil sería acostumbrarse a usar algo como <Esc><Esc>?
Random832
@ Random832 Esa es una idea intrigante.
Rico
1
Todos los programas xterm harán esto porque emulan terminales VT-100. No tiene nada que ver con Linux. iOS, que se basa en BSD, no Linux, también tendrá xterms que emulan VT-100.
shawnhcorey
1

Prueba esto:

augroup escape_mapping
  autocmd TermResponse * nnoremap <Esc> :noh<CR><esc>
augroup end

cf /programming//a/16027716/400545

Jerome Dalbert
fuente
Esto no funciona bien para mí. Después, reemplazando la asignación en mi escapemapvimrcarchivo con esto, cuando se completa el inicio de Vim, estoy en modo de línea de comando, con la línea de comando que contiene los siguientes contenidos: :83/94/95^G(eso es un literal CTRL-Gal final). Este poco :helpparece sugerir que este podría no ser el mejor momento para configurar el mapeo:Note that this event may be triggered halfway executing another event, especially if file I/O, a shell command or anything else that takes time is involved.
Rico
1

Intenté configurar un comando automático para configurar la asignación más adelante en el inicio, pero el problema aún ocurrió.* *

Finalmente creé un autocomando para que ocurra la primera vez que entro en el modo Insertar. Obviamente, esta no es una solución perfecta, pero para mí funcionará la mayor parte del tiempo, y parece ser lo mejor que puedo hacer:

ACTUALIZACIÓN : Después de usar la versión más larga a continuación sin problemas durante unos años, decidí que posiblemente estaba un poco sobre diseñada, y desde entonces he usado esta versión mucho más simple, que en cambio solo restablece el mapeo cada vez que ingresas al modo de inserción:

augroup escape_mapping
  autocmd!
  autocmd InsertEnter * call s:setupEscapeMap()
augroup END

function! s:setupEscapeMap()
  nnoremap <Esc> :noh<CR><Esc>
endfunction

El mapeo no necesita reiniciarse cada vez que ingresa al modo de inserción, pero tampoco le hace ningún daño a Vim.

VERSIÓN ORIGINAL :

if !exists('g:escape_mapped')  " Only need to set the mapping up once.
  augroup escape_mapping
    autocmd!
    " Create the autocommand, to fire when Insert mode is entered
    autocmd InsertEnter * call s:setupEscapeMap()
  augroup END
endif

function! s:setupEscapeMap()
  " Actually create the mapping
  nnoremap <Esc> :noh<CR><Esc> 

  " Now the map exists, so we won't ever need the autocommand again.
  let g:escape_mapped = 1

  " Tidy up the autocommand and group
  autocmd! escape_mapping InsertEnter *
  augroup! escape_mapping
endfunction

* He intentado instalarla en varios eventos: VimEnter, BufReadPost, BufWinEnter, e incluso CursorMoved(!), Pero todos ellos parece que el fuego demasiado pronto.

Rico
fuente
¿Alguna vez has probado el TermResponseautocomando?
Christian Brabandt
@ChristianBrabandt que tengo ahora. No me funciona bien :(.
Rico
Hace poco me enteré de que TermResponse no se activa para todos los comandos de consulta relacionados con la terminal, que vim simplemente envía. ( t_RV, t_u7, t_RF, t_RB, Y, posiblemente, otros.) Así que esto podría también dependen de su terminal
Cristiano Brabandt