Büyük mod bağlayıcılarını geçersiz kılma


38

Bazen global anahtar kelimelerim büyük bir mod tarafından geçersiz kılınır. Kolay bir örnek init dosyamda aşağıdaki ayardır

(global-set-key (kbd "C-j") 'newline-and-indent)

Ancak can sıkıcı bir şekilde bu anahtar bağlama, çizik arabelleğinin varsayılan modu olan "Lisp Etkileşim" ana modu tarafından gizlenir.

Kendimi büyük bir modun (veya küçük modun) global anahtarlığımı gizlediği bir durumda bulduğumda, onu nasıl geri alabilirim?

Not: My soru değil "Nasıl yapabilirim bağlama C-jiçin newline-and-indent'? Modunda'" Lisp Etkileşim Bazı büyük / küçük kipler tarafından gizlenen tuş takımlarıyla veya kullanıcı tuş takımlarıyla nasıl başa çıkılacağı konusunda daha genel bir cevap istiyorum.


Yanıtlar:


39

Kendi küçük kipinizi tanımlamak istemiyorsanız (ilk cevabımda bahsettiğim), aynı çözüm için "kısayol" yaklaşımı da var.

Sen yükleyebilir use-packageMelpa temin paketi ve make kullanımını bind-key*veya bind-keys*bir parçası makro bind-keyo gemileri ile paketin use-package.

Dokümantasyonundan bind-key.el:

;; If you want the keybinding to override all minor modes that may also bind
;; the same key, use the `bind-key*' form:
;;
;;   (bind-key* "<C-return>" 'other-window)

;; To bind multiple keys in a `bind-key*' way (to be sure that your bindings
;; will not be overridden by other modes), you may use `bind-keys*' macro:
;;
;;    (bind-keys*
;;     ("C-o" . other-window)
;;     ("C-M-n" . forward-page)
;;     ("C-M-p" . backward-page))

Herhangi birinin merak etmesi durumunda, bunun sadece perde arkasında küçük bir kip kullandığını unutmayın. emulation-mode-map-alistsÖnceliği zorlamak için kullanarak, diğer küçük modlarla çatışmalara farklı bir yaklaşım getirir.
phils

Bunu sadeliği nedeniyle cevap olarak işaretledim. Esasen bu cevabın aynısını yapıyor , ama sahne arkasındaki işlerin çoğunu rahatlıkla yapıyor.
nispio

@nispio Haklısın. Tecrübelerime göre, tek fark, küçük moddaki bağlantıları genel olarak diğer modları geçersiz kılmak için kullanılan yöntemdir. Ancak, diğer yaklaşımın avantajı (kendi küçük kipinize sahip olmanız), gerektiğinde (birkaç kez yapmam gerekiyorsa) orijinal emac bağlarını denemek için geçici olarak kapatabilirsiniz.
Kaushal Modi

1
(bind-key* "C-M-&" 'override-global-mode)İnitinize ekleyin ve genellikle bağlamaları hızlı bir şekilde yoldan çıkartabilirsiniz. Yana override-global-mode"global" minör modu değil, yine de başına tampon bazında devre dışı gerekir. Bu nedenle, kendinizi genel geçersiz kılma tuşlarını devre dışı bırakırken bulursanız, bu çözüm uygun değildir.
nispio

25

Kendi küçük modunuzu ve ana haritanızı tanımlayabilir ve diğer tüm modları (küçük + büyük) geçersiz kılabilirsiniz. İşte bu yüzden kendi küçük modumu yazmayı seçtim.

Anahtar ciltlemelerinizin tüm bağlantıları geçersiz kılma adımları:

  • Kendi küçük modunuzu ve ana haritanızı aşağıda gösterildiği gibi tanımlayın.
  • Küçük modunuzu global olarak etkinleştirin
  • (define-key my-mode-map (kbd "C-j") #'newline-and-indent)

Benzer şekilde, küçük modunuzda ayarlanan diğer anahtar bağlarınız, diğer modlardakileri geçersiz kılacaktır.

Küçük bir modun nasıl yazılacağı hakkında Christopher Wellons'un blog yazısını okumanı şiddetle tavsiye ederim . Bu blog ve birden nilfazla ana ve küçük modda birden fazla anahtar bağlama ayarlamak zorunda olmanın sıkıntısı, kendime ait olan küçük modumu yazmak için bana ilham verdi.

Bu yaklaşımı kullanmanın en iyi yanı, anahtar bağlamaların emacs'ın varsayılan yapılandırmasında ne yaptığını kontrol etmek istediğinizde, sadece küçük modunuzu kapatmanızdır; daha sonra tekrar açın ve özel anahtar bağlantılarınızı geri alın.

;; Main use is to have my key bindings have the highest priority
;; https://github.com/kaushalmodi/.emacs.d/blob/master/elisp/modi-mode.el

(defvar my-mode-map (make-sparse-keymap)
  "Keymap for `my-mode'.")

