ข้อมูลทั้งหมดที่คุณต้องการรวมอยู่ในซึ่งอธิบายกลไกพื้นฐานของC-h f add-function
advice-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 จะต้องจัดทำเอกสารเอง