ข้อมูลทั้งหมดที่คุณต้องการรวมอยู่ในซึ่งอธิบายกลไกพื้นฐานของC-h f add-functionadvice-add
ระบบคำแนะนำใหม่โดยทั่วไปจะทำหน้าที่แทนการนิยามคำจำกัดความปัจจุบันของฟังก์ชันด้วยฟังก์ชันที่อธิบายไว้ในตาราง
C-h f add-functionโดยขึ้นอยู่กับการเลือกWHERE
อาร์กิวเมนต์ที่คุณเลือกเท่านั้นที่สะอาดกว่าเพื่อติดตามพฤติกรรมที่กำหนดไว้ในไฟล์ต้นฉบับ
ตัวอย่างพร้อม:aroundตัวเลือก
กรณีทั่วไปมากที่สุดคือ:aroundตัวเลือกดังนั้นฉันให้ตัวอย่างสำหรับสิ่งนั้น (น่าจะดีกว่าถ้าใช้WHEREพารามิเตอร์เฉพาะเมื่อเป็นไปได้ แต่คุณสามารถแทนที่กันด้วย:aroundฟังก์ชันที่เทียบเท่า
)
ตัวอย่างเช่นสมมติว่าคุณต้องการดีบักการใช้งานบางอย่างfind-file
และต้องการprintรายการอาร์กิวเมนต์ทุกครั้งที่มีการเรียกใช้ คุณสามารถเขียน
(defun my-find-file-advice-print-arguments (old-function &rest arguments)
"Print the argument list every time the advised function is called."
(print arguments)
(apply old-function arguments))
(advice-add #'find-file :around #'my-find-file-advice-print-arguments)
ด้วยการใช้งานใหม่นี้ทุกสิ่งที่ความต้องการของคำแนะนำจะถูกส่งเป็นอาร์กิวเมนต์ ad-get-argsไม่จำเป็นเนื่องจากอาร์กิวเมนต์จะถูกส่งผ่านไปยังฟังก์ชันคำแนะนำเหมือนกับอาร์กิวเมนต์ของฟังก์ชันปกติ (สำหรับ
WHEREอาร์กิวเมนต์ที่สมเหตุสมผล) ad-do-itกลายเป็นไม่จำเป็นตาม:aroundคำแนะนำที่ได้รับเป็นอาร์กิวเมนต์ฟังก์ชั่นและข้อโต้แย้งจึง(ad-do-it)ถูกแทนที่ด้วยแบบฟอร์ม
(apply old-function arguments)
หรือเมื่อคุณตั้งชื่อข้อโต้แย้ง
(funcall old-function first-arg second-arg)
ซึ่งสะอาดกว่าเนื่องจากไม่มีรูปแบบเวทมนตร์ที่เกี่ยวข้อง การแก้ไขข้อโต้แย้งเกิดขึ้นเพียงแค่ส่งค่าที่แก้ไขไปOLD-FUNCTIONแล้ว
WHEREค่าอื่น ๆ
docstring ของadd-functionมีตารางของสถานที่ให้คำแนะนำทั้งหมด (หรือ "combinators") และสิ่งที่พวกเขาจะเทียบเท่าและอธิบายการทำงานในแง่ของlambdaพฤติกรรมเทียบเท่ากับฟังก์ชั่นที่แนะนำ:
`:before' (lambda (&rest r) (apply FUNCTION r) (apply OLDFUN r))
`:after' (lambda (&rest r) (prog1 (apply OLDFUN r) (apply FUNCTION r)))
`:around' (lambda (&rest r) (apply FUNCTION OLDFUN r))
`:override' (lambda (&rest r) (apply FUNCTION r))
`:before-while' (lambda (&rest r) (and (apply FUNCTION r) (apply OLDFUN r)))
`:before-until' (lambda (&rest r) (or (apply FUNCTION r) (apply OLDFUN r)))
`:after-while' (lambda (&rest r) (and (apply OLDFUN r) (apply FUNCTION r)))
`:after-until' (lambda (&rest r) (or (apply OLDFUN r) (apply FUNCTION r)))
`:filter-args' (lambda (&rest r) (apply OLDFUN (funcall FUNCTION r)))
`:filter-return'(lambda (&rest r) (funcall FUNCTION (apply OLDFUN r)))
(cited from `C-h f add-function')
โดยที่ FUNCTION เป็นฟังก์ชันคำแนะนำและ OLDFUN เป็นฟังก์ชันที่เพิ่มคำแนะนำไว้ อย่าพยายามทำความเข้าใจกับพวกเขาทั้งหมดในครั้งเดียวเพียงเลือกWHEREสัญลักษณ์ที่ฟังดูเหมาะสมและพยายามเข้าใจสิ่งนั้น
:aroundหรือการใช้งานเพียงแค่ เท่าที่ผมสามารถบอกได้เปรียบเพียงอย่างเดียวของการใช้ความWHEREเหนือ:aroundสำหรับทุกสิ่งที่คุณได้รับข้อมูลอีกเล็กน้อยจากการมองขึ้นC-h f ADVISED-FUNCTION
ก่อนที่จะมีการอ่าน docstring ของคำแนะนำที่ นอกจากว่าคุณวางแผนที่จะเผยแพร่รหัสที่มีคำแนะนำมันอาจไม่สำคัญ
ฟังก์ชั่นคำแนะนำที่มีชื่อ
ฉันขอแนะนำให้ใช้ฟังก์ชั่นที่มีชื่อเป็นคำแนะนำเนื่องจากมันมีข้อดีหลายประการ (บางฟังก์ชั่นเหล่านี้ยังใช้กับการใช้ฟังก์ชั่นที่มีชื่อสำหรับ hooks):
มันแสดงให้เห็นในC-h f find-fileฐานะ
:around advice: `my-find-file-advice-print-arguments'
การลิงก์ไปยังนิยามของฟังก์ชันคำแนะนำซึ่งตามปกติจะมีลิงก์ไปยังไฟล์ที่มีการกำหนดไว้ หากคำแนะนำถูกกำหนดเป็นlambdaแบบฟอร์มโดยตรงในadvice-add
แบบฟอร์ม docstring จะแสดงแบบอินไลน์ (เป็นระเบียบสำหรับ docstrings ยาว?) และไม่มีอะไรจะระบุว่ามันถูกกำหนดไว้ที่ไหน
คุณสามารถลบคำแนะนำด้วย
(advice-remove #'find-file #'my-find-file-advice-print-arguments)
คุณสามารถอัปเดตคำจำกัดความของคำแนะนำได้โดยไม่ต้องเรียกใช้ซ้ำ
advice-addหรือเสี่ยงต่อการใช้งานเวอร์ชันเก่า (เนื่องจากการรัน
advice-addด้วยการเปลี่ยนแปลงlambdaจะได้รับการยอมรับว่าเป็นคำแนะนำใหม่
หมายเหตุ Side#'functionสัญกรณ์เป็นพื้นเทียบเท่ากับการ
'functionยกเว้นว่ามันช่วยให้คอมไพเลอร์ไบต์ระบุสัญลักษณ์ชื่อฟังก์ชั่นและทำให้การแจ้งฟังก์ชั่นที่ขาดหายไป (เช่นเนื่องจากการพิมพ์ผิด)
M-x report-emacs-bugรายงานข้อผิดพลาด: นักพัฒนาบางคนชอบที่จะพัฒนามากกว่าการทำเอกสาร ;-) เป็นสิ่งสำคัญที่ Emacs จะต้องจัดทำเอกสารเอง