;;;###autoload
(define-minor-mode my-mode
  "A minor mode so that my key settings override annoying major modes."
  ;; If init-value is not set to t, this mode does not get enabled in
  ;; `fundamental-mode' buffers even after doing \"(global-my-mode 1)\".
  ;; More info: http://emacs.stackexchange.com/q/16693/115
  :init-value t
  :lighter " my-mode"
  :keymap my-mode-map)

;;;###autoload
(define-globalized-minor-mode global-my-mode my-mode my-mode)

;; https://github.com/jwiegley/use-package/blob/master/bind-key.el
;; The keymaps in `emulation-mode-map-alists' take precedence over
;; `minor-mode-map-alist'
(add-to-list 'emulation-mode-map-alists `((my-mode . ,my-mode-map)))

;; Turn off the minor mode in the minibuffer
(defun turn-off-my-mode ()
  "Turn off my-mode."
  (my-mode -1))
(add-hook 'minibuffer-setup-hook #'turn-off-my-mode)

(provide 'my-mode)

;; Minor mode tutorial: http://nullprogram.com/blog/2013/02/06/

5

Genel bir ciltlemenin ana mod ciltlemesini geçersiz kılması için, ciltlemeyi ana modda ayarlamanız yeterlidir nil:

(define-key my-major-mode-map (kbd "C-j") nil)

Global bağlamanın genel olarak tüm modlardan öncelikli olması mümkün değildir (aksi halde büyük modlara sahip olmanın anlamı yoktur), ancak en önemli bağlarınızla kendi küçük modunuzu oluşturarak etrafını kesebilirsiniz. O zaman en azından çoğu (hepsinde olmasa da) modlarından öncelikli olursunuz.


Bu herhangi bir keyfi ana mod için işe yarar mı? Başka bir deyişle, "foo-mode" denilen ana bir mod (define-key foo-mode (kbd "C-j") nil)kurarsam .emacs dosyama koyabilir ve çalışmasını bekleyebilir miyim?
nispio

Aslında olmasını istersiniz foo-mode-map(cevabımdaki örneğim kötüydü), ama evet, bu ana moddaki tuş takımını devre dışı bırakacak ve böylece global tuş takımının kullanılacağı yerine (onu kullanan farklı bir küçük mod yoksa).
shosti

Anahtar eşleminin foo-modeçağrılması oldukça evrensel foo-mode-mapmi?
nispio

@ nispio evet, bu modların büyük çoğunluğu için geçerlidir (dışarıda birkaç haydut olmasına rağmen).
shosti

0

Bu makroları kullanabilirsiniz:

(defmacro expose-global-keybinding (binding map)
  `(define-key ,map ,binding (lookup-key (current-global-map) ,binding)))

(defmacro expose-bindings (map bindings)
  `(dolist (bnd ,bindings)
     (expose-global-keybinding (kbd bnd) ,map)))

EDIT :

Aşağıdaki örneği kontrol edin:

Eğer keymap X global bağlayıcınızı Y geçersiz kılıyorsa, şunu yazın:

(expose-bindings X '("Y"))

Ve sonra geçersiz kılma 'geri alınacak' olacak.


Makronuz, backquote'u kullanmaktan faydalanırsınız: `(define-anahtar, harita, ciltleme (arama-anahtar (geçerli-global-harita), ciltleme))
Sigma

Makronun ne yaptığı ve nasıl kullanılacağı hakkında yorum yapabilir misiniz? Bana koddan belli değil.
nispio

İlk makro sadece küresel haritası anahtarı yukarı bakar ve sonucu atamak other mapyoluyla bağlanması dünya haritası açığa böylece other map. İkincisi, birincisini bir bağlama listesi için uygulamanıza izin verir.
Renan Ranelli

Çok yoğun olduğum için kusura bakma ama hala kullanımını tam olarak anlamadım. Kendi özel global anahtar haritamı tanımlamam gerekir mi? Küçük bir moda mı ait olmalı? expose-bindingsÖnce bunu gerçekleştirip sonra genel olarak bu anahtarları istediğim komutlara bağlayabilir miyim? Belki init dosyama bu çalışmasını sağlamak için ne koyabileceğime bir örnek gösterebilirsin.
nispio

2
Bu makro adlarının yanlış isim olduğuna dikkat edin. Onlar küresel bağlama "açığa" yok, ama bunun yerine çoğaltmak küresel bağlama. Gerçek global bağlanma değişirse, bu kopyalar değişmeyecektir.
phils
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.