Ci'yi TAB'dan farklı olarak nasıl bağlayabilirim?


16

Ben yapmak istiyorum Control-igerçekleştirmek indent-region(Xcode zaten kas hafızası inşa etti temelde beri).

Bunu fark ediyorum Control-ive tabAscii anlamında ayırt edilemez, ama onlar anahtar kod anlamında.

Açık olanı denedim:

(global-unset-key (kbd "C-i"))
(global-set-key (kbd "C-i") 'indent-region)

boşuna - tuşa basmak Control-ihala tabanahtarın mevcut bağlamda ne yaptığını yapar. Emacs'ın sekme düğmesini farklı şekilde kullanmasına yardımcı olmak için yapabileceğim bir şey var mı Control-i?

Güncelleme: Sanırım bir bölge seçildiğinde a tab/ press'in yaptıklarını yeniden eşleştirerek eşdeğer bir sonuç elde edilebilir Control-i.


1
Bu bir GUI çerçevesinden mi yoksa terminal çerçevesinden mi? Bir terminal için geçersiz kılabilir misin bilmiyorum.
14'te

İyi Q, GUI çerçevesi genellikle, ancak sunuculara uzak çalışıyorum ve bazen bir terminalde emacs kullanıyorum (git-paylaşımlı emacs.d ile elbette :)
Mark Aufflick

Yanıtlar:


15

Bu bir terminalden elde edilebilir sanmıyorum, ama GUI modunda bunu deneyebilirsiniz:

(define-key input-decode-map [?\C-i] [C-i])
(global-set-key (kbd "<C-i>") 'indent-region)

Ben de aynı şeyi yapıyorum C-mkiRET

DÜZENLE:

GUI veya TTY modunda olsanız aşağıdakiler işe yaramalıdır:

;; Unbind <C-i> from the TAB key and bind it to indent-region.
;; Since TAB and <C-i> cannot be differentiated in TTY emacs,
;; the workaround is to conditionally bind TAB to indent-region
;; when there is an active region selected.
(if (window-system)
  ; IF we are not in a TTY, unbind C-i from TAB
    (progn
      (define-key input-decode-map [?\C-i] [C-i])
      ; ... and remap it to indent-region
      (global-set-key (kbd "<C-i>") 'indent-region))
  ; ELSE IF we are in a TTY, create a replacement for TAB
  (defun my/tab-replacement (&optional START END)
    (interactive "r")
    (if (use-region-p)
      ; IF active region, use indent-region
        (indent-region START END)
      ; ELSE IF no active region, use default tab command
      (indent-for-tab-command)))
  ; Bind our quick-and-dirty TAB replacement to the TAB key
  (global-set-key (kbd "TAB") 'my/tab-replacement))

Güzel değil, ama işi yapıyor gibi görünüyor. Bu kodda gerekli düzeltmeleri veya düzenlemeleri memnuniyetle karşılıyoruz.


1
Mükemmel çalışıyor! ++ bir emacs
stackexchange

Sadece düşündüm sadece küçük bir sorun şimdi bir pencere sistemi ile başlatılan bir Emacs karşı bir terminal emacsclient getirebilir (ki bazen yapmak). Herhangi bir gecikme görmezsem, sekme değiştirme işlevini her durumda kullanacağım.
Mark Aufflick

1
Sadece eklemek istiyorum <C-i>ve [C-i]benzeri, keyfi bir tanımlayıcı olabilirdi <foobar>ve [foobar]ve çalışma hala olur; sadece arama tabya dabackspace
xdavidliu

Ben içine yanıta Düzenlenen kod parçasını eklemiş .emacsdosyanın ama hem TABve C-ibir remapped :-( @nispio
alper

@alper, Büyük olasılıkla bu , yüklendiğiniz anda (window-system)döndürülen anlamına gelir . Bunun nedeni grafiksel olmayan bir Emacs örneği çalıştırmanız veya bir Emacs arka plan programı çalıştırmanız olabilir. nil.emacs
nispio

13

GUI çerçeveleri

GUI çerçevelerinde (X11, Windows, OSX, ... olsun) Emacs, Tabtuşu tabişlev tuşu olarak okur . Ancak, Tabterminallerdeki tuş geleneksel olarak ^I( Control + I) karakterini gönderdiğinden , Emacs tabişlev tuşunu, görüntülenen Control + I karakterine (karakter 9) çevirir TAB. Bu çeviri ile yapılır function-key-map.

Benzer bir çeviri diğer bazı işlev tuşlarında da gerçekleşir. ( BackspaceVe Deletebir olan dikenli bir vaka burada ayrıntılı olarak tartışmak değildir.)

Function key    Translated to character         Notes
                Number  Name  Decomposition
backspace       127     DEL   Ctrl+?            May be translated to C-h instead
tab               9     TAB   Ctrl+I
linefeed         10     LFD   Ctrl+J            Few keyboards have this key
return           13     RET   Ctrl+M
escape           27     ESC   Ctrl+[

Eğer ayırmak istiyorsanız Tabden Ctrl+ Itamamen, dan bağlama kaldırmak function-key-map:

(define-key function-key-map [tab] nil)

Ancak bu çok kullanışlı değildir, çünkü içindeki girdiler function-key-mapmoda özgü tuş haritalarındaki veya global haritadaki bağlamalar tarafından geçersiz kılınır. Eğer farklı bir bağlayıcı tanımlamak istiyorsanız Yani tab, sadece bunu (elisp içinde değil etkileşimli istemi okuma anahtar geçerlidir çünkü function-key-mapsen yeniden bağlama bitirmek istiyorum böylece çeviri TABdeğil tab):

(global-set-key [tab] '…)
(define-key some-mode-map [tab] '…)

TabAnahtarın eylemini değiştiren tüm standart modlar, + tuş kombinasyonu tarafından oluşturulan karakterin TABtakma adı olan anahtarı değiştirerek bunu yapar . Standart bağlamalar yerine bunun yerine uygulanmasını istiyorsanız , tuş haritalarını tek başına bırakın ve modlandırın ve bunun yerine + tuşunu farklı bir anahtara yeniden yönlendirin .C-iCtrlItabC-ifunction-key-mapCtrlI

(define-key input-decode-map [(control ?i)] [control-i])
(define-key input-decode-map [(control ?I)] [(shift control-i)])
(define-key some-mode-map [control-i] '…)

Şimdi Emacs Ctrl+ ' Iyı " <control-i>(çevrildi TAB)" olarak rapor edecek . Bu hoş değil, ama kaçınılmaz: TABEmacs kaynak kodunda yerleşik olarak 9 karakterinin güzel yazdırılması .

Terminal çerçeveleri

Terminal çerçevelerinde sorun daha zor ve çoğu zaman imkansızdır. Terminaller anahtar iletmez, karakter iletir (daha doğrusu, aslında bayt iletir). TabControl + I, tuş kombinasyonu aynı ne - Anahtar sekme karakteri olarak iletilir Ctrl+ Iüretir. Karşılık gelen karakteri olmayan işlev tuşları (imleç tuşları gibi) çıkış dizileri olarak iletilir, yani ESC= Control + [ ile başlayan karakter dizileri (bu nedenle Emacs escapebir önek tuşu olarak tanımlanır - ESCbir önek olmalıdır). Bkz. Klavye girişi ve metin çıkışı nasıl çalışır? daha fazla arka plan için.

Fonksiyon tuşları için farklı tuş dizileri gönderecek şekilde yapılandırılabilen birkaç terminal vardır, ancak çok değil. Hem LeoNerd'in libtermkey / libtickit hem de Thomas Dickey'nin xterm (sürüm 216'dan beri) bunu destekliyor. Xterm'de özellik isteğe bağlıdır ve modifyOtherKeyskaynak aracılığıyla etkinleştirilir . Ancak, bunu destekleyen xterm dışında herhangi bir popüler terminal emülatörü, özellikle libvte üzerine inşa edilmiş birçok emülatör bilmiyorum . Bazı terminal emülatörleri, bunu anahtar kodlardan kaçış dizilerine kadar kullanıcı tanımlı bir yazışma yoluyla manuel olarak yapmanızı sağlar.

Bu mekanizma, sadece tab / Ci, return / Cm ve escape / C- [değil, birçok tuş kombinasyonunun ayırt edilmesini sağlar. Bkz terminali kullanırken keybinding Sorunları daha ayrıntılı bilgi için.

Temel xterm özelliği Emacs 24.4'ten beri desteklenmektedir. Ancak temelleri (özellikle Tab, Return, Escape, Backspaceo en hangi uygulamalara bekliyoruz çünkü) hala geleneksel kontrol karakterleri göndermek. Ctrl+ ' letterNın kontrol karakteri yerine bir kaçış dizisi gönderdiği bir mod vardır . Bu nedenle, işlev tuşlarını CtrlEmacs 24.4'teki kombinasyonlardan ayırmak için modifyOtherKeys, kaynağı 1 yerine 2 olarak ayarlayarak bu modu kullanma desteğini değiştirin .

;; xterm with the resource ?.VT100.modifyOtherKeys: 2
;; 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))
    ;; Override the standard definition to set modifyOtherKeys to 2 instead of 1
    (defun xterm-turn-on-modify-other-keys ()
      "Turn the modifyOtherKeys feature of xterm back on."
      (let ((terminal (frame-terminal)))
        (when (and (terminal-live-p terminal)
                   (memq terminal xterm-modify-other-keys-terminal-list))
          (send-string-to-terminal "\e[>4;2m" terminal))))
    (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;3~" meta)
                ("\e\[%d;5~" control)
                ("\e\[%d;6~" control shift)
                ("\e\[%d;7~" control meta)
                ("\e\[%d;8~" control meta shift)))
        (setq c (1+ c)))))
  (define-key xterm-function-map "")
  t)
(eval-after-load "xterm" '(my-eval-after-load-xterm))

"Emacs 24.24" ne zaman demek istediniz? "Emacs 24.4"?
tarsius

1
@tarsius Başlangıç ​​dosyamdan kopyalanan koddaki bir yorum “24.4” diyor, bu yüzden doğru olduğunu düşünüyorum ve bu cevap için yazdığım metindeki “24.24” “24.4” için bir yazım hatasıydı.
Gilles 'SO- kötü olmayı bırak
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.