Dlaczego to mapowanie trybu normalnego <Esc> wpływa na uruchamianie?

13

Mam dziwny problem z mapowaniem trybu normalnego Esc.

Jeśli utworzysz plik escmapvimrcz zawartością:

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

A następnie uruchom vim za pomocą tego vimrc:

vim --noplugin -u escmapvimrc

Następnie vim uruchomi się w trybie oczekiwania operatora z cpoleceniem oczekującym na dalsze wprowadzanie, wyświetlaniem pustego pliku i wyświetlaniem wiersza poleceń :noh.

Jeśli usuniesz nnoremaplinię, problem zniknie.

Jeśli debugujesz i przejdziesz przez wszystko, otrzymasz następujące dane wyjściowe:

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

Po wciśnięciu enter wyświetli się ekran startowy Vima, a pod nim:

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

Ekran startowy Vima znika, a ty jesteś w trybie oczekiwania operatora, jak opisano powyżej.

Co się dzieje?

EDYCJA: Zachowanie jest takie, jak opisano w Vim 7.3. W Vimie 7.4.52 nmappowoduje , że Vim uruchamia się w trybie Zastąpienia podczas uruchamiania Vima bez pliku. (Jeśli Vim 7.4.52 jest uruchamiany z plikiem, uruchamia się również z trwającym poleceniem c). Tak czy inaczej, problem zniknie po usunięciu nmap.

Bogaty
źródło
Powtórzyłem to za pomocą vima, ale linia poleceń nie pokazała :nohmi się. Robienie tego samego z gvimem nie wykazało tego zachowania.
PhilippFrank
1
Typowe mapowanie w celu wyczyszczenia podświetlenia wyszukiwania to:nnoremap <c-l> :noh<cr><c-l>
Peter Rincker
Na marginesie, możesz użyć /alksdjflaskjdo wyczyszczenia podświetlenia wyszukiwania, które jest również dość szybkie.
Shahbaz

Odpowiedzi:

11

Podczas uruchamiania Vim wysyła specjalne kody terminali (które zwykle zawierają <esc>klucz), aby określić kilka rzeczy (kolory, bs, ...). Jeśli to zmapujesz <esc>, najprawdopodobniej pomylisz parser kodów powrotu i mogą się zdarzyć dziwne rzeczy.

Dlatego używaj powyższej mapy tylko po prawidłowym skonfigurowaniu wszystkich elementów (np. Za pomocą komendy automatycznej VimEnter).

Christian Brabandt
źródło
1
Są wysyłane za każdym razem, gdy 'term'opcja jest ustawiona. Zwykle dzieje się to tylko podczas uruchamiania, ale mogą istnieć scenariusze, w których jest on ustawiany w czasie wykonywania.
jamessan
W tym konkretnym przypadku wydaje się, że jest to spowodowane przez may_req_ambiguous_char_width (), który jest wywoływany tylko podczas uruchamiania
Christian Brabandt
Chciałem wypróbować dokładnie to (dlatego nie zaakceptowałem innej odpowiedzi). Dobrze mieć potwierdzenie, że powinno działać.
Rich
To załatwiło sprawę, chociaż VimEnterkonkretnie nie działało.
Bogaty
Żartujesz, prawda? Escape używany do komunikacji powinien być oddzielny od mapowania klawisza Escape.
shawnhcorey
11

Terminal Linux wykorzystuje sekwencje specjalne ANSI (tj. Ciągi znaków rozpoczynające się od <Esc>) do wysyłania specjalnych kluczy do Vima oraz jako część protokołu komunikacyjnego, z którym aplikacja pyta o swoje możliwości. Twoje mapowanie zakłóca to, a tym samym prowadzi do tych „dziwnych” zachowań.

Dlatego nie mapuj<Esc> . Użyj innego klucza. Problem jest mniej wyraźny w GVIM, ale nie poleciłbym go też tam.

Ingo Karkat
źródło
Niestety, miałem to mapowanie prawie od kiedy zacząłem używać Vima, więc jest już całkiem dobrze zapamiętywane w mojej pamięci mięśni. Dziękuję za wyjaśnienie.
Bogaty
Powinienem chyba dodać, ze względu na potomstwo, opisany problem jest jedynym problemem, który, jak wiem, jest zdecydowanie spowodowany przez to mapowanie i jedynym dziwnym nierozwiązanym problemem, który mogę sobie przypomnieć z Vimem.
Bogaty
1
@Rich, jak trudno byłoby przyzwyczaić się do używania czegoś takiego <Esc><Esc>?
Random832,
@ Random832 To intrygujący pomysł.
Bogaty
1
Wszystkie programy xterm zrobią to, ponieważ emulują terminale VT-100. Nie ma to nic wspólnego z Linuksem. iOS, który jest oparty na BSD, a nie Linux, będzie także miał xtermy emulujące VT-100.
shawnhcorey
1

Spróbuj tego:

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

por. /programming//a/16027716/400545

Jerome Dalbert
źródło
To nie działa dobrze dla mnie. Po zastąpieniu mapowania w moim escapemapvimrcpliku tym, po zakończeniu uruchamiania Vima, jestem w trybie wiersza poleceń, z wierszem poleceń zawierającym następującą zawartość: :83/94/95^G(to dosłownie CTRL-Gna końcu). Ta część :helpwydaje się sugerować, że nie może to być najlepszy czas na skonfigurowanie mapowania: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

Próbowałem skonfigurować automatyczne polecenie, aby ustawić mapowanie później podczas uruchamiania, ale problem nadal występował. *

W końcu utworzyłem komendę automatyczną, która pojawi się przy pierwszym wejściu w tryb wstawiania. To oczywiście nie jest idealne rozwiązanie, ale dla mnie będzie działać przez większość czasu i wydaje się, że najlepiej, co mogę zrobić:

AKTUALIZACJA : Po kilku latach używania dłuższej wersji bez problemu zdecydowałem, że jest ona nieco przerobiona i od tego czasu korzystam z tej znacznie prostszej wersji, która zamiast tego resetuje mapowanie za każdym razem, gdy wchodzisz w tryb wstawiania:

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

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

Mapowanie nie musi być resetowane za każdym razem, gdy wchodzisz w tryb wstawiania, ale nie wyrządza to żadnej szkody Vimowi.

WERSJA ORYGINALNA :

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

* Próbowałem dołączając je do różnych wydarzeń: VimEnter, BufReadPost, BufWinEnter, a nawet CursorMoved(!), Ale wszystkie one wydają się ognia zbyt wcześnie.

Bogaty
źródło
Czy próbowałeś kiedyś TermResponsekomendy automatycznej?
Christian Brabandt
@ChristianBrabandt Mam teraz. Nie działa mi to dobrze :(.
Rich
Niedawno dowiedziałem się, że TermResponse nie jest uruchamiany dla wszystkich poleceń zapytań związanych z terminalem, które vim po prostu wysyła. ( t_RV, t_u7, t_RF, t_RB, I ewentualnie innych). Więc to może również zależeć od terminala
Christian Brabandt