Apa yang dimaksud dengan shell dalam mode "vi" atau "emacs"?

32

Pertanyaan ini mengikuti langsung dari jawabannya . Dalam hal ini saya secara khusus tidak dapat memahami bagian yang mengatakan:

Dalam hal itu, perilakunya lebih dekat dengan emacs 'daripada dengan mode bash (readline) / ksh / zsh emacs, tetapi berangkat dari editor baris driver terminal tertanam (dalam mode kanonik), di mana Ctrl-Wmenghapus kata sebelumnya (werase, juga di vi ).

Di sini kita berbicara tentang shell dan bukan editor yang merupakan dua program yang sama sekali berbeda. Apa artinya mengatakan shell dalam beberapa mode editor?

PS: Anda dapat mendasarkan jawaban Anda pada premis bahwa saya mengerti apa itu shell dan bagaimana menggunakan vim untuk pengeditan dasar.

Kutu buku
sumber
Ini bukan tentang fungsionalitas inti shell per se, tetapi lebih tentang pengeditan baris (apa yang Anda lakukan ketika Anda membuat kesalahan ketik dan kembali dan memperbaiki sendiri).
n. 'kata ganti' m.

Jawaban:

27

Dalam mode "vi" Anda dapat mengedit / menavigasi pada prompt shell saat ini seperti baris di editor vi. Anda dapat melihatnya seperti file teks satu baris. Secara analogi dalam mode "emacs" Anda dapat mengedit / menavigasi baris perintah saat ini menggunakan (beberapa) pintasan Emacs.

Contoh

Misalnya dalam mode-vi Anda dapat melakukan sesuatu seperti (dalam bash):

$ set -o vi
$ ls hello world
<ESC>
bbdw # results in
$ ls world

