Pourquoi ce mappage en mode normal <Esc> affecte-t-il le démarrage?

13

Je rencontre un problème étrange avec un mappage en mode normal de Esc.

Si vous créez le fichier escmapvimrcavec le contenu:

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

Et puis démarrez vim en utilisant ce vimrc:

vim --noplugin -u escmapvimrc

Ensuite, vim démarrera en mode opérateur en attente avec une ccommande en attente de saisie supplémentaire, affichant un fichier vide et avec la ligne de commande :noh.

Si vous supprimez la nnoremapligne, le problème disparaît.

Si vous déboguez et parcourez tout, vous obtenez la sortie suivante:

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

Après avoir appuyé sur Entrée, l'écran de démarrage de Vim s'affiche, et en dessous:

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

L'écran de démarrage de Vim disparaît alors et vous êtes en mode opérateur en attente, comme décrit ci-dessus.

Que se passe-t-il?

EDIT: Le comportement est tel que décrit dans Vim 7.3. Dans Vim 7.4.52, le nmapfait démarrer Vim en mode Remplacer lors du démarrage de Vim sans fichier. (Si Vim 7.4.52 est démarré avec un fichier, cependant, il démarre également avec une commande c en cours.) Quoi qu'il en soit, le problème disparaît lorsque le nmap est supprimé.

Riches
la source
J'ai reproduit ceci avec vim, mais la ligne de commande ne s'est pas affichée :nohpour moi. Faire de même avec gvim n'a pas montré ce comportement.
PhilippFrank
1
Un mappage commun pour effacer le surlignage de recherche est le suivant:nnoremap <c-l> :noh<cr><c-l>
Peter Rincker
En guise de remarque, vous pouvez utiliser /alksdjflaskjpour effacer la surbrillance de la recherche, ce qui est également assez rapide.
Shahbaz

Réponses:

11

Vim envoie au démarrage des codes de terminal spéciaux (qui contiennent généralement la <esc>clé) pour déterminer plusieurs choses (couleurs, bs, ...) Si vous avez mappé, <esc>cela confondra très probablement l'analyseur des codes de retour et des choses étranges peuvent se produire.

Par conséquent, utilisez votre carte ci-dessus uniquement après que tout a été correctement configuré (par exemple via une autocommande VimEnter).

Christian Brabandt
la source
1
Eh bien, ils sont envoyés chaque fois que l' 'term'option est définie. C'est généralement uniquement au démarrage, mais il peut y avoir des scénarios où il est défini au moment de l'exécution.
jamessan
Dans ce cas particulier, cela semble être causé par may_req_ambiguous_char_width () qui n'est appelé qu'au démarrage
Christian Brabandt
J'avais l'intention d'essayer exactement cela (c'est pourquoi je n'ai pas accepté l'autre réponse). C'est bien d'avoir la confirmation que cela devrait fonctionner.
Rich
Cela a fait l'affaire, bien que cela VimEntern'ait pas fonctionné.
Rich
Tu plaisante, n'Est-ce pas? L'échappement utilisé pour communiquer doit être distinct du mappage de clé d'échappement.
shawnhcorey
11

Le terminal Linux utilise des séquences d'échappement ANSI (c'est-à-dire des chaînes de caractères commençant par <Esc>) pour envoyer des clés spéciales à Vim, et dans le cadre du protocole de communication avec lequel l'application recherche ses capacités. Votre cartographie interfère avec cela et conduit ainsi à ces comportements "étranges".

Par conséquent, ne mappez pas<Esc> . Utilisez une autre clé. Le problème est moins prononcé dans GVIM, mais je ne le recommanderais pas non plus.

Ingo Karkat
la source
Malheureusement, j'ai cette cartographie presque depuis que j'ai commencé à utiliser Vim, donc elle est assez bien gravée dans ma mémoire musculaire. Merci pour l'explication, cependant.
Rich
Je devrais probablement ajouter, pour l'amour de la postérité, que le problème décrit est le seul problème que je sais être définitivement causé par cette cartographie, et le seul problème étrange non résolu que je me souvienne avoir avec Vim.
Rich
1
@ Rich combien serait-il difficile de s'habituer à utiliser quelque chose comme <Esc><Esc>?
Random832
@ Random832 C'est une idée intrigante.
Rich
1
Tous les programmes xterm le feront car ils émulent les terminaux VT-100. Cela n'a rien à voir avec Linux. iOS, qui est basé sur BSD et non sur Linux, aura également des xterms qui émuleront les VT-100.
shawnhcorey
1

Essaye ça:

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

cf /programming//a/16027716/400545

Jerome Dalbert
la source
Ça ne marche pas bien pour moi. Après avoir remplacé le mappage dans mon escapemapvimrcfichier par ceci, lorsque le démarrage de Vim est terminé, je suis en mode ligne de commande, avec la ligne de commande contenant le contenu suivant: :83/94/95^G(c'est un littéral CTRL-Gà la fin). Ce morceau de :helpsemble suggérer que ce n'est peut-être pas le meilleur moment pour configurer la cartographie: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.
Rich
1

J'ai essayé de configurer une autocommande pour définir le mappage plus tard au démarrage, mais le problème persiste. *

J'ai finalement créé une autocommande qui se produit la première fois que j'entre en mode Insertion. Ce n'est évidemment pas une solution parfaite, mais pour moi, cela fonctionnera la plupart du temps, et cela semble être le mieux que je puisse faire:

MISE À JOUR : Après avoir utilisé la version longue ci-dessous sans problème pendant quelques années, j'ai décidé qu'elle était peut-être légèrement sur-conçue, et depuis lors, j'ai utilisé cette version beaucoup plus simple, qui à la place réinitialise simplement le mappage à chaque fois que vous entrez en mode insertion:

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

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

Le mappage n'a pas besoin d'être réinitialisé à chaque fois que vous entrez en mode d'insertion, mais cela ne nuit pas non plus à Vim.

VERSION ORIGINALE :

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

* J'ai essayé attacher à divers événements: VimEnter, BufReadPost, BufWinEnter, et même CursorMoved(!), Mais ceux - ci semblent tous au feu trop tôt.

Riches
la source
Avez-vous déjà essayé la commande TermResponseautomatique?
Christian Brabandt
@ChristianBrabandt je l'ai maintenant. Cela ne fonctionne pas bien pour moi :(.
Rich
J'ai récemment appris que la TermResponse n'est pas déclenchée pour toutes les commandes de requête liées au terminal, que vim envoie simplement. ( t_RV, t_u7, t_RF, t_RB, Et peut - être d' autres.) Donc , cela dépend aussi de votre terminal
Christian Brabandt