Почему это <Esc> отображение нормального режима влияет на запуск?

13

У меня странная проблема с отображением нормального режима Esc.

Если вы создаете файл escmapvimrcс содержимым:

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

А затем запустите vim, используя этот vimrc:

vim --noplugin -u escmapvimrc

Затем vim запустится в режиме ожидания оператора с cкомандой, ожидающей дальнейшего ввода, отображением пустого файла и отображением командной строки :noh.

Если вы удалите nnoremapлинию, то проблема исчезнет.

Если вы отлаживаете и проходите все этапы, вы получите следующий вывод:

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

После того, как вы нажмете ввод, появится экран запуска Vim, и под ним:

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

После этого экран запуска Vim исчезает, и вы находитесь в режиме ожидания оператора, как описано выше.

В чем дело?

РЕДАКТИРОВАТЬ: Поведение, как описано в Vim 7.3. В Vim 7.4.52 nmapпричины запуска Vim в режиме замены при запуске Vim без файла. (Однако, если Vim 7.4.52 запускается с файлом, он также запускается с выполняющейся командой c.) В любом случае, проблема исчезает, когда nmap удаляется.

Богатый
источник
Я воспроизвел это с помощью vim, но командная строка :nohмне не показалась . То же самое с gvim не показывало такого поведения.
PhilippFrank
1
Обычное сопоставление для очистки выделенной области поиска:nnoremap <c-l> :noh<cr><c-l>
Питер Ринкер
Как примечание, вы можете использовать, /alksdjflaskjчтобы очистить подсветку поиска, что также довольно быстро.
Шахбаз

Ответы:

11

Во время запуска Vim отправляет некоторые специальные коды терминала (которые обычно содержат <esc>ключ), чтобы определить несколько вещей (цвета, bs, ...). Если вы отобразили <esc>это, это, скорее всего, запутает анализатор кодов возврата, и могут произойти странные вещи.

Поэтому используйте приведенную выше карту только после того, как все настроено правильно (например, с помощью автокоманды VimEnter).

Кристиан Брабандт
источник
1
Ну, они отправляются всякий раз, когда 'term'опция установлена. Обычно это только во время запуска, но могут быть сценарии, в которых он установлен во время выполнения.
Jamessan
В данном конкретном случае это может быть вызвано функцией may_req_ambiguous_char_width (), которая вызывается только при запуске
Кристиан Брабандт
Я планировал попробовать именно это (именно поэтому я не принял другой ответ). Хорошо, что есть подтверждение, что оно должно работать.
Rich
Ты прикалываешься, да? Побег, используемый для связи, должен быть отделен от сопоставления клавиши Escape.
Shawnhcorey
11

Терминал Linux использует escape-последовательности ANSI (то есть строки символов, начинающиеся с <Esc>) для отправки специальных ключей в Vim и как часть протокола связи, с которым приложение запрашивает свои возможности. Ваше отображение мешает этому и тем самым приводит к такому «странному» поведению.

Поэтому не наносите на карту<Esc> . Используйте другой ключ. Проблема менее выражена в GVIM, но я бы не стал ее рекомендовать.

Инго Каркат
источник
К сожалению, у меня это отображение было почти с тех пор, как я начал использовать Vim, так что оно довольно хорошо сгорело в моей мышечной памяти. Спасибо за объяснение, хотя.
Рич
Вероятно, я должен добавить, что для потомков описанная проблема - это единственная проблема, которая, как я знаю, определенно вызвана этим отображением, и единственная странная нерешенная проблема, о которой я могу вспомнить, с Vim.
Rich
1
@ Как сложно было бы привыкнуть к чему-то подобному <Esc><Esc>?
Random832
@ Random832 Это интригующая идея.
Рич
1
Все программы xterm будут делать это, потому что они эмулируют терминалы VT-100. Это не имеет ничего общего с Linux. iOS, основанная на BSD, а не на Linux, также будет иметь xterms, эмулирующие VT-100.
shawnhcorey
1

Попробуй это:

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

см. /programming//a/16027716/400545

Джером Далберт
источник
Это не очень хорошо для меня. После замены отображения в моем escapemapvimrcфайле на это, когда запуск Vim завершается, я нахожусь в режиме командной строки с командной строкой, содержащей следующее содержимое: :83/94/95^G( CTRL-Gв конце это литерал ). Этот бит , :helpкажется, предполагают , что это может быть не самое лучшее время , чтобы настроить отображение: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

Я попытался настроить автокоманду, чтобы установить сопоставление позже при запуске, но проблема все еще возникала. *

В конце концов я создал автокоманду, которая появляется при первом входе в режим вставки. Это, очевидно, не идеальное решение, но для меня это будет работать большую часть времени, и, похоже, это лучшее, что я могу сделать:

ОБНОВЛЕНИЕ : После использования более длинной версии, представленной ниже, без проблем в течение нескольких лет, я решил, что она, возможно, немного перегружена, и с тех пор я использовал эту гораздо более простую версию, которая вместо этого просто сбрасывает отображение каждый раз, когда вы входите в режим вставки:

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

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

Сопоставление не нужно сбрасывать каждый раз, когда вы входите в режим вставки, но оно также не причиняет Vim никакого вреда.

ОРИГИНАЛЬНАЯ ВЕРСИЯ :

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

* Я пытался прикрепив ее к различным событиям: VimEnter, BufReadPost, BufWinEnter, и даже CursorMoved(!), Но все они , кажется, огонь слишком рано.

Богатый
источник
Вы когда-нибудь пробовали TermResponseавтокоманду?
Кристиан Брабандт
@ChristianBrabandt у меня сейчас. Это не работает для меня :(.
Богатый
Я только недавно узнал, что TermResponse не запускается для всех команд запросов, связанных с терминалом, которые просто отправляет vim. ( t_RV, t_u7, t_RF, t_RB, И , возможно , другие.) Таким образом , это может также зависеть от вашего терминала
Christian Brabandt