Tất cả thông tin bạn cần được bao gồm trong C-h f add-function
đó mô tả cơ chế cơ bản của advice-add
.
Hệ thống tư vấn mới về cơ bản hoạt động như thay thế định nghĩa hiện tại của hàm bằng hàm được mô tả trong bảng
C-h f add-function
, tùy thuộc vào lựa chọn WHERE
đối số của bạn, chỉ sạch hơn để theo dõi hành vi nào đã được xác định trong tệp nguồn nào.
Một ví dụ với :around
tùy chọn
Trường hợp chung nhất là :around
tùy chọn, vì vậy tôi đưa ra một ví dụ cho điều đó. (Có thể tốt hơn để sử dụng WHERE
các tham số chuyên dụng khi có thể, nhưng bạn có thể thay thế các tham số khác bằng một :around
chức năng tương đương
).
Chỉ là một ví dụ, giả sử bạn muốn gỡ lỗi một số cách sử dụng find-file
và muốn vào print
danh sách đối số của nó mỗi khi nó được gọi. Bạn có thể viết
(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)
Với việc thực hiện mới này, mọi thứ mà lời khuyên cần được thông qua như là đối số. ad-get-args
trở nên không cần thiết, bởi vì các đối số được truyền cho hàm lời khuyên dưới dạng đối số hàm bình thường (đối với các
WHERE
đối số có ý nghĩa). ad-do-it
trở nên không cần thiết khi :around
lời khuyên trở thành đối số của hàm và đối số, do đó (ad-do-it)
được thay thế bằng biểu mẫu
(apply old-function arguments)
hoặc khi bạn đã đặt tên cho các đối số
(funcall old-function first-arg second-arg)
đó là sạch hơn vì không có hình thức ma thuật liên quan. Sửa đổi các đối số chỉ đơn giản xảy ra bằng cách chuyển các giá trị sửa đổi đến OLD-FUNCTION
.
Các WHERE
giá trị khác
Chuỗi tài liệu add-function
chứa một bảng gồm tất cả các vị trí tư vấn (hoặc "tổ hợp") và những gì chúng tương đương và giải thích chức năng theo cách lambda
hành xử tương đương với chức năng được tư vấn:
`: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')
trong đó FUNCTION là chức năng tư vấn và OLDFUN chức năng nơi lời khuyên được thêm vào. Đừng cố gắng hiểu tất cả chúng cùng một lúc, chỉ cần chọn một WHERE
biểu tượng nghe có vẻ phù hợp và cố gắng hiểu biểu tượng đó.
Hoặc chỉ sử dụng :around
. Theo như tôi có thể nói lợi thế duy nhất của việc sử dụng WHERE
s chuyên biệt :around
cho mọi thứ là bạn có thêm một chút thông tin từ việc tra cứu C-h f ADVISED-FUNCTION
trước khi đọc chuỗi tài liệu của lời khuyên. Trừ khi bạn có kế hoạch xuất bản mã chứa lời khuyên, nó có thể không quan trọng.
Chức năng tư vấn được đặt tên
Tôi khuyên bạn nên sử dụng các hàm được đặt tên như lời khuyên vì nó cung cấp nhiều lợi thế (một số trong số chúng cũng áp dụng cho việc sử dụng các hàm được đặt tên cho hook):
Nó hiện lên C-h f find-file
như
:around advice: `my-find-file-advice-print-arguments'
liên kết đến định nghĩa của chức năng tư vấn, như thường lệ chứa một liên kết đến tệp nơi nó được xác định. Nếu lời khuyên đã được định nghĩa là một lambda
biểu mẫu trực tiếp trong advice-add
biểu mẫu thì chuỗi doc sẽ được hiển thị nội tuyến (một mớ hỗn độn cho các tài liệu dài?) Và không có gì cho biết nó được định nghĩa ở đâu.
Bạn có thể xóa lời khuyên với
(advice-remove #'find-file #'my-find-file-advice-print-arguments)
Bạn có thể cập nhật định nghĩa về lời khuyên mà không cần chạy lại
advice-add
hoặc mạo hiểm để giữ phiên bản cũ hoạt động (vì chạy
advice-add
với thay đổi lambda
sẽ được công nhận là lời khuyên mới, không phải là cập nhật cho phiên bản cũ).
Side nhận xét Các #'function
ký hiệu về cơ bản là tương đương với
'function
, ngoại trừ việc nó giúp trình biên dịch byte xác định những biểu tượng như tên hàm và do đó để xác định các chức năng còn thiếu (ví dụ như do lỗi chính tả).
M-x report-emacs-bug
. Một số nhà phát triển đôi khi thích phát triển hơn tài liệu. ;-) Điều quan trọng là tài liệu của Emacs.