प्रमुख मोड बाइंडिंग को ओवरराइड कैसे करें


38

कभी-कभी मेरी ग्लोबल कीबाइंडिंग एक प्रमुख विधा द्वारा ओवरराइड होती है। एक आसान उदाहरण मेरी इनिट फ़ाइल में निम्नलिखित सेटिंग है

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

लेकिन नाराज़गी से यह कीबाइंडिंग "लिस्प इंटरेक्शन" प्रमुख मोड द्वारा छिपी हुई है जो कि स्क्रैच बफर का डिफ़ॉल्ट मोड है।

जब मैं खुद को ऐसी स्थिति में पाता हूं जहां एक प्रमुख मोड (या मामूली मोड) मेरी वैश्विक कीबाइंडिंग को छिपा रहा है, तो मैं इसे कैसे वापस ले सकता हूं?

नोट: मेरा प्रश्न नहीं है "कैसे कर सकते हैं मैं बाँध C-jके लिए newline-and-indent?" मोड "में" लिस्प इंटरेक्शन मैं इस बारे में बहुत अधिक सामान्य उत्तर में दिलचस्पी लेता हूं कि कैसे कीमैप्स से निपटने के लिए जो क्लैश या उपयोगकर्ता कीबाइंडिंग जो किसी प्रमुख / लघु मोड द्वारा छिपी हो।


जवाबों:


39

यदि आप अपने स्वयं के मामूली मोड को परिभाषित नहीं करना चाहते हैं, तो उसी समाधान के लिए "शॉर्टकट" दृष्टिकोण भी है (जो मैं अपने पहले उत्तर में बात करता हूं)।

आप स्थापित कर सकते हैं use-packageMelpa से पैकेज उपलब्ध है और का उपयोग करें bind-key*या bind-keys*मैक्रो का भाग है जो bind-keyपैकेज है कि जहाज के साथ use-package

के प्रलेखन से 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))

यदि कोई भी उत्सुक है, तो ध्यान दें कि यह सिर्फ पर्दे के पीछे एक मामूली मोड का उपयोग करता है। emulation-mode-map-alistsपूर्ववर्ती व्यवस्था को लागू करने के लिए अन्य मामूली तरीकों के साथ टकराव के लिए यह एक अलग दृष्टिकोण लेता है)।
फिल्स

मैंने इसकी सरलता के कारण इसे उत्तर के रूप में चिह्नित किया है। यह अनिवार्य रूप से इस उत्तर के रूप में एक ही काम कर रहा है , लेकिन यह पर्दे के पीछे से आपके लिए अधिकतर काम आसानी से कर रहा है।
nispio

@nispio आप सही हैं। मेरे अनुभव से एकमात्र अंतर वह विधि है जिसका उपयोग मामूली मोड बाइंडिंग को विश्व स्तर पर अन्य मोड को ओवरराइड करने के लिए किया जाता है। लेकिन दूसरे दृष्टिकोण का लाभ (अपनी खुद की मामूली विधा होने का) यह है कि यदि आप कभी भी ज़रूरत हो तो मूल एमएसीएस बाइंडिंग को आज़माने के लिए इसे पल-पल बंद कर सकते हैं (मुझे ऐसा करने की ज़रूरत है)।
कौशल मोदी