Dalam mode-emacs Anda dapat menekan misalnya Ctrl+ Auntuk melompat pada awal baris (vi: Ctrl+ [, 0atau ESC, 0). Anda dapat mengaktifkan mode emacs via set -o emacs(dalam bash, ksh, zsh dll.).

Readline

Banyak program baris perintah interaktif (termasuk bash ) menggunakan pustaka readline . Dengan demikian, Anda dapat mengonfigurasi mode input mana yang akan digunakan (vi atau emacs) dan opsi lain di satu tempat sehingga setiap program yang menggunakan readline memiliki antarmuka pengeditan / navigasi yang sama persis.

Misalnya konfigurasi readline saya terlihat seperti:

$ cat ~/.inputrc 
set editing-mode vi
set blink-matching-paren on

Sebagai contoh zsh / ksh tidak menggunakan readline sejauh yang saya tahu, tetapi juga mendukung mode vi / emacs yang sangat mirip dengan bash / readline.

Tentu saja, mode vi / emacs dalam shell baris perintah hanyalah sebagian dari set fitur editor lengkap. Tidak semua fitur masuk akal dalam shell baris perintah, dan beberapa fitur lebih rumit untuk didukung daripada yang lain.

Mode Canonical

Sebelum mode vi / emacs dari shell baris perintah interaktif 'ditemukan', shell Anda hanya akan menggunakan mode kanonik dari terminal Anda yang hanya menyediakan serangkaian perintah pengeditan yang terbatas (misalnya Ctrl+ Wuntuk menghapus kata terakhir.

maxschlepzig
sumber
Misalkan saya tidak tahu di mode Input mana saya aktif. Bisakah saya memverifikasinya dengan memasukkan beberapa teks dan tekan [Ctrl] + [A]? jika kursor bergerak untuk memulai emacs yang lain itu vi?
limovala
2
@limovala, seharusnya perkiraan yang baik. Tergantung pada shell Anda tentu saja - jika CTL + A tidak bekerja kemungkinan lain adalah bahwa shell Anda tidak termasuk mode pengeditan apa pun. Mungkin beberapa shell juga menerapkan mode pengeditan lainnya. Tetapi dalam praktiknya metode Anda harus cukup baik. Anda juga dapat menguji dengan perintah vi setelah itu untuk lebih yakin. Dalam bash Anda juga bisa menggunakan sesuatu seperti set -o | grep 'emacs\|vi'. Di zsh (di mana saya memiliki mode-vi) ini tidak bekerja, meskipun.
maxschlepzig
bind -P juga akan memberikan indikasi yang baik tentang mode mana yang ada
Paul
23

Anda akan melihat bahwa ketika Anda menjalankan catprompt shell pada terminal, catyang seharusnya menulis ke stdout apa yang dibaca dari stdin, dan tekan a, Anda melihat agema kembali oleh driver terminal, tetapi cattidak menulis itu a(Anda lihat hanya satu a, yang digaungkan oleh driver terminal).

Namun, jika Anda mengetik a Backspace b Enter, Anda tidak melihat catkeluaran a\010b\015, tetapi b\012( bdan baris baru).

Itu karena driver terminal (kita berbicara perangkat lunak di kernel, bukan di terminal emulator suka xterm) mengimplementasikan editor baris yang sangat dasar ketika dalam mode kanonik . Driver terminal dapat dikonfigurasi menggunakan ioctl()panggilan sistem seperti saat menggunakan sttyperintah. Misalnya, untuk meninggalkan mode kanonik, Anda bisa melakukannya stty -icanon. Jika kamu melakukan:

stty -icanon; cat

Kemudian, Anda akan melihat echo(yang bisa dinonaktifkan dengan Anda stty -echo) dan catoutput pada saat yang sama.

Editor itu adalah editor baris. Yaitu, bagi pengguna untuk mengedit satu baris teks sampai dikirim ke aplikasi membaca perangkat terminal setelah menekan Enter.

Kemampuan mengedit editor itu sangat terbatas. Dalam sebagian besar implementasi, hanya ada 4 tombol pengeditan (sebenarnya karakter) yang dapat dikonfigurasi dengan stty:

  • erase ( ^Hatau ^?biasanya): hapus karakter sebelumnya
  • bunuh ( ^Ubiasanya): kosongkan (bunuh) garis yang dimasukkan sejauh ini
  • werase ( ^W): hapus kata sebelumnya
  • lnext ( ^V): masukkan karakter berikutnya secara harfiah (batalkan makna khusus semua hal di atas)

Kembali di masa lalu, diperkirakan bahwa editor garis driver terminal akan diperluas dengan kemampuan yang lebih bagus. Itulah sebabnya mengapa tidak ada shell awal yang memiliki kemampuan pengeditan baris perintah (Anda akan mendapatkan kemampuan pengeditan baris yang sama pada prompt shell daripada saat menjalankan catseperti yang kami lakukan di atas).

Namun, itu benar-benar tidak pernah terjadi, mungkin sebagian alasannya adalah kekacauan dengan terminal yang berbeda tidak mengirim karakter yang sama pada beberapa penekanan tombol yang membuatnya menjadi jelas bahwa itu tidak boleh diimplementasikan dalam ruang kernel.

Jadi beberapa shell mulai menjatuhkan mode kanonik driver terminal dan menerapkan editor baris mereka sendiri. Pada saat itu, emacsdan vimerupakan editor teks visual paling populer dengan mode operasi dan pengikatan tombol yang sama sekali berbeda. Di vi, Anda memiliki satu mode untuk memasukkan teks, dan satu untuk mengedit. Di emacs, Anda selalu masuk mode teks , tetapi pengeditan dilakukan dengan menekan kombinasi tombol (seperti ^buntuk memindahkan karakter ke belakang).

Tidak ada gunanya kerang pada saat itu datang dengan pengikatan kunci yang berbeda. Itu akan menyebabkan frustrasi bagi orang untuk harus belajar yang berbeda. Namun, memilih satu ( emacsatau vi) gaya di atas yang lain akan menjadi cara yang pasti untuk mengasingkan pengguna editor lain .

Menurut https://www.usenix.org/legacy/publications/library/proceedings/vhll/full_papers/korn.ksh.a :

Fitur pengeditan sebaris populer (mode vi dan emacs) dari ksh dibuat oleh pengembang perangkat lunak di Bell Laboratories; mode edit garis vi oleh Pat Sullivan, dan mode edit baris emacs oleh Mike Veach. Masing-masing telah secara mandiri memodifikasi shell Bourne untuk menambahkan fitur-fitur ini, dan keduanya berada di organisasi yang ingin menggunakan ksh hanya jika ksh memiliki inline editor masing-masing. Awalnya ide menambahkan pengeditan baris perintah ke ksh ditolak dengan harapan bahwa pengeditan baris akan pindah ke driver terminal. Namun, ketika menjadi jelas bahwa ini tidak mungkin terjadi segera, kedua mode pengeditan baris diintegrasikan ke dalam ksh dan dibuat opsional sehingga mereka dapat dinonaktifkan pada sistem yang menyediakan pengeditan sebagai bagian dari antarmuka terminal.

Jadi sebagai gantinya, mereka mengimplementasikan keduanya dan sebuah antarmuka bagi pengguna untuk memilih di antara keduanya. kshkemungkinan besar yang pertama di awal 80-an (menggunakan kembali kode yang telah ditulis secara terpisah untuk menambahkan mode vi dan mode emacs ke shell Bourne seperti yang terlihat di atas) diikuti oleh tcsh( tcshawalnya hanya memiliki emacspengikatan kunci, vimode ditambahkan kemudian) dan kemudian bashdan zshdi awal 90-an.

Anda beralih di antara dua mode di bash, zshatau kshdengan set -o viatau set -o emacs, dan dengan bindkey -eatau bindkey -vdi tcshatau zsh.

POSIX sebenarnya menentukan vimode dan bukan emacsmode untuk sh(ceritanya Richard Stallman keberatan dengan POSIX menentukan emacsmode untuksh ).

Modus default untuk bash, domain publik varian dari ksh(pdksh, mksh, oksh), tcshdan zshmerupakan modus emacs (meskipun dengan zsh, itu vijika Anda $EDITORyaitu vi), sedangkan di AT & T ksh, itu adalah bodoh modus kecuali $EDITORatau $VISUALmenyebutkan viatau emacs.

kshjuga kemudian menambahkan gmacsmode untuk mengakomodasi pengguna Gosling emacsyang ditangani secara Ctrl+Tberbeda.

Sekarang penanganan ^Wdalam emacsatau dalam tcshmode emacs mungkin mendahului werasekarakter dalam editor baris terminal, jadi kita tidak bisa menyalahkan mereka untuk itu dan pernyataan saya tentang "berangkat ..." dapat dilihat sebagai menyesatkan. Hanya saja saya merasa menjengkelkan ketika hal-hal suka emacs, tcshatau infoberperilaku berbeda dari yang lainnya saat Anda mengetik Ctrl-W. Anda dapat membayangkan saya merasa jauh lebih menjengkelkan ketika beberapa aplikasi mulai menutup jendela mereka ketika Anda mengetik Ctrl-W.

Stéphane Chazelas
sumber
1
pdkshjuga mem $EDITOR- parsing vidan mengganti mode pada saat startup; Saya menghapus itu untuk mksh(terutama karena saya hanya benar-benar mempertahankan mode Emacs pula).
mirabilos
Terima kasih banyak tambahan, terutama dengan diskusi rinci tentang perilaku dan sejarah berbagai kerang. Sebagai seseorang yang secara teratur diminta untuk bekerja di distro yang berbeda dengan cangkang yang tidak saya konfigurasikan, ini sangat membantu.
BryKKan
Terima kasih untuk konteks sejarah yang luar biasa. Sayang sekali bahwa fitur pengeditan inline yang lebih canggih tidak ditambahkan ke driver terminal pada waktu itu. Program tidak perlu menyertakan perpustakaan seperti Readline. Saya juga bertanya-tanya mengapa Emacs-mode tidak ditentukan oleh POSIX sehingga tautan ke Rationale menarik. (Saya juga berbagi rasa frustrasi Anda dengan ^Wmenutup jendela).
Anthony G - keadilan untuk Monica
1
@AnthonyGeoghegan, kita masih membutuhkan hal-hal seperti zle / readline karena hal-hal seperti nama file / penyelesaian perintah tidak dapat benar-benar dilakukan pada driver terminal.
Stéphane Chazelas