Nadvice.el में तर्क सूची में हेरफेर कैसे करें?


12

से इसे जारी रखते हुए नई सलाह सिस्टम के बारे में एक और प्रश्न का उत्तर :

पुरानी शैली में advice.el, एक सलाह दी गई फ़ंक्शन की तर्क सूची के अलग-अलग सदस्यों को हेरफेर करना संभव था, बिना उन सदस्यों के बारे में कोई भी अनुमान लगाए बिना ऐसा हेरफेर नहीं किया गया था। उदाहरण के लिए, निम्नलिखित सलाह:

(defadvice ansi-term (around prompt-for-name last)
  (let ((name (read-from-minibuffer "Tag: ")))
    (and (not (string= name ""))
         (ad-set-arg 1 (concat "Term: " name)))
    ad-do-it))

ansi-termकॉल करने के लिए बफर-नाम तर्क के वैकल्पिक (वैकल्पिक) प्रावधान की अनुमति देता है , जबकि ansi-termअभी भी अपने स्वयं के संवादात्मक रूप के अनुसार संकेत देकर अपना पहला तर्क प्राप्त करेगा।

(बाद के संदर्भ के लिए, ansi-termहस्ताक्षर है (PROGRAM &optional BUFFER-NAME), और इसका इंटरैक्टिव रूप कई संभावित चूक के साथ PROGRAM के लिए संकेत देता है, लेकिन BUFFER-NAME के ​​बारे में कुछ भी नहीं करता है।)

मुझे यकीन नहीं है कि यह संभव है या नहीं nadvice.el। यदि यह है, तो मुझे यकीन नहीं है कि यह कैसे किया जा सकता है। मुझे सलाह दी गई फ़ंक्शन की तर्क सूची को बदलने के कुछ तरीके मिले हैं ।

उदाहरण के लिए, * info * (elisp) से सलाह कॉम्बिनेटर :