1
(bind-key* "C-M-&" 'override-global-mode)अपने init में जोड़ें , और आप आमतौर पर अपने रास्ते से बाइंडिंग को जल्दी से निकाल सकते हैं यदि आपको आवश्यकता है। चूंकि override-global-mode"वैश्विक" मामूली मोड नहीं है, इसलिए आपको इसे प्रति-बफर आधार पर निष्क्रिय करना होगा। इसलिए यदि आप खुद को अक्सर वैश्विक ओवरराइड कुंजियों को निष्क्रिय करते हुए पाते हैं तो यह समाधान सुविधाजनक नहीं है।
nispio

25

आप अपने स्वयं के मामूली मोड और इसके मुख्य मानचित्र को परिभाषित कर सकते हैं और अन्य सभी मोड (मामूली + प्रमुख) को ओवरराइड कर सकते हैं। इसीलिए मैंने अपनी छोटी विधा लिखने का विकल्प चुना।

आपकी कुंजी बाइंडिंग के चरण सभी बाइंडिंग को ओवरराइड करते हैं:

  • नीचे दिखाए गए अनुसार अपने स्वयं के मामूली मोड और मुख्य मानचित्र को परिभाषित करना।
  • विश्व स्तर पर अपने मामूली मोड को सक्रिय करें
  • (define-key my-mode-map (kbd "C-j") #'newline-and-indent)

इसी तरह आपके अन्य मोड में सेट की गई आपकी अन्य बाइंडिंग अन्य मोड्स में ओवरराइड हो जाएगी।

मैं एक मामूली मोड लिखने के तरीके पर क्रिस्टोफर वेलन्स द्वारा ब्लॉग पोस्ट पढ़ने की अत्यधिक सलाह देता हूं । यह ब्लॉग प्लस को nilकई प्रमुख और लघु मोड में कई प्रमुख बाइंडिंग सेट करने की झुंझलाहट से प्रेरित करता है और मुझे अपनी खुद की मामूली मोड लिखने के लिए प्रेरित करता है।

इस दृष्टिकोण का उपयोग करने का सबसे अच्छा हिस्सा यह है कि जब आप यह जांचना चाहते हैं कि इमैक के डिफ़ॉल्ट कॉन्फ़िगरेशन में मुख्य बाइंडिंग क्या करते हैं, तो आप बस अपने मामूली मोड को बंद कर देते हैं; फिर आप इसे वापस चालू करते हैं और आपको अपने कस्टम कुंजी बाइंडिंग वापस मिल जाते हैं।

;; 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

एक वैश्विक बाइंडिंग को एक प्रमुख मोड बाइंडिंग से अलग करने के लिए, बस बाइंडिंग को nilप्रमुख मोड में सेट करें:

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

वैश्विक बंधन को सामान्य रूप से सभी तरीकों से पहले लेना संभव नहीं है (अन्यथा प्रमुख मोड होने का कोई मतलब नहीं होगा), लेकिन आप अपने सबसे महत्वपूर्ण बाइंडिंग के साथ अपना खुद का मामूली मोड बनाकर इसके चारों ओर हैक कर सकते हैं। तब आपके पास कम से कम पहले (हालांकि जरूरी नहीं कि सभी) मोड पर प्राथमिकता हो।


क्या यह किसी भी प्रमुख प्रमुख मोड के लिए काम करेगा? दूसरे शब्दों में, अगर मैं "फू-मोड" नामक एक प्रमुख मोड स्थापित करता हूं तो मैं (define-key foo-mode (kbd "C-j") nil)अपनी .emacs फ़ाइल में डाल सकता हूं और यह काम करने की उम्मीद कर सकता हूं?
nispio

वास्तव में आप चाहते हैं कि यह हो foo-mode-map(उत्तर में मेरा उदाहरण खराब था), लेकिन हां, यह कीबाइंडिंग को प्रमुख मोड में अक्षम कर देगा, इसलिए वैश्विक कीबाइंडिंग का उपयोग इसके बजाय किया जाएगा (जब तक कि एक अलग मामूली मोड का उपयोग न किया जाए)।
20

क्या यह काफी सार्वभौमिक है कि केमैप को foo-modeकहा जाएगा foo-mode-map?
nispio

@nispio हाँ, यह बहुत सारे मोड के लिए सही है (हालाँकि वहाँ कुछ बदमाश हैं)।
शोस्ती

0

आप इन मैक्रो का उपयोग कर सकते हैं:

(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)))

संपादित करें :

उदाहरण bellow की जाँच करें:

यदि कीमैप X आपकी वैश्विक बाइंडिंग Y को ओवरराइड कर रहा है, तो आप लिखते हैं:

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

और फिर ओवरराइड 'पूर्ववत' हो जाएगा।


आपके मैक्रो को आप बैककौट का उपयोग करने से लाभान्वित होते हैं: `(परिभाषित-की, मानचित्र, बाइंडिंग (लुक-की-करेंट-वर्तमान-वैश्विक-मानचित्र), बाइंडिंग)
सिग्मा

क्या आप टिप्पणी कर सकते हैं कि मैक्रो क्या कर रहा है, और इसका उपयोग कैसे करना है? यह मेरे लिए कोड से स्पष्ट नहीं है।
nispio

पहला मैक्रो सिर्फ वैश्विक मानचित्र में कुंजी दिखता है और परिणाम को असाइन करता है other map, इस प्रकार, वैश्विक मानचित्र बाइंडिंग को उजागर करता है other map। दूसरा केवल आपको बाइंडिंग की सूची के लिए पूर्व को लागू करने देता है।
रेनन रनेली

क्षमा करें यदि मैं सघन हो रहा हूं, लेकिन मैं अभी भी उपयोग को पूरी तरह से नहीं समझता हूं। क्या मुझे अपने विशेष वैश्विक कीमैप को परिभाषित करने की आवश्यकता है? क्या यह एक मामूली मोड से संबंधित है? क्या मैं expose-bindingsपहले प्रदर्शन करता हूं , और फिर विश्व स्तर पर उन कुंजियों को बाध्य करता हूं जो मुझे चाहिए? हो सकता है कि आप इस काम को करने के लिए अपने इनिट फ़ाइल में जो कुछ डाल सकते हैं उसका एक उदाहरण दिखा सकते हैं।
nispio

2
ध्यान दें कि ये मैक्रो नाम गलत हैं। वे वैश्विक बंधन को "उजागर" नहीं करते हैं, बल्कि वे वैश्विक बंधन की नकल करते हैं। यदि वास्तविक वैश्विक बाध्यकारी परिवर्तन होता है, तो ये डुप्लिकेट प्रतियां नहीं होंगी।
फिल्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.