Dalam mode bash vi, petakan jk untuk keluar dari mode sisipkan

11

Saya menggunakan instalasi baru ubuntu 16.04, dengan bash shell. Ada dua hal yang ingin saya lakukan:

  1. Atur mode vi sehingga saya dapat memiliki gerakan seperti vim dari terminal
  2. keluar dari mode penyisipan dengan mengetik jk

Saya membaca di posting lain bagaimana ini bisa dilakukan zsh, bagaimana saya bisa melakukannya bash?

tl; dr

dimasukkan bind '"jk":vi-movement-mode'ke dalam .bashrcfile Anda setelah set -o vi:)

server@thinkpad:~$ tail -n 2 .bashrc
set -o vi
bind '"jk":vi-movement-mode'

silakan lihat jawaban @ grochmal untuk penjelasan yang lebih terperinci

mbigras
sumber
1
Apa yang Anda maksud dengan memetakan kembali jk? Apakah itu beberapa tombol khusus pada keyboard Anda?
Stephen Harris
silakan lihat edit
mbigras
Untuk pertama Anda, .bashrcbiasanya dipanggil pada setiap shell (misalnya jika Anda keluar dari vi) tetapi .bash_profilehanya dipanggil pada shell login. Jadi .bashrcadalah tempat yang tepat untuk set -o vi. Saya tidak punya jawaban untuk pertanyaan kedua Anda yang telah direvisi :-(
Stephen Harris
Bagaimana Anda memulai bash shell Anda? Berikut adalah penjelasan yang bagus tentang Perbedaan antara .bashrc dan .bash_profile
the_velour_fog
set -o vimasuk .bashrc, lihat Mengapa ~ / .bash_profile saya tidak berfungsi?
Gilles 'SANGAT berhenti menjadi jahat'

Jawaban:

10

TL; DR

Bash memiliki fungsi yang mirip dengan zsh's bindkeymelalui bind, tetapi tidak memiliki beberapa vimode seperti zsh. Setelah set -o viAnda bisa melakukannya:

bind '"jk":vi-movement-mode'

yang setara zshdenganbindkey -M <all vi modes> jk vi-movement-mode

The vi-movement-modefungsi berasal dari inputrc(lihat /etc/inputrcuntuk daftar mereka).

Teks lengkap

Seperti yang ditunjukkan Stephen Harris dalam komentarnya:

  • .bashrcdisebut dengan bashselalu (dan terutama tidak oleh shell lain).

  • .bash_profile hanya dipanggil di shell login (dan sekali lagi, hanya bash).

Beberapa distro hadir dengan .bash_profilekerangka yang terlihat seperti berikut:

# ~/.bash_profile
[[ -f ~/.bashrc ]] && . ~/.bashrc

Yang merupakan konten yang bagus .bash_profilekarena Anda bisa melupakannya.

Sekarang, untuk memetakan jkke Escdalam sesi shell, itu tidak benar-benar mungkin. Saat kamu melakukan:

inoremap jk <esc>

Di Vim, setelah Anda mengetik j, Vim tahu perlu menunggu sedikit untuk melihat apakah Anda mengetik kberikutnya dan itu harus memanggil pemetaan (atau Anda mengetik kunci lain dan pemetaan tidak boleh dipicu). Sebagai tambahan, ini dikendalikan oleh :set timeoutlen=<miliseconds>dalam Vim (lihat :h timeoutlen).

Beberapa shell atau X11 tidak memiliki kontrol batas waktu dan tidak memungkinkan untuk memetakan banyak karakter. Hanya pemetaan satu kunci yang diizinkan (Tetapi lihat catatan dukungan di bawah ini.).

set -o vi

Tidak membaca .vimrc, itu hanya meniru beberapa kombinasi tombol vi(bahkan tidak vim) yang dapat digunakan dalam shell. Hal yang sama dapat dikatakan tentang -o emacs, itu tidak datang dengan kekuatan penuh emacs.


Dukungan zsh

zshsebenarnya mendukung timeout peta. Dan Anda dapat menggunakan yang berikut untuk memetakan jkke <esc>:

bindkey -v  # instead of set -o vi
bindkey -e jk \\e

(Itu harus pergi ke ~/.zshrctidak ~/.bashrc)

Namun, saya menyarankan hal ini. Saya menggunakan vimdan zshsebagian besar waktu. Saya miliki inoremap jk <esc>di saya vimrcdan saya memang mencoba menggunakan bindkeykombinasi di atas. zshmenunggu terlalu lama untuk dicetak jsaat menggunakannya, dan itu sangat mengganggu saya.


dukungan bash

bashmendukung readline bind. Saya percaya bahwa bashdapat dikompilasi tanpa readilnekarena itu mungkin ada beberapa sistem langka yang memiliki bash yang tidak mendukung bind(waspada). Untuk memetakan jkke <esc>dalam bashAnda perlu melakukan:

set -o vi
bind '"jk":"\e"'

(ya itu tingkat ganda mengutip, itu diperlukan)

Sekali lagi, ini membuat mengetik jcukup mengganggu. Tapi entah kenapa kurang mengganggu daripada zshsolusi di mesin saya (mungkin batas waktu default lebih pendek).


Penanganan masalah (untuk cangkang non-bash dan non-zsh)

Alasan untuk memetakan kembali Esckunci adalah karena letaknya cukup jauh pada keyboard, dan mengetiknya membutuhkan waktu. Trik yang dapat dipinjam dari emacsorang - orang adalah untuk memetakan kembali CapsLockkarena itu adalah kunci yang tidak berguna. emacskalian remap ke Ctrltapi kami akan remap ke Esc.

Mari kita gunakan xev -event keyboarduntuk memeriksa kode kunci CapsLock:

KeyPress event, serial 25, synthetic NO, window 0x1c00001,
    root 0x496, subw 0x0, time 8609026, (764,557), root:(765,576),
    state 0x0, keycode 66 (keysym 0xffe5, Caps_Lock), same_screen YES,
    XLookupString gives 0 bytes: 
    XmbLookupString gives 0 bytes: 
    XFilterEvent returns: False

Dan untuk memeriksa fungsi Esc:

KeyPress event, serial 25, synthetic NO, window 0x1c00001,
    root 0x496, subw 0x0, time 9488531, (571,525), root:(572,544),
    state 0x0, keycode 9 (keysym 0xff1b, Escape), same_screen YES,
    XLookupString gives 1 bytes: (1b) "
    XmbLookupString gives 1 bytes: (1b) "
    XFilterEvent returns: False

Sangat bagus, CapsLockkode kunci 66 dan Escfungsinya disebut "Escape". Sekarang kita bisa melakukan:

# diable caps lock
xmodmap -e "remove lock = Caps_Lock"
# make an Esc key from the keycode 66
xmodmap -e "keycode 66 = Escape"

Hal di atas harus dilakukan dalam urutan ini. Sekarang setiap kali Anda menekannya CapsLockberfungsi seperti Esckunci.


Bagian yang sulit adalah di mana mengatur ini. File ~/.Xmodmapdengan konten:

remove lock = Caps_Lock
keycode 66 = Escape

Harus dihormati oleh sebagian besar distro (sebenarnya menampilkan manajer, tapi saya katakan distro untuk kesederhanaan), tetapi saya melihat yang tidak menghormati beberapa ~/X*file. Untuk distro semacam itu Anda dapat mencoba sesuatu seperti:

if [ "x" != "x$DISPLAY" ]; then
    xmodmap -e "remove lock = Caps_Lock"
    xmodmap -e "keycode 66 = Escape"
fi

Di Anda .bashrc.

(Secara teori itu akan lebih baik ditempatkan ~/.xinitrctetapi jika seorang manajer tampilan tidak menghormati .Xmodmapitu pasti tidak akan menghormati ~/.xnintrc.)

Ekstra Catatan: ini hanya remaps CapsLockke Escdalam sesi X11, karena peta hanya akan bekerja di emulator terminal. Sebenarnya ttytidak akan melihat peta.

Referensi dan bacaan tambahan:

grochmal
sumber
Terima kasih untuk penjelasan rinci. Apakah Anda bersedia menggambarkan proses yang sama kecuali untuk pemetaan, jkbukan CapsLock? Saya sudah mengaturnya di mesin osx saya; Namun, saya tidak memilikinya selama sisa akhir pekan dan saya tidak ingat bagaimana saya melakukannya :)
mbigras
@ Mbigras - Apakah Anda yakin melakukannya dengan bash? Bash tidak memiliki peta ambiguos. Aku tahu cara melakukannya di zsh: bindkey -v; bindkey -s jk \\e. Tapi itu adalah sesuatu yang akan datang kembali dan menggigit Anda kembali ketika Anda membutuhkan jk, karena timer tidak dikonfigurasi dan Anda tidak <leader>di zsh.
grochmal
Saya pasti melakukannya zshdan tidak bash, apakah itu tidak mungkin di bash?
mbigras
@ Mbigras - Tunggu, saya salah! Membaca man bashSaya menemukan bindbahwa pekerjaan sangat mirip dengan zsh's bindkey. Saya akan memperbarui jawabannya. Ini dia, saya menggunakan zshterlalu banyak.
grochmal
2
@Jason - Hei, ini Vi SE, Di sini semua orang menulis kata ALL CAPS dengan: "ketik kata" <Esc> viwU :). Tidak diperlukan penyelesaian
grochmal
2

Terima kasih, untuk jawaban sebelumnya, saya menggunakan ini di ~ / .zshrc saya untuk pintasan mirip-vi di terminal saya. Saya harap ini akan membantu seseorang.

bindkey -v
bindkey 'jk' vi-cmd-mode
om2c0de
sumber
Saya datang ke sini mencari jawaban yang berfungsi untuk mengikat kunci '^ G' untuk memasuki "mode normal" di zsh yang diaktifkan vi, dan ini adalah satu-satunya yang berfungsi.
Dalker