`:filter-args'
 Call FUNCTION first and use the result (which should be a list) as
 the new arguments to pass to the old function.  More specifically,
 the composition of the two functions behaves like:
      (lambda (&rest r) (apply OLDFUN (funcall FUNCTION r)))

अन्य कॉम्बिनेटर समान क्षमता प्रदान करते हैं, और उनमें से सामान्य धागा वह है, जबकि किसी फ़ंक्शन की तर्क सूची को प्रतिस्थापित किया जा सकता है, छोटा किया जा सकता है, विस्तारित किया जा सकता है, एट अल हो सकता है, बिना सूची में दिए गए स्थान पर तर्क को संशोधित करने के लिए फ़ंक्शन सलाह के लिए कोई स्पष्ट तरीका नहीं है बाकी के बारे में कुछ भी कहना

चर्चा के तहत मामले में, यह सलाह लेखक के लिए ansi-termकेवल एक बफर नाम को पारित करने के लिए असंभव प्रतीत होता है , क्योंकि ऐसी सूची का निर्माण संभव नहीं है जिसका मूल्य 1 में है, लेकिन कुछ भी नहीं, nilस्थिति में भी नहीं है । 0. सामान्य मामले में, यह सलाह लेखक के लिए स्थिति 0 से परे तर्कों को मनमाने ढंग से संशोधित करने के लिए असंभव प्रतीत होता है।

यह उसी में दुर्भाग्यपूर्ण लगता है, इसी तरह के प्रभाव का उत्पादन करने के लिए, कोड-पेस्ट को कॉपी करना आवश्यक है: विशेष रूप से, या तो मैं ansi-termसंवादात्मक रूप को कॉपी कर सकता हूं और इसे अपने स्वाद तक बढ़ा सकता हूं, या मैं ansi-termपूरी तरह से कॉपी कर सकता हूं और इसी तरह बढ़ा सकता हूं। या तो मामले में, मुझे अब अपनी इनिट फ़ाइल में एमएसीएस लिस्प वितरण का हिस्सा फिर से परिभाषित करना होगा, जो मुझे स्थायित्व और सौंदर्यशास्त्र दोनों के संदर्भ में अवांछनीय बनाता है।

मेरा सवाल यह है कि: क्या इस प्रकार की तर्क सूची के साथ काम किया जा सकता है nadvice.el? यदि हां, तो कैसे?


3
आप एएनआई-टर्म के शीर्ष पर अपनी खुद की इंटरेक्टिव कमांड को परिभाषित क्यों नहीं करते हैं? मुझे लगता है कि यहाँ बेहतर समाधान है।
चंद्रग्रहण

1
बेशक, मुझे ऐसा करने से कुछ भी नहीं रोक रहा है, लेकिन यह एक दशक के लायक मांसपेशी की स्मृति के बेहतर हिस्से को बदलने की आवश्यकता होगी, जो मैं कर सकता हूं तो मैं बचना चाहूंगा।
एरोन मिलर

जवाबों:


5

यह उसी में दुर्भाग्यपूर्ण लगता है, एक समान प्रभाव उत्पन्न करने के लिए, कोड को कॉपी-पेस्ट करना आवश्यक है: [...] मैं ansi-termइंटरैक्टिव रूप से कॉपी कर सकता हूं

इसके विपरीत, मुझे लगता है कि सलाह दी गई फ़ंक्शन के इंटरैक्टिव रूप को कॉपी-पेस्ट करना एक अच्छा विचार होगा, भले ही आपको वास्तव में यहां ऐसा करने की आवश्यकता न हो।

मैंने आपको ऊपर से नीचे तक सवाल पढ़ा। जब मुझे कोड-ब्लॉक मिला तो मैंने अनुमान लगाया कि आपकी सलाह शायद बफर नाम को बदल रही है। लेकिन मुझे नहीं पता था कि आपने बाद में हस्ताक्षर के रूप में एक टिप्पणी प्रदान की थी।

विचाराधीन मामले में, सलाह लेखक के लिए ansi-termकेवल एक बफर नाम पारित करना असंभव प्रतीत होता है , क्योंकि ऐसी सूची का निर्माण करना संभव नहीं है जिसका मूल्य 1 में है, लेकिन nilस्थिति 0 में भी कुछ नहीं है ।

वास्तव में कुछ भी नहीं से कम कुछ भी नहीं है। :-) लेकिन यहाँ शायद ही प्रासंगिक है।

जैसा कि आप उद्धृत दस्तावेज़ में देख सकते हैं, सलाह द्वारा लौटाए गए मूल्य का उपयोग सलाहित फ़ंक्शन के तर्क के रूप में किया जाता है। वापसी का मूल्य उन तर्कों की एक सूची होना चाहिए जो न केवल बदल गए हैं।

पुरानी सलाह के अनुसार जितना संभव हो सके रहें, यह वह है जो आपको उपयोग करना होगा nadvice:

(defun ansi-term--tag-buffer (args)
  ;; As npostavs pointed out we also have to make sure the list is
  ;; two elements long.  Which makes this approach even more undesirable.
  (when (= (length args) 1)
    (setq args (nconc args (list nil))))
  (let ((name (read-from-minibuffer "Tag: ")))
    (and (not (string= name ""))
         (setf (nth 1 args) (concat "Term: " name))))
  args)

(advice-add 'ansi-term :filter-args 'ansi-term--tag-buffer)

लेकिन मैं आपको इसके बजाय सलाह को परिभाषित करने की सलाह देता हूं:

(defun ansi-term--tag-buffer (program &optional buffer-name)
  (list program
        (let ((tag (read-from-minibuffer "Tag: ")))
          (if (string= tag "")
              buffer-name
            (concat "Term: " tag)))))

यह संस्करण वास्तव में आत्म-व्याख्यात्मक है।


1 प्रकार के लिए आपको argsकॉल जैसी स्थिति में सूची का विस्तार करने की आवश्यकता होती है (ansi-term "foo"), अन्यथा (setf (nth 1 args)...कोई त्रुटि होगी।
npostavs

हाँ तुम सही हो। दूसरे संस्करण का उपयोग करने का एक अन्य कारण - पहले में एक बग ;-) प्रदर्शन के उद्देश्य के लिए देता है, बस मान लें कि buffer-nameयह अनिवार्य है।
तारसियस

"इसके विपरीत, मुझे लगता है कि सलाह दी गई फ़ंक्शन के इंटरैक्टिव रूप को कॉपी-पेस्ट करना एक अच्छा विचार होगा" - ऐसा क्यों? कॉपी-पेस्टिंग कोड हर दूसरे मामले में बहुत बुरा विचार है; यहाँ क्यों नहीं?
हारून मिलर

वास्तव में मुझे नहीं लगता कि "कॉपी-पेस्ट" इस मामले में सही शब्द है, मैंने सिर्फ इसलिए इसका इस्तेमाल किया क्योंकि आपने किया था। लेकिन यहां तक ​​कि अगर उस शब्द का यहां उपयोग करना उचित था, तो "कॉपी-पेस्ट न करें" केवल एक पूर्ण नियम नहीं है। अन्य अनुमान, जो मुझे लगता है कि यहां लागू होते हैं, "चर और तर्कों को सार्थक नाम देते हैं" और "जब आपके पास किसी चीज़ को जटिल करने या क्रिया करने के बीच कोई विकल्प होता है, तो क्रिया के साथ जाएं"।
तारसियस

1
उम, वास्तव में, यह अभी भी टूटा हुआ है, :filter-argsसलाह को एक एकल तर्क मिलता है जो कि सलाह दी गई फ़ंक्शन के लिए args की एक सूची है, इसलिए 1 संस्करण को छोड़ देना चाहिए &restऔर 2 वें संस्करण को अच्छे नाम प्राप्त करने के लिए कुछ प्रकार के विनाशकारी निर्माण का उपयोग करना होगा।
npostavs

3

यहाँ है कि मैं यह कैसे करूँगा:

(defun my-ansi-term-prompt-for-name (orig-fun program
                                     &optional buffer-name &rest args)
  (apply orig-fun program
         (or buffer-name
             (let ((name (read-string "Tag: ")))
               (and (> (length name) 0)
                    (concat "Term: " name))))
         args))
(advice-add 'ansi-term :around #'my-ansi-term-prompt-for-name)

जबकि मैं एक था जिसने :filter-argsमुझे व्यक्तिगत रूप से पेश किया, यह शायद ही कभी सुविधाजनक लगता है।

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