问题
In my .emacs file, I have:
(defadvice narrow-to-region (around test activate)
(message "advice")
ad-do-it)
When I call narrow-to-region, the advice runs and prints 'advice' before narrowing.
When I call narrow-to-defun, it does not.
I found where narrow-to-defun is defined - in lisp.el, and re-evaluated the function. At this point, the advice started running.
What could cause this?
回答1:
The problem is, apparently, due to byte-compilation and therefore the inability to advise the narrowing primitives (narrow-to-region
is the primitive, narrow-to-defun
calls narrow-to-region
).
The following post on Null Program ("The Limits of Emacs Advice") goes into detail about this problem. Here's the shortish version from deep in the post:
It turns out
narrow-to-region
is so special -- probably because it's used very frequently -- that it gets its own bytecode. The primitive function call is being compiled away into a single instruction. This means my advice will not be considered in byte-compiled code. Darnit. The same is true forwiden
(code 126).
As to why the advice started working after you re-evaluated narrow-to-defun
: I'm guessing it's because you ended up replacing the byte-compiled version when you re-evaluated.
回答2:
@Dan described the problem well. Here is some info that might help you work around it.
What you can do is to advise (or to redefine) also narrow-to-defun
(and perhaps narrow-to-page
), so it acts similarly.
FWIW, I do something similar in library wide-n.el (see Multiple Narrowings).
I advise narrow-to-region
. But I also redefine narrow-to-defun
and narrow-to-page
. In all 3 cases I make the same change, to record the details of each narrowing so you can return to them later. Here is the advice, for example:
(defadvice narrow-to-region (before push-wide-n-restrictions activate)
"Push the region limits to `wide-n-restrictions'.
You can use `C-x n x...' to widen to previous buffer restrictions."
(when (or (interactive-p) wide-n-push-anyway-p)
(wide-n-push (ad-get-arg 0) (ad-get-arg 1)))) ; Args START and END.
And here is the relevant part of the narrow-to-defun
redefinition:
...
(goto-char end)
(re-search-backward "^\n" (- (point) 1) t)
(when (or (interactive-p) wide-n-push-anyway-p) (wide-n-push beg end)) ; <=====
(narrow-to-region beg end))))
来源:https://stackoverflow.com/questions/25246901/advice-only-applies-in-all-cases-after-function-calling-advised-function-is-re-e