Bagaimana cara mengikat C- [nyata?

10

C-[setara dengan tombol escape pada keyboard Inggris AS, karenanya, segala upaya mengikatnya akan mengacaukan M-perilaku.

Emacs tampaknya tidak kesulitan membedakan <escape>dan C-[memisahkan dalam bingkai GUI. Berikut ini berfungsi dengan baik dan binding mulai dengan M-tetap berfungsi:

(global-set-key (kbd "<escape>") (lambda () (interactive) (message "<escape>")))

Namun, jika saya ikat

(global-set-key (kbd "C-[") (lambda () (interactive) (message "C-[")))

tiba-tiba emacs menjadi gila dan mengikat seperti M-xistirahat. Selain itu, menekan C-[menolak untuk memicu lambda yang terikat. Cukup menarik, C-x @ c [(berlaku kontrol pengubah untuk membuka braket) masih mengatakan C-[ is undefined.

Apakah ada cara mengikat sesuatu C-[tanpa melanggar emacs?

Kristóf Marussy
sumber

Jawaban:

7

Anda tidak dapat benar-benar mengubah C-[pengikatan di peta tingkat pengguna, seperti yang akan Anda lakukan global-set-key. Namun, Anda dapat mengubahnya sebagai acara keyboard sebelum mencapai keymaps tersebut. Anda bisa mengatakan misalnya:

(define-key input-decode-map 
    (kbd "C-[") 
    [control-bracketleft])

dan kemudian gunakan [control-bracketleft]diymap Anda. Cukup sederhana bukan?

Potongan direktor

Sayangnya, itu tidak sesederhana itu, dan solusi ini membutuhkan beberapa penyesuaian, yang akan tampak sangat menyakitkan. Anda sudah diperingatkan. Tapi mari kita lihat dulu mengapa peta tingkat pengguna tidak bisa menjawab pertanyaan. Berikut ini, saya merujuk pada manual Emacs Lisp untuk emacs 26.1 ketika saya mengatakan "melihat sesuatu" tanpa lebih presisi.

C-[ditafsirkan pada tahap sangat awal sebagai karakter kontrol ASCII ESC(lihat 21.7.1 - Acara Keyboard ). Kode ini tersebar di semua tempat sebagai awalan untuk urutan yang lebih lama. Ada alasan untuk itu: ESCsebenarnya adalah awalan meta (lihat meta-prefix-char), dan semua binding yang membaca M-sesuatu akan diterjemahkan ke urutan yang dimulai dengan ESC. Dengan demikian, mengubah peta global tidak akan cukup: pertama-tama Anda perlu mengubah meta-prefix-char, kemudian untuk memetakan kembali ESCke yang baru meta-prefix-chardi setiap peta yang digunakan M-sebelum Anda dapat memetakan dengan aman C-[.

Baiklah kalau begitu, tentu saja: mari kita gunakan input-decode-map. Ada beberapa peta serupa yang mungkin kita tergoda untuk menggunakan (lihat bagian 21.8.3 dan 22.14), tetapi mari kita tetap pada yang ini. Dan yah ... ini berhasil! Anda sudah selesai, bukan?

Sebenarnya, tidak, ceritanya tidak berakhir di sini. Ini berfungsi ... selama Anda menggunakan sistem jendela. Jika karena nasib buruk Anda dipenjara di konsol linux dalam keadaan darurat, Anda menyadari betapa dramatisnya situasinya: tombol panah Home, dan tentu saja M-binding, semuanya sampah. Mengapa? Karena ketika terminal mengatakan ESC(yang dilakukannya ketika Anda mengetik C-[), itu benar-benar berarti ESC , dan memulai urutan dari jenis yang sama yang digunakannya untuk mengirimkan karakter non-ASCII.

Mengamati bencana, Anda mungkin menganggap bijaksana untuk melindungi input-decode-mapmodifikasi di atas sedemikian rupa sehingga hanya diaktifkan jika sistem jendela mengendalikan keyboard:

(let ((frame (framep (selected-frame))))
  (or (eq  t  frame)
      (eq 'pc frame)

      (define-key input-decode-map 
                  (kbd "C-[") 
                  [control-bracketleft])
     )))

Terminal kemudian berfungsi seperti biasanya.

Sekarang, bisakah kita berurusan dengan C-[terminal? Sebenarnya, ya kita bisa, pada konsol linux dan juga pada emulator terminal lain yang bisa saya mainkan. Tapi itu membuat ceritanya cukup panjang, ketika karakter baru memasuki adegan. Karena tidak ada lagi emacs saja: terminal sekarang memiliki peran sentral.

Mari kita dengarkan apa yang dikatakan oleh konsol linux. Ketik C-vsebelum beberapa tombol untuk mendengarnya dengan jelas. C-[adalah ESC; begitu juga Esc. Panah suara seperti ESC [ A, sementara M-aini ESC A. Hmm ... Sepertinya ini keliling kunci meta di emacs bukan? Bagaimanapun.

Kecuali kita siap untuk memainkan beberapa trik berdasarkan waktu berlalu antara peristiwa karakter (yang dengan cara tidak akan membedakan Escdari C-[), tampaknya kita tidak punya pilihan selain untuk memberitahu konsol apa yang sebenarnya kita tidak berarti ESCsaat kita mengetik C-[. Selain itu, tampaknya segera bahwa C-[itu bukan satu-satunya masalah dengan kode terminal stok: pengubah sebagian besar waktu menghapus informasi yang dikirimkan. Kita perlu menyesuaikan terminal untuk alasan yang sama seperti kita menyesuaikan emacs: akan jauh lebih praktis jika kita lakukan.

Pada titik ini, Anda harus berani melihat ke dalam mata dokumentasi terminal Anda: halaman loadkeys(1)manual untuk konsol linux, untuk xterm xterm(1)di bagian Custom Key Bindings , dan apa pun-i-tidak-tahu untuk terminal lain. Di KDE konsole, Anda dapat menentukan terjemahan khusus di Pengaturan / Edit Profil Saat Ini ... lalu Keyboard . Berikut adalah kutipan dari ~/.local/share/konsole/Test.keytab setelah bermain dengan dialog yang terakhir ini:

key [+Ctrl+AnyModifier : "\EO*["

Setelah Anda memiliki send terminal ESC O 5 [untuk C-[(seperti dalam konfigurasi di atas), Anda dapat kembali ke emacs. Tentu saja, Anda belum selesai.

Untuk menginstruksikan emacs dialek apa yang digunakan terminal tertentu, Anda dapat menyesuaikan input-decode-map. Ya, ini kebetulan yang telah kami modifikasi di awal cerita ini, dan ini adalah yang paling term/xterm.elmenyentuh ketika xterm terlibat. Tempat yang baik untuk penyesuaian adalah tty-setup-hook(lihat bagian 40.1.3):

(add-hook 'tty-setup-hook 
   (lambda ()
    (let ((term (getenv "TERM")))
      (cond 
        (;; xterm-function-map not in doc, but in term/xterm.el
         (boundp 'xterm-function-map) 
         (map-my-term-codes xterm-function-map))

        ((equal term "linux")
         (map-my-term-codes input-decode-map))
        )
      )))

Ketahuilah bahwa kait ini hanya berfungsi jika Anda berada di terminal. Dengan demikian, Anda tidak dapat memasukkan kode inisialisasi sistem jendela di sini. Inilah fungsi terjemahannya sendiri:

(defun map-my-term-codes (map)
      (define-key map (kbd "M-O 5 [") 
                      [control-bracketleft])
      )

Dan kemudian Anda dapat beristirahat: ini adalah akhir dari perjalanan. Tentu saja, jika Anda tidak peduli dengan terminal, itu cepat karena Anda akan melewati semua bagian yang menyakitkan. Tapi Anda akan mengakui itu juga agak tidak lengkap.

Dua catatan akhir:

  • Saya memilih ESC O 5 [kode C-[. Ini hanya sebuah contoh: Saya tidak akan berpura-pura itu pilihan yang baik . Hanya 5 bagian, yang artinya C-, yang menuruti semacam konvensi yang sudah mapan

  • mengkonfigurasi konsol linux meninggalkan rasa yang tidak enak: sepertinya tidak mungkin untuk melakukan pengikatan tanpa menggunakan simbol perantara yang ada , dan yang saya perlukan tidak ada . Saya menggunakan simbol dalam F21- F246kisaran seperti dalam kebanyakan contoh internet, tetapi tidak sangat memuaskan. Tidak apa-apa untuk beberapa ikatan yang tidak terkait, tetapi tidak akan melayani skema sistematis.

Edit

  • Saya telah menyelesaikan ini dengan Esckasing - yang memiliki kepribadiannya sendiri - di pos lain: Cara menghapus binding ke kunci awalan ESC
  • di sini adalah bagian dari konfigurasi untuk diumpankan loadkeys. Saya meletakkan ini di /root/custom.kmap, dan memuatnya ketika saya perlu (yang jarang terjadi). Konfigurasi aktual saya juga memetakan panah dan kombinasi pengubah yang berbeda, tetapi agak panjang, pilihan simbol dan urutan dipertanyakan, dan saya tidak yakin kode kunci untuk keyboard saya akan cocok dengan Anda. Jadi mari kita tetap pada tingkatnya: ini hanyalah ilustrasi.

    keymaps 0-127
    
    # http://tldp.org/HOWTO/Keyboard-and-Console-HOWTO-15.html
    # web+man:keymaps
    # web+man:loadkeys
    
    # escape
    keycode  1  = F100
        alt keycode  1 = Escape # keep the Escape behavior somewhere          
    
    # keycode  26 = bracketleft
        control keycode 26 = F115 # Control_bracketleft does not exist          
    
    string F100     = "\033OO" # map this to [escape] in map-my-term-codes
    string F115     = "\033O5["
    
Champignac
sumber
1
Terima kasih, itu jawaban yang bagus. Tetapi tentunya jawaban yang bagus seperti ini tentu saja tidak perlu ditabrak ke atas halaman depan 34 kali. Setiap benjolan memiliki biaya kecil yang dibagi oleh komunitas: memeriksa spam, mencari apakah ada konten baru yang menarik, dll. Mungkin Anda bisa mengelompokkan perbaikan kecil bersama? Atau tetap dengan apa yang Anda miliki. Berbicara dari pengalaman, tidak ada yang namanya postingan yang sempurna, pada titik tertentu Anda hanya perlu melanjutkan.
Gilles 'SANGAT berhenti menjadi jahat'
@Gilles Mengerti, dan maaf untuk itu. Saya tidak menyadari ada beberapa masalah yang menyesuaikan hal ini sesuai keinginan.
Champignac
0

Solusi berikut ini agak kludky, tetapi tampaknya berhasil:

Biarkan ~/.xbindkeysrcberisi yang berikut ini:

"xvkbd -xsendevent -text '\[Control_L]\[F13]'"
  m:0x14 + c:34

"xvkbd -xsendevent -text '\[Control_L]\[F14]'"
  m:0x14 + c:35

Sekarang xbindkeysakan menerjemahkan C-[ke C-<f13>dan C-]ke C-<f14>, sehingga mereka dapat terikat dalam emacs secara bebas. Anda mungkin ingin mengikat abort-recursive-editsesuatu selain dari C-], misalnya C-S-g,.

Kelemahannya adalah bahwa sekarang C-[rusak di setiap aplikasi kecuali Emacs, yang dapat diperbaiki dengan menambahkan beberapa logika untuk menguji apakah kombinasi kunci dikirim ke emacs ...

Kristóf Marussy
sumber
FWIW, saya tidak berpikir ada sesuatu yang istimewa C-].
Malabarba
Ya, saya juga tidak, tetapi untuk beberapa alasan aneh C-]ikatan saya berhenti bekerja setelah saya menyalakan Xbindkeys, jadi saya juga rebound itu.
Kristóf Marussy