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.


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).


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.


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


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.


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.