Mengapa pemetaan mode normal <Esc> ini memengaruhi startup?


13

Saya mengalami masalah aneh dengan pemetaan mode normal Esc.

Jika Anda membuat file escmapvimrcdengan konten:

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

Dan kemudian mulai vim menggunakan vimrc ini:

vim --noplugin -u escmapvimrc

Kemudian vim akan mulai dalam mode menunggu operator dengan cperintah menunggu input lebih lanjut, menampilkan file kosong, dan dengan menampilkan baris perintah :noh.

Jika Anda menghapus nnoremapgaris, maka masalahnya hilang.

Jika Anda men-debug dan melangkah melalui semua yang Anda dapatkan output berikut:

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

Setelah Anda menekan enter, layar startup Vim ditampilkan, dan di bawahnya:

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

Layar startup Vim kemudian menghilang, dan Anda dalam mode pending operator, seperti dijelaskan di atas.

Apa yang sedang terjadi?

EDIT: Perilaku seperti dijelaskan dalam Vim 7.3. Dalam Vim 7.4.52, nmappenyebab Vim untuk memulai dalam mode Ganti ketika memulai Vim tanpa file. (Jika Vim 7.4.52 dimulai dengan file, bagaimanapun, itu juga dimulai dengan c-command yang sedang berlangsung.) Bagaimanapun, masalahnya hilang ketika nmap dihapus.


Saya mereproduksi ini dengan vim, tetapi baris perintah tidak muncul :nohuntuk saya. Melakukan hal yang sama dengan gvim tidak menunjukkan perilaku ini.
PhilippFrank

1
Pemetaan umum untuk menghapus sorotan pencarian adalah:nnoremap <c-l> :noh<cr><c-l>
Peter Rincker

Sebagai catatan tambahan, Anda dapat menggunakan /alksdjflaskjuntuk menghapus sorotan pencarian yang juga cukup cepat.
Shahbaz

Jawaban:


11

Vim mengirimkan selama startup beberapa kode terminal khusus (yang biasanya berisi <esc>kunci) untuk menentukan beberapa hal (warna, bs, ...) Jika Anda memetakan <esc>ini kemungkinan besar akan membingungkan parser dari kode kembali dan hal-hal aneh dapat terjadi.

Karena itu, gunakan peta Anda di atas hanya setelah semuanya telah diatur dengan benar (misalnya melalui perintah otomatis VimEnter).


1
Ya, mereka dikirim setiap kali 'term'opsi disetel. Itu biasanya hanya selama startup, tetapi mungkin ada skenario di mana ia diatur saat runtime.
jamessan

Dalam kasus khusus ini, ini sepertinya disebabkan oleh may_req_ambiguous_char_width () yang hanya dipanggil saat startup
Christian Brabandt

Saya berencana untuk mencoba persis ini (itulah sebabnya saya tidak menerima jawaban yang lain). Bagus untuk mendapat konfirmasi, itu pasti berhasil.
Rich

Ini telah melakukan trik, meskipun VimEntersecara khusus tidak berhasil.
Rich

Kamu bercanda kan? Escape yang digunakan untuk berkomunikasi harus terpisah dari pemetaan kunci Escape.
shawnhcorey

11

Terminal Linux menggunakan urutan pelarian ANSI (yaitu rangkaian karakter yang dimulai dengan <Esc>) untuk mengirim kunci khusus ke Vim, dan sebagai bagian dari protokol komunikasi yang dengannya aplikasi menanyakan kemampuannya. Pemetaan Anda mengganggu itu, dan dengan demikian mengarah pada perilaku "aneh" ini.

Karena itu, jangan memetakan<Esc> . Gunakan tombol lain. Masalahnya kurang jelas di GVIM, tapi saya juga tidak akan merekomendasikannya.


Sayangnya, saya sudah memetakan ini hampir sejak saya mulai menggunakan Vim, jadi cukup baik untuk memori otot saya sekarang. Terima kasih atas penjelasannya.
Rich

Saya mungkin harus menambahkan, demi anak cucu, masalah yang dijelaskan adalah satu - satunya masalah yang saya tahu pasti disebabkan oleh pemetaan ini, dan satu-satunya masalah aneh yang tidak dapat saya selesaikan dengan Vim.
Rich

1
@ Betapa sulitnya membiasakan diri menggunakan sesuatu seperti <Esc><Esc>?
Random832

@ Random832 Itu ide yang menarik.
Rich

1
Semua program xterm akan melakukan ini karena mereka meniru terminal VT-100. Itu tidak ada hubungannya dengan Linux. iOS, yang didasarkan pada BSD bukan Linux, juga akan memiliki xterms yang meniru VT-100.
shawnhcorey

1

Coba ini:

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

lih /programming//a/16027716/400545


Ini tidak bekerja dengan baik untuk saya. Setelah, mengganti pemetaan dalam escapemapvimrcfile saya dengan ini, ketika startup Vim selesai, saya dalam mode baris perintah, dengan baris perintah yang berisi konten berikut: :83/94/95^G(itu literal CTRL-Gdi akhir). Bit ini dari :helptampaknya menunjukkan ini mungkin bukan waktu terbaik untuk mengatur pemetaan: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.
Kaya

1

Saya mencoba mengatur autocommand untuk mengatur pemetaan nanti di startup, tetapi masalahnya masih terjadi. *

Saya akhirnya membuat perintah otomatis untuk muncul pertama kali saya memasuki mode Sisipkan. Ini jelas bukan solusi yang sempurna, tetapi bagi saya itu akan bekerja sebagian besar waktu, dan sepertinya itu yang terbaik yang bisa saya lakukan:

UPDATE : Setelah menggunakan versi yang lebih panjang di bawah ini tanpa masalah selama beberapa tahun, saya memutuskan bahwa itu mungkin sedikit over-engineered, dan sejak itu saya telah menggunakan versi yang lebih sederhana ini, yang alih-alih hanya menyetel ulang pemetaan setiap kali Anda memasukkan mode insert:

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

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

Pemetaan tidak perlu diatur ulang setiap kali Anda masuk ke mode insert, tetapi juga tidak ada salahnya bagi Vim untuk melakukannya.

VERSI ASLI :

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

* Saya mencoba melampirkan ke berbagai acara: VimEnter, BufReadPost, BufWinEnter, dan bahkan CursorMoved(!), Tapi ini semua tampaknya api terlalu dini.


Apakah Anda pernah mencoba perintah otomatis TermResponse?
Christian Brabandt

@ChristianBrabandt saya miliki sekarang. Ini tidak berfungsi dengan baik untuk saya :(.
Kaya

Saya baru-baru ini belajar, bahwa TermResponse tidak dipicu untuk semua perintah permintaan terminal terkait, yang vim baru saja mengirimkan. ( t_RV, t_u7, t_RF, t_RB, Dan mungkin orang lain.) Jadi kekuatan ini juga tergantung pada terminal Anda
Christian Brabandt
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.