Masalah dengan ikatan kunci saat menggunakan terminal

30

Saya memiliki baris berikut di init.el:

(global-set-key [(control \;)] 'comment-region)

Ini berfungsi sangat baik di jendela GUI, tetapi jika emacsdipanggil dengan -nwopsi maka C-;tidak berkomentar wilayah, hanya menyisipkan ;karakter. M-x comment-region RETbekerja dengan baik.

Saya mencoba mengikuti jawaban ini pada masalah yang sama, tetapi C-q C-;kembali saja ;dan saya jelas tidak ingin mengikat ;.

Bagaimana cara mencapai efek yang diinginkan?

WeSenseASoulInSearchOfAnswers
sumber
4
Mungkin saja terminal Anda (apa yang Anda gunakan, omong-omong?) Tidak mengenali urutan perintah itu. Coba gunakan C-;kombo dan kemudian gunakan M-x view-lossageuntuk melihat apakah itu bahkan sampai ke Emacs.
Dan
Saya menggunakan gnome-terminal, dan M-x view-lossagemengembalikan:ESC [ > 1 ; 2 8 0 2 ; 0 c ; ESC x v i e w - l o s s a g e RET
WeSenseASoulInSearchOfAnswers
3
Sepertinya masalah terminal: jika kombinasi kunci itu untuk mencapai Emacs, itu akan terlihat seperti C-;daripada c ;(atau, setidaknya, saya dapatkan C-;).
Dan
@ Dan: Bisakah Anda menjawabnya sebagai jawaban? Itu akan menandai pertanyaan sebagai dijawab dan membuatnya lebih mudah untuk melihat solusinya, yang bagus untuk orang lain yang memiliki masalah yang sama. Terima kasih!
Tikhon Jelvis
Ringkas dan diposting dengan tautan tambahan untuk membaca lebih lanjut. Juga mengedit judul pertanyaan untuk membuatnya sedikit lebih umum.
Dan

Jawaban:

17

Pertama, masalah yang lebih umum: emulator terminal sering terbatas dalam urutan kontrol dan lolos yang dapat mereka kirim. Jadi: terminal mungkin menelan karakter khusus Anda sebelum mencapai Emacs. Sebagai diagnostik umum, Anda dapat menekan C-h l(atau M-x view-lossage) untuk melihat apakah kombinasi kunci Anda membuatnya menjadi Emacs.

Untuk diskusi lebih lanjut tentang masalah ini, lihat thread Stack Overflow ini dan tautan di dalamnya.

Untuk meringkas bolak-balik dalam komentar, masalah spesifik Anda menunjukkan itu terminal bukan Emacs yang menjadi masalah. Ketika Anda mencoba C-;dan kemudian M-x view-lossage, Anda mendapatkannya blah blah blah c ; ESC v i e w - l o s s a g e RET. Itu terlihat seperti masalah terminal: jika kombinasi kunci mencapai Emacs, c ;bagian itu akan terlihat seperti C-;.

Dan
sumber
33

Dalam Shift + Up tidak dikenali oleh Emacs di terminal saya menjelaskan bagaimana terminal menerjemahkan sebagian besar tombol fungsi ke dalam urutan escape, karena antarmuka antara aplikasi dan terminal mentransmisikan karakter (atau lebih tepatnya byte), bukan kunci. Hanya beberapa pengubah + kombinasi karakter yang memiliki karakternya sendiri:

  • Ctrlditambah satu huruf atau satu @[\]^_belokan menjadi byte 0–31 ( karakter kontrol ASCII ).
  • Seringkali Ctrl+ ?berubah menjadi byte 127 dan Ctrl+ Spacesama dengan Ctrl+ @(byte 0).
  • Beberapa tombol fungsi setara dengan karakter kontrol: Tab= Ctrl+ I, Return= Ctrl+ M, Esc= Ctrl+ [.
  • Dan Backspace= Ctrl+ Hatau Ctrl+ ?tergantung pada konfigurasi. Ctrl+ ?lebih nyaman untuk Emacs, karena Ctrl+ Hadalah bantuan.
  • Meta+ characterDikirim sebagai Escdiikuti oleh karakter .

Jadi, bagaimana dengan kombinasi lain seperti Ctrl+ ;atau Ctrl+ Shift+ letter? Karena tidak ada karakter yang sesuai, terminal harus menggunakan kembali karakter atau mengirim urutan pelarian. Banyak terminal mengabaikan pengubah ketika tidak ada karakter yang sesuai, sehingga Anda berakhir dengan Ctrl+ ;pengiriman ;, Ctrl+ Shift+ lettersetara dengan Ctrl+ letter, dll.

Vendor terminal terus melakukan hal sederhana untuk waktu yang lama. Tidak ada standar untuk sekuens melarikan diri, yang bersifat swadaya - vendor terminal tidak mengimplementasikannya, aplikasi tidak mendukungnya, pengguna tidak mengharapkannya. Beberapa emulator terminal dapat dikonfigurasikan untuk mengirim urutan pelarian yang sewenang-wenang, jadi jika Anda bisa, Anda dapat mengonfigurasinya dan mendeklarasikan urutan pelepasan ke Emacs (lebih lanjut tentang ini nanti).

Akhir-akhir ini, situasinya berubah, karena telah ada dua proposal untuk distandarisasi pada urutan pelarian. Salah satunya adalah libtermkey LeoNerd dengan sintaks . Lain adalah xterm Thomas Dickey dengan sintaks . Versi xterm saat ini (≥216) dapat dikonfigurasikan untuk sintaksis dengan mengatur sumber daya; fitur harus diaktifkan dengan menyetel ke nilai bukan nol.ESC [ codepoint ; modifier uESC [ 2 7 ; modifier ; codepoint ~formatOtherKeysmodifyOtherKeys

Jika emulator terminal Anda tidak mendukung sintaks ini tetapi dapat dikonfigurasi, pilih salah satunya.

Sejak Emacs 24.4, Emacs secara otomatis menyalakan modifyOtherKeysfitur ketika mendeteksi bahwa terminal adalah versi xterm ≥216. Deteksi Emacs tentang urutan sekuensi untuk menyandikan kunci berfungsi melalui variabel local-function-key-map. Pada Emacs 24.4, tidak semua urutan pelarian didukung. Anda dapat menggunakan kode berikut dalam file init Anda untuk menyelesaikan pekerjaan.

;; xterm with the resource ?.VT100.modifyOtherKeys: 1
;; GNU Emacs >=24.4 sets xterm in this mode and define
;; some of the escape sequences but not all of them.
(defun character-apply-modifiers (c &rest modifiers)
  "Apply modifiers to the character C.
MODIFIERS must be a list of symbols amongst (meta control shift).
Return an event vector."
  (if (memq 'control modifiers) (setq c (if (or (and (<= ?@ c) (<= c ?_))
                                                (and (<= ?a c) (<= c ?z)))
                                            (logand c ?\x1f)
                                          (logior (lsh 1 26) c))))
  (if (memq 'meta modifiers) (setq c (logior (lsh 1 27) c)))
  (if (memq 'shift modifiers) (setq c (logior (lsh 1 25) c)))
  (vector c))
(defun my-eval-after-load-xterm ()
  (when (and (boundp 'xterm-extra-capabilities) (boundp 'xterm-function-map))
    (let ((c 32))
      (while (<= c 126)
        (mapc (lambda (x)
                (define-key xterm-function-map (format (car x) c)
                  (apply 'character-apply-modifiers c (cdr x))))
              '(;; with ?.VT100.formatOtherKeys: 0
                ("\e\[27;3;%d~" meta)
                ("\e\[27;5;%d~" control)
                ("\e\[27;6;%d~" control shift)
                ("\e\[27;7;%d~" control meta)
                ("\e\[27;8;%d~" control meta shift)
                ;; with ?.VT100.formatOtherKeys: 1
                ("\e\[%d;3u" meta)
                ("\e\[%d;5u" control)
                ("\e\[%d;6u" control shift)
                ("\e\[%d;7u" control meta)
                ("\e\[%d;8u" control meta shift)))
        (setq c (1+ c))))))
(eval-after-load "xterm" '(my-eval-after-load-xterm))

Jika TERMvariabel lingkungan tidak disetel ke xtermatau varian seperti itu xterm-256color, Emacs tidak akan mengaktifkan urutan itu. Jika Emacs sudah memiliki dukungan untuk nilai TERMAnda, Anda dapat menambahkan dukungan dengan mendefinisikan fungsi yang mirip dengan yang di atas, yang akan dieksekusi setelah memuat file Lisp yang namanya bernilaiTERM . Jika Emacs tidak memiliki dukungan seperti itu, Anda dapat menambahkannya dengan membuat subdirektori yang dipanggil termdi suatu tempat di Anda load-path, dan membuat file Lisp yang disebut dengan nilai di term/$TERM.elmana , mendefinisikan fungsi yang disebut .$TERMTERMterminal-init-$TERM

Saat saya menulis, tampaknya beberapa emulator terminal selain xterm telah mengadopsi urutan pelarian ini. Pada OSX, Anda dapat mengkonfigurasi iTerm2 dengan memilih urutan keluar untuk setiap kombinasi tombol, satu per satu.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
2
Jawaban Anda tentang hal ini selalu luar biasa, Gilles. Sangat dihargai.
phils
Besar!. Meskipun saya mengalami kesulitan menemukan cara membuat urxvt mengirimkan urutan tersebut. Bisakah Anda membantu saya :)
Amos
@Amos Saya tidak menggunakan rxvt. Anda harus bertanya pada Unix & Linux bagaimana membuat urxvt mengirim urutan pelarian yang sama seperti xterm dengan modifyOtherKeys.
Gilles 'SANGAT berhenti menjadi jahat'
tidak berfungsi pada macOS xterm-256color. M-C-%diakuiESC 5
LoranceChen
@ LoranceChen Itulah perilaku yang diharapkan jika modifyOtherKeysfitur tidak aktif. Perhatikan bahwa itu hanya didukung dalam versi xterm yang cukup baru, dan itu hanya diaktifkan secara otomatis sejak Emacs 24.4. Saya tidak tahu apakah OSX dikirimkan dengan versi terbaru. Jika tidak, dan tidak berfungsi untuk Anda, saya sarankan Anda mengajukan pertanyaan baru. Sebutkan versi yang Anda gunakan.
Gilles 'SANGAT berhenti menjadi jahat'
2

Jawaban Gilles menyatakan: On OSX, you can configure iTerm2 by selecting an escape sequence for each key combination, one by one. Saya mengalami sedikit kesulitan untuk sampai ke sana, jadi di sini penjelasan terperinci jika Anda seperti saya, bingung.

Jika, ketika menjalankan Emacs di terminal (mis., Terminal.app default Mac), C-x C-;tidak berjalan comment-line, dan Anda ingin fungsi itu, maka Anda harus beralih ke iTerm2 (Terminal.app tidak memiliki kemampuan) dan membuat Pemetaan Kunci di bawah Profil ... Kunci sebagai berikut:

^;     ^[[59;5u

Ini dilakukan dengan mengklik +tombol, yang memunculkan jendela kecil yang disebut "Pintasan Keyboard"; jendela ini awalnya memiliki dua bidang; bagian atas memiliki nilai "Klik untuk Mengatur" dan bagian bawah memiliki nilai "Abaikan." Klik tombol atas dan ketik C-;. Ini mengatur kombinasi tombol yang akan menjalankan aksi dan kode. Klik bidang bawah, "Aksi", dan temukan dan klik "Kirim Escape Urutan", yang turun sedikit lebih dari setengah jalan. Setelah Anda mengklik itu, bidang ketiga akan muncul, yang disebut "Esc +". Di dalam bidang ini, ketik:

[59;5u

Ini 59adalah kode ASCII desimal koma, dan 5kode untuk Ctrl. Lalu tekan "OK" untuk menyelesaikan. Kombo kunci yang benar ke urutan kunci sekarang akan dimasukkan dalam preferensi iTerm2. Ketika Anda memulai Emacs di iTerm, Anda sekarang akan memiliki akses ke C-x C-;fungsionalitas.

Biji pinus
sumber