aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
Diffstat (limited to 'lisp')
-rw-r--r--lisp/ChangeLog10
-rw-r--r--lisp/emacs-lisp/nadvice.el41
2 files changed, 31 insertions, 20 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 3f47c077f5c..0fa0c93915a 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,13 @@
12014-05-10 Stefan Monnier <monnier@iro.umontreal.ca>
2
3 * emacs-lisp/nadvice.el: Support adding a given function multiple times.
4 (advice--member-p): If name is given, only compare the name.
5 (advice--remove-function): Don't stop at the first match.
6 (advice--normalize-place): New function.
7 (add-function, remove-function): Use it.
8 (advice--add-function): Pass the name, if any, to
9 advice--remove-function.
10
12014-05-09 Philipp Rumpf <prumpf@gmail.com> (tiny change) 112014-05-09 Philipp Rumpf <prumpf@gmail.com> (tiny change)
2 12
3 * electric.el (electric-indent-post-self-insert-function): Don't use 13 * electric.el (electric-indent-post-self-insert-function): Don't use
diff --git a/lisp/emacs-lisp/nadvice.el b/lisp/emacs-lisp/nadvice.el
index 0e2536f8179..332d1ed61b6 100644
--- a/lisp/emacs-lisp/nadvice.el
+++ b/lisp/emacs-lisp/nadvice.el
@@ -183,9 +183,9 @@ WHERE is a symbol to select an entry in `advice--where-alist'."
183(defun advice--member-p (function name definition) 183(defun advice--member-p (function name definition)
184 (let ((found nil)) 184 (let ((found nil))
185 (while (and (not found) (advice--p definition)) 185 (while (and (not found) (advice--p definition))
186 (if (or (equal function (advice--car definition)) 186 (if (if name
187 (when name 187 (equal name (cdr (assq 'name (advice--props definition))))
188 (equal name (cdr (assq 'name (advice--props definition)))))) 188 (equal function (advice--car definition)))
189 (setq found definition) 189 (setq found definition)
190 (setq definition (advice--cdr definition)))) 190 (setq definition (advice--cdr definition))))
191 found)) 191 found))
@@ -209,8 +209,8 @@ WHERE is a symbol to select an entry in `advice--where-alist'."
209 (lambda (first rest props) 209 (lambda (first rest props)
210 (cond ((not first) rest) 210 (cond ((not first) rest)
211 ((or (equal function first) 211 ((or (equal function first)
212 (equal function (cdr (assq 'name props)))) 212 (equal function (cdr (assq 'name props))))
213 (list rest)))))) 213 (list (advice--remove-function rest function)))))))
214 214
215(defvar advice--buffer-local-function-sample nil 215(defvar advice--buffer-local-function-sample nil
216 "keeps an example of the special \"run the default value\" functions. 216 "keeps an example of the special \"run the default value\" functions.
@@ -232,6 +232,12 @@ different, but `function-equal' will hopefully ignore those differences.")
232 ;; This function acts like the t special value in buffer-local hooks. 232 ;; This function acts like the t special value in buffer-local hooks.
233 (lambda (&rest args) (apply (default-value var) args))))) 233 (lambda (&rest args) (apply (default-value var) args)))))
234 234
235(defun advice--normalize-place (place)
236 (cond ((eq 'local (car-safe place)) `(advice--buffer-local ,@(cdr place)))
237 ((eq 'var (car-safe place)) (nth 1 place))
238 ((symbolp place) `(default-value ',place))
239 (t place)))
240
235;;;###autoload 241;;;###autoload
236(defmacro add-function (where place function &optional props) 242(defmacro add-function (where place function &optional props)
237 ;; TODO: 243 ;; TODO:
@@ -267,8 +273,9 @@ a special meaning:
267 the advice should be innermost (i.e. at the end of the list), 273 the advice should be innermost (i.e. at the end of the list),
268 whereas a depth of -100 means that the advice should be outermost. 274 whereas a depth of -100 means that the advice should be outermost.
269 275
270If PLACE is a simple variable, only its global value will be affected. 276If PLACE is a symbol, its `default-value' will be affected.
271Use (local 'VAR) if you want to apply FUNCTION to VAR buffer-locally. 277Use (local 'SYMBOL) if you want to apply FUNCTION to SYMBOL buffer-locally.
278Use (var VAR) if you want to apply FUNCTION to the (lexical) VAR.
272 279
273If one of FUNCTION or OLDFUN is interactive, then the resulting function 280If one of FUNCTION or OLDFUN is interactive, then the resulting function
274is also interactive. There are 3 cases: 281is also interactive. There are 3 cases:
@@ -278,20 +285,18 @@ is also interactive. There are 3 cases:
278 `advice-eval-interactive-spec') and return the list of arguments to use. 285 `advice-eval-interactive-spec') and return the list of arguments to use.
279- Else, use the interactive spec of FUNCTION and ignore the one of OLDFUN." 286- Else, use the interactive spec of FUNCTION and ignore the one of OLDFUN."
280 (declare (debug t)) ;;(indent 2) 287 (declare (debug t)) ;;(indent 2)
281 (cond ((eq 'local (car-safe place)) 288 `(advice--add-function ,where (gv-ref ,(advice--normalize-place place))
282 (setq place `(advice--buffer-local ,@(cdr place)))) 289 ,function ,props))
283 ((symbolp place)
284 (setq place `(default-value ',place))))
285 `(advice--add-function ,where (gv-ref ,place) ,function ,props))
286 290
287;;;###autoload 291;;;###autoload
288(defun advice--add-function (where ref function props) 292(defun advice--add-function (where ref function props)
289 (let ((a (advice--member-p function (cdr (assq 'name props)) 293 (let* ((name (cdr (assq 'name props)))
290 (gv-deref ref)))) 294 (a (advice--member-p function name (gv-deref ref))))
291 (when a 295 (when a
292 ;; The advice is already present. Remove the old one, first. 296 ;; The advice is already present. Remove the old one, first.
293 (setf (gv-deref ref) 297 (setf (gv-deref ref)
294 (advice--remove-function (gv-deref ref) (advice--car a)))) 298 (advice--remove-function (gv-deref ref)
299 (or name (advice--car a)))))
295 (setf (gv-deref ref) 300 (setf (gv-deref ref)
296 (advice--make where function (gv-deref ref) props)))) 301 (advice--make where function (gv-deref ref) props))))
297 302
@@ -302,11 +307,7 @@ If FUNCTION was not added to PLACE, do nothing.
302Instead of FUNCTION being the actual function, it can also be the `name' 307Instead of FUNCTION being the actual function, it can also be the `name'
303of the piece of advice." 308of the piece of advice."
304 (declare (debug t)) 309 (declare (debug t))
305 (cond ((eq 'local (car-safe place)) 310 (gv-letplace (getter setter) (advice--normalize-place place)
306 (setq place `(advice--buffer-local ,@(cdr place))))
307 ((symbolp place)
308 (setq place `(default-value ',place))))
309 (gv-letplace (getter setter) place
310 (macroexp-let2 nil new `(advice--remove-function ,getter ,function) 311 (macroexp-let2 nil new `(advice--remove-function ,getter ,function)
311 `(unless (eq ,new ,getter) ,(funcall setter new))))) 312 `(unless (eq ,new ,getter) ,(funcall setter new)))))
312 313