emacs एलीस्प: सशर्त कुंजीबाइंडिंग परिवर्तित करें




elisp (4)

मैं एक कस्टम टैब पूरा करने का कार्यान्वयन लिखने की कोशिश कर रहा हूं जो उस बिंदु के आधार पर अलग-अलग पूर्णता का एक गुच्छा का प्रयास करता है। हालांकि, यदि पूर्णता के लिए कोई भी शर्तें पूरी नहीं हुई हैं तो मैं चाहता हूं कि वह टैब जो मौजूदा मोड को मूल रूप से करना है, करना है।

कुछ इस तरह:

(defun my-custom-tab-completion ()
  (interactive)
  (cond
   (some-condition
    (do-something))
   (some-other-condition
    (do-something-else))
   (t
    (do-whatever-tab-is-supposed-to-do-in-the-current-mode))) ;; How do I do this?

वर्तमान में मैं विशिष्ट मोड की जाँच कर रहा हूं और उस मोड के लिए सही काम कर रहा हूं, लेकिन मुझे वाकई ऐसा समाधान चाहिए जो मेरे बिना उस विशिष्ट मोड की शर्त को स्पष्ट रूप से जोड़ने के बिना सही काम करता है

यह कैसे करने के लिए कोई विचार?

धन्यवाद! / एरिक


बाइंडिंग के लिए सक्रिय कुंजीमैप की जांच करने के लिए आप key-binding (या इसके अधिक विशिष्ट प्रकारों की global-key-binding , minor-mode-key-binding और local-key-binding ) जैसे कार्यों का उपयोग कर सकते हैं

उदाहरण के लिए:

(call-interactively (key-binding (kbd "TAB")))
;; in an emacs-lisp-mode buffer:
;;    --> indent-for-tab-command
;; 
;; in a c++-mode buffer with yas/minor-mode:
;;    --> yas/expand

असीमित छोरों से बचने का एक तरीका यदि आपका आदेश टैब से जुड़ा होता है तो आपकी बाध्यता को एक छोटे से मोड में लगाया जा सकता है, और टैब बाइंडिंग की तलाश करते समय अस्थायी रूप से अपने कीमैप को अक्षम कर सकते हैं:

(define-minor-mode my-complete-mode
  "Smart completion"
  :keymap (let ((map (make-sparse-keymap)))
            (define-key map (kbd "TAB") 'my-complete)
            map))

(defun my-complete ()
  (interactive)
  (message "my-complete")
  (let ((my-complete-mode nil))
    (call-interactively (key-binding (kbd "TAB")))))

यह संभव है कि आप बिना किसी विशेष कार्य-समाधान के बिना इसे प्राप्त कर सकें। अधिकांश मोड TAB में डिफ़ॉल्ट रूप से इंडैेंडेशन होता है, लेकिन यदि आप वैश्विक चर tab-always-indent को 'complete करने के लिए सेट करते हैं तो यह पहले पूरा करने का प्रयास करेगा, और यदि पूरा नहीं हो सकता है तो इंडेंट। यह आमतौर पर वास्तव में अच्छी तरह से काम करता है, यद्यपि यदि TAB आपके प्रमुख तरीकों में से किसी अन्य कमांड में बाध्य है तो आप भाग्य से बाहर हो सकते हैं।

यदि वह आपको आवश्यक मोड में काम करता है, तो आपको बस अपनी कस्टम पूर्णता कार्य को सभी लागू बफ़र्स (संभवतः एक मोड हुक) का उपयोग करके सूची completion-at-point-functions के सामने जोड़ना होगा। completion-at-point कमांड प्रत्येक फ़ंक्शन को completion-at-point-functions में सूचीबद्ध करते हुए कॉल completion-at-point-functions जब तक कि उनमें से कोई भी नॉन- nil लौटाता है, इसलिए आपको अपने कस्टम पूर्णता कार्य को करने की ज़रूरत है "मौजूदा आदान-प्रदान" से मौजूदा व्यवहार में वापस आना है इसे से nil

यह प्रश्न का 100% जवाब नहीं है, लेकिन यदि आप जिन प्रमुख तरीकों से काम कर रहे हैं वे सामान्य दिशानिर्देशों के अनुसार लिखे गए हैं, यह साफ तरीके से हो सकता है।


यहां एक मैक्रो है जो कि एमासिक की बाध्यकारी फ़ॉलबैक के आधार पर लिखा गया है ताकि कबाइंडिंग को सशर्त रूप से परिभाषित किया जा सके। यह निर्दिष्ट छोटे मोड में कीबाइंडिंग जोड़ता है लेकिन यदि स्थिति सही नहीं है, तो पहले की नियत क्रिया निष्पादित की गई है:

(defmacro define-key-with-fallback (keymap key def condition &optional mode)
  "Define key with fallback. Binds KEY to definition DEF in keymap KEYMAP, 
   the binding is active when the CONDITION is true. Otherwise turns MODE off 
   and re-enables previous definition for KEY. If MODE is nil, tries to recover 
   it by stripping off \"-map\" from KEYMAP name."
  `(define-key ,keymap ,key
     (lambda () (interactive)
        (if ,condition ,def
          (let* ((,(if mode mode
                     (let* ((keymap-str (symbol-name keymap))
                            (mode-name-end (- (string-width keymap-str) 4)))
                       (if (string= "-map" (substring keymap-str mode-name-end))
                           (intern (substring keymap-str 0 mode-name-end))
                         (error "Could not deduce mode name from keymap name (\"-map\" missing?)")))) 
                  nil)
                 (original-func (key-binding ,key)))
            (call-interactively original-func))))))

तब मैं निम्नलिखित की तरह बातें कर सकता हूँ, खासकर टैब के लिए विशेष बंधन का उपयोग करने के लिए जब मैं आउटलाइन-मामूली-मोड में एक शीर्ष लेख में हूं अन्यथा मेरी डिफ़ॉल्ट कार्रवाई (मेरे पास दोनों इंडेंट और यसनिपेट्स हैं) निष्पादित हैं:

(define-key-with-fallback outline-minor-mode-map (kbd "TAB") 
  (outline-cycle 1) (outline-on-heading-p))

define-key उद्धृत स्ट्रिंग या इंटरैक्टिव लैम्ब्डा जैसे इस उदाहरण में स्वीकार कर सकते हैं।

;Static
(define-key evil-normal-state-mapr "m" 'evil-motion-state)
;Conditional
(define-key evil-normal-state-map "m" 
  (lambda () (interactive) (message "%s" major-mode)))

लैम्ब्डा को नामित फ़ंक्शंस से बदल दिया जा सकता है जैसे कि मेरी-टैब-पूर्णता और अधिक प्रभावी ढंग से इस्तेमाल किया गया।

परिभाषित-कुंजी के डॉकस्ट्रिंग (25 Emacs) से

DEF is anything that can be a key's definition:
 nil (means key is undefined in this keymap),
 a command (a Lisp function suitable for interactive calling),
 a string (treated as a keyboard macro),
 a keymap (to define a prefix key),
 a symbol (when the key is looked up, the symbol will stand for its
    function definition, which should at that time be one of the above,
    or another symbol whose function definition is used, etc.),
 a cons (STRING . DEFN), meaning that DEFN is the definition
    (DEFN should be a valid definition in its own right),
 or a cons (MAP . CHAR), meaning use definition of CHAR in keymap MAP,
 or an extended menu item definition.
 (See info node `(elisp)Extended Menu Items'.)




elisp