Assume there is a sample function defined in a library (this question's precondition is all definitions in this library cannot be modified, something like "read only"):
(defun sample ()
(foo)
(bar)
(baz))
I want to use this library, but the function sample cannot match my request, what I want is:
(defun sample ()
(foo)
(when condition
(bar))
(baz))
Someone told me to use defadvice, but I noticed that defadvice can only insert code before or after the invocations of sample, like:
(before-advice ...)
(sample)
(after-advice ...)
it cannot modify the definition of sample itself. So, how can I achieve this graciously? Should I have to rewrite a sample myself, called my-sample or sample2?
sds's answer works, except that you presumably only want to be advising bar when sample is executing, so you'd need to advise sample as well in order to activate and deactivate the advice for bar. My with-temporary-advice macro facilitates this:
(defmacro with-temporary-advice (function class name &rest body)
"Enable the specified advice, evaluate BODY, then disable the advice."
`(unwind-protect
(progn
(ad-enable-advice ,function ,class ,name)
(ad-activate ,function)
,#body)
(ad-disable-advice ,function ,class ,name)
(ad-activate ,function)))
(defadvice bar (around my-conditional-bar disable)
;; This advice disabled by default, and enabled dynamically.
(when condition
ad-do-it))
(defadvice sample (around my-sample-advice activate)
"Make execution of `bar' conditional when running `sample'."
(with-temporary-advice 'bar 'around 'my-conditional-bar
ad-do-it))
Note that if bar is also called in other ways while sample is executing, the advice will apply for those calls as well, so you should account for that if it's a possibility.
Alternatively, you may prefer to use flet to redefine bar when required. This is subject to the same caveat as the first solution, of course.
(defadvice sample (around my-sample-advice activate)
"Make execution of `bar' conditional when running `sample'."
(if condition
ad-do-it
(flet ((bar () nil))
ad-do-it)))
That's much simpler to read, but for reasons I don't understand flet is, as of Emacs 24.3, no longer in favour. Its docstring suggests using cl-flet instead, but as cl-flet uses lexical binding, that won't actually work. As best I could tell, it sounded like flet isn't actually going away, however the current recommendation seems to be to use advice instead.
Also note that if, inside bar, the unwanted behaviour depended on some variable, then it would be preferable to use a let binding on that variable instead of the flet binding on the function.
Edit:
These approaches do make it harder to see what is happening, of course. Depending upon the exact situation, it may well be preferable to simply redefine the sample function to do what you want (or to write a my-sample function to call in its place, as you suggested).
Others have already provided good answers, but since some complain about flet's disgrace, I'll show what I'd use:
(defvar my-inhibit-bar nil)
(defadvice bar (around my-condition activate)
(unless my-inhibit-bar ad-do-it))
(defadvice sample (around my-condition activate)
(let ((my-inhibit-bar (not condition)))
ad-do-it))
Look ma! No flet and no ugly activate/deactive! And when you C-h f bar it will clearly tell you that there's more than meets the eye. Also I'd actually use the new advice-add instead:
(defvar my-inhibit-bar nil)
(defun my-bar-advice (doit &rest args)
(unless my-inhibit-bar (apply doit args)))
(advice-add :around 'bar #'my-bar-advice)
(defun my-sample-advice (doit &rest args)
(let ((my-inhibit-bar (not condition)))
(apply doit args)))
(advice-add :around 'sample #'my-sample-advice)
You should advise function bar instead, using an around advice:
(defadvice bar (around my-condition)
(when condition
ad-do-it))
Related
I have a function:
(defun function-name (&optional args) ... <unknown content>)
I redefine it with
(defun function-name (&optional args) ... my own content)
Can I somehow after some time remove my own version of function-name and stay with the first one?
No, you cannot.
Save/Restore
You can save the definition yourself before redefining the function:
Common Lisp:
(defparameter *old-def* (fdefinition 'function-name))
(defun function-name ...)
...
(setf (fdefinition 'function-name) *old-def*)
Emacs Lisp:
(defconst *old-def* (symbol-function 'function-name))
(defun function-name ...)
...
(fset 'function-name *old-def*)
Reload
Or, if you know where the function was defined, you can reload the definition:
Common Lisp:
(load "file-name")
Emacs Lisp: same as above or M-x load-library RET.
Reeval
Or, if you know the original definition, you can reevaluate it, by pasting it at the Common Lisp prompt or by visiting the file with the definition in Emacs and evaluating the defun using C-M-x, as suggested by #Drew in a comment.
Note that it's risky to redefine other libraries' or Emacs' own functions, since you don't know what else depends on them working exactly as expected. If at all possible, use a different name. If not, provide copious documentation warning prominently about the redefinitions. Also, did you check first whether the existing function can be tweaked to your satisfaction using predefined hooks that run before or after it or by customizing any particular user options?
Not the way you do it, but you can get what you want by using an advice instead of a new definition. E.g.
(defadvice function-name (around my-overrride activate)
... my own content)
after the above you can recover the old behavior by deactivating the advice. Using the new advice system in Emacs-24.4 this would look like:
(defun my-function-name (&optional args) ... my own content)
(add-advice 'function-name :override #'my-function-name)
which can be reverted with
(remove-advice 'function-name #'my-function-name)
Once in a while I manually set the font-family and size different from the default, and I use buffer-face-mode to do it. (To be exact I use the mouse & pick one from the dialog box.) Once I set it, I'd like it to stay set for that buffer, even if I change modes, so I tried a customization. The idea was to add a change-major-mode-hook (which runs just before buffer-locals get killed) that would save the buffer face, if it is set, in a function to be called later- that much seems to work. But then that function seems to be called too soon, and when the mode change is over, buffer-face-mode is not active.
Here's the customization I cam up with so far
(defun my-preserve-bufface-cmmh ()
"Keep the state of buffer-face-mode between major-mode changes"
(if (and (local-variable-p 'buffer-face-mode) buffer-face-mode)
(delay-mode-hooks
(message "face is %s" buffer-face-mode-face) ; Just to show me it has the right face
(let ((my-inner-face buffer-face-mode-face))
(run-mode-hooks
(message "inner %s" my-inner-face) ; it still has the right face here
(setq buffer-face-mode-face my-inner-face)
(buffer-face-mode))))))
(add-hook 'change-major-mode-hook
'my-preserve-bufface-cmmh)
The messages both run and show a custom face, as they should, when I'm changing major-mode in a buffer with the minor-mode buffer-face-mode set. I had thought the combination of delay-mode-hooks ... run-mode-hooks would make setq buffer-face-mode-face ... (buffer-face-mode) run after the new mode was set up, but apparently not.
Is this customization "close"/salvageable for my wants? Is there a cleaner way?
The first thing is that delayed-mode-hooks is itself a local variable.
That means, if you set it by (delay-mode-hooks (run-mode-hooks ...)) in change-major-mode-hook
this will have no effect since it is killed instantaneously.
The second thing is that the stuff within your run-mode-hooks is
evaluated within my-preserve-bufface-cmmh. It should be defined as a back-quoted hook function
`(lambda () ...) where you splice in the values you want to keep.
The alternative would be to use lexical binding (which google).
The 2nd thing is demonstrated in the following example (to be evaluated step-by-step):
(defun test (str)
(let ((mytest (concat "hello " str)))
(add-hook 'my-own-hook `(lambda () (message "mytest:%S" ,mytest)))))
(test "you")
(run-hooks 'my-own-hook)
(test "world")
(run-hooks 'my-own-hook)
(put :myface 'test)
If you want to keep the font buffer-local you have to use a local variable that survives kill-all-local-variables such as buffer-file-name. You can hook a property there:
Edit: Even if the symbol has a buffer local value its properties are not buffer local. Thus, the previous approach did not work. Better: Create your own permanent buffer-local variable:
(defvar-local my-preserve-bufface nil
"Keep the state of buffer-face-mode between major-mode changes")
(put 'my-preserve-bufface 'permanent-local t)
(defun my-preserve-bufface-put ()
"Keep the state of buffer-face-mode between major-mode changes"
(and (local-variable-p 'buffer-face-mode)
buffer-face-mode
(setq my-preserve-bufface buffer-face-mode-face)))
(defun my-preserve-bufface-get ()
"Keep the state of buffer-face-mode between major-mode changes"
(and my-preserve-bufface
(setq buffer-face-mode-face my-preserve-bufface)
(buffer-face-mode)))
(add-hook 'change-major-mode-hook 'my-preserve-bufface-put)
(add-hook 'after-change-major-mode-hook 'my-preserve-bufface-get)
Thanks for the educational comments and especially the answer/example from #user2708138, which I am going to accept because it does answer the question.
Yet I am also going to answer my own question, since I did come up with working code that is a more general solution. I went down this path after finding I also wanted my font-size changes maintained and that they were from text-scale-mode, one more minor-mode to keep. This code reads a list of minor-modes to preserve, without my having to figure out which variables they use. (It isn't too hard for a human to figure them out, but I wanted to try having emacs do it).
Alas there is no function I know of to retrieve the variables used by a minor-mode, but the modes I'm interested in use the convention minor-mode-var-name, so this code just filters buffer-local variables for that pattern.
; Save & restore minor modes I wish to be "permanent" if set
(setq my-preserve-minor-modes '(buffer-face-mode text-scale-mode))
(defun my-preserve-minor-modes-cmmh ()
"Keep the state of desired-permanent minor modes between major-mode changes. Assumes that associated buffer-local minor-mode variables to save begin with `minor-mode-'"
(setq my-restore-minor-modes-acmmh nil)
(dolist (mm my-preserve-minor-modes)
(when (and (local-variable-p mm) (symbol-value mm))
(push mm my-restore-minor-modes-acmmh)))
(when my-restore-minor-modes-acmmh
(add-hook 'after-change-major-mode-hook 'my-restore-minor-modes-acmmh)
; Predicate-list showing if symbol starts with a preserved mode
(let ((mm-p-l `(lambda (locvar-nm)
(or ,#(mapcar (lambda (mm)
`(and (< ,(length (symbol-name mm))
(length locvar-nm))
(string-prefix-p ,(symbol-name mm)
locvar-nm)))
my-restore-minor-modes-acmmh)))))
; For each found minor mode, create fn to restore its buf-local variables
(dolist (locvar (buffer-local-variables))
(if (and (listp locvar) (funcall mm-p-l (symbol-name (car locvar))))
(push `(lambda()(setq ,(car locvar) ',(cdr locvar)))
my-restore-minor-modes-acmmh))))))
(defun my-restore-minor-modes-acmmh ()
"After major-mode change, restore minor-mode state, and remove self from hook. It restores state by calling the function stored in the variable my-restore-minor-modes-acmmh."
(remove-hook 'after-change-major-mode-hook 'my-restore-minor-modes-acmmh)
(dolist (restore-f my-restore-minor-modes-acmmh) (funcall restore-f)))
(add-hook 'change-major-mode-hook 'my-preserve-minor-modes-cmmh)
I did know about the permanent-local property but I wasn't sure about any unwanted side-effects... probably unwarranted paranoia on my part!
My answer could be improved if there is ever a way to get a list of variables for a minor mode, or by having the user specify an alist of variables per minor mode- in either case we wouldn't have to loop over buffer-local-variables anymore, and maybe simply making those all permanent-local would be all we need, simplifying the code quite a bit. Anyway, figuring all this out (with your help & looking at the fine manual) was quite educational.
How can I rename elisp macro? To be more accurate, I want make defun to be synonym to cl-defun.
I do not care about time or memory overhead.
Summary
I don't think you can do that - at least not easily.
Since cl-defun expands to defun, you will get an infinite macroexpand loop when using defun if you do the obvious (defalias 'defun 'cl-defun).
The is a way...
So what you need to do is
save the original defun: (fset 'defun-original (symbol-function 'defun)).
copy the definition of cl-defun in cl-macs.el, replacing defun with defun-original.
replace defun with cl-defun using defalias: (defalias 'defun 'cl-defun).
Now, at least, if things go sour, you can restore the original behavior with (fset 'defun (symbol-function 'defun-original)).
...but you don't want it
However, I think you don't really want to do that.
If you want to use a Common Lisp, use it. Trying to pretend that you can turn Elisp into CL will cause you nothing but grief. I tried to travel that road 15 years ago - there is no fun there. It should be easier now, at least there is lexical binding, but I still don't think it is worth the effort.
If you want to extend Emacs, then using cl-defun makes even less sense: your extensions will be useless for others and you won't even be able to ask for help because few people will bother with such a radical change in such a basic functionality for such a tiny gain.
In general, you can make a synonym very simply with (defalias 'foo 'cl-defun).
But the expansion of a call to cl-defun uses defun, so if you do (defalias 'defun 'cl-defun) you'll get into infinite loops.
You can probably get what you want by replacing defun with a macro which either does what defun does or what cl-defun does, depending on whether the cal uses cl-defun features or not. E.g. using advice-add (which is in Emacs's trunk; you can use defadvice in older Emacsen to get simlar results) it could look something like the untested code below:
(defun my-defun-dispatch (doit name args &rest body)
(let ((needs-cl nil))
(dolist (arg args)
(unless (and (symbolp arg)
(or (not (eq ?& (aref (symbol-name arg) 0)))
(memq arg '(&optional &rest))))
(setq needs-cl t)))
(if needs-cl
`(cl-defun ,name ,args ,#body)
(funcall doit name args body))))
(advice-add :around 'defun 'my-defun-dispatch)
Any particular reason?
Maybe it's safe to do, and I'm sure it's possible, but I'm very dubious that you should be attempting it in the first place if you can't figure out how to go about it. I don't mean that as any kind of insult; I just suspect that a fundamental change like this could easily cause problems, so you ought to have a solid handle on elisp first before trying it.
I realise that's a bit of a non-answer, but I thought it was worth saying.
FYI cl-defun is defined in terms of defun.
I would like to temporarily override the kill-new function. I have a way I want to reimplement kill-new that works in only in certain contexts, but I don't want to reimplement a special version of kill-region on top of that. (kill-new is called from kill-region)
Since Emacs Lisp uses dynamic scoping, this should be possible, right? (On the other hand, it seems that this would be an unsafe thing to support, and it might make me a bit nervous knowing that it is possible...)
I have experimented with using let and fset, but so far have found no way to get it to work as expected. So, hopefully someone can fill in the blank in the following pseudocode:
(defun my-kill-new (string &optional replace yank-handler)
(message "in my-kill-new!"))
(defun foo ()
(some-form-that-binds-a-function (kill-new my-kill-new)
(kill-region (point) (mark))))
What should some-form-that-binds-a-function be? Or am I barking up the wrong tree?
Your some-form-that-binds-a-function is called flet, so you were close.
Here is a solution:
(defadvice kill-new (around my-kill-new (string &optional replace yank-handler))
(message "my-kill-new!"))
(defun foo ()
(progn (ad-enable-advice 'kill-new 'around 'my-kill-new)
(ad-activate 'kill-new)
(kill-region (point) (mark))
(ad-disable-advice 'kill-new 'around 'my-kill-new)
(ad-activate 'kill-new)))
Look at the advice package, which is very good at doing all of this.
I'm a big fan of ido-mode, so much so that I would like to use it for things like describe-function or find-tag and so on, without having to write something like in "Can I get ido-mode-style completion for searching tags in Emacs?" for each one.
Both
(defalias completing-read ido-completing-read)
and
(setf 'completing-read 'ido-completing-read)
don't work, at least partly because ido-completing-read calls completing-read in its body, so any simple redefinition would result in infinite recursion.
In theory, it should be possible, since the first line of the docstring for ido-completing-read is "Ido replacement for the built-in completing-read." I've looked around a bit and can't seem to find anyone else who has attempted or succeeded at it.
I realize that Icicles probably provides something like this, and I may end up going with that anyway, but it is a bit more of a plunge than I care to take right now.
Thanks for any help.
Edit: This is now an Emacs package available from MELPA. It has been expanded into a full-fledged minor mode. Development happens on GitHub.
Original post:
Here is my refinement of Jacobo's answer. Credit to him for the original magic. I've added an override variable, which you can use to prevent the use of ido-completing-read in specific functions. I have also added a check that uses the original completing-read if there are no completions (This happens occasionally, for example in org-remember-apply-template from org-mode, which breaks with Jacobo's original advice).
(defvar ido-enable-replace-completing-read t
"If t, use ido-completing-read instead of completing-read if possible.
Set it to nil using let in around-advice for functions where the
original completing-read is required. For example, if a function
foo absolutely must use the original completing-read, define some
advice like this:
(defadvice foo (around original-completing-read-only activate)
(let (ido-enable-replace-completing-read) ad-do-it))")
;; Replace completing-read wherever possible, unless directed otherwise
(defadvice completing-read
(around use-ido-when-possible activate)
(if (or (not ido-enable-replace-completing-read) ; Manual override disable ido
(boundp 'ido-cur-list)) ; Avoid infinite loop from ido calling this
ad-do-it
(let ((allcomp (all-completions "" collection predicate)))
(if allcomp
(setq ad-return-value
(ido-completing-read prompt
allcomp
nil require-match initial-input hist def))
ad-do-it))))
Oh, and for using ido in M-x, use amx.
Hocus pocus, abracadabra, presto!
(defadvice completing-read
(around foo activate)
(if (boundp 'ido-cur-list)
ad-do-it
(setq ad-return-value
(ido-completing-read
prompt
(all-completions "" collection predicate)
nil require-match initial-input hist def))))
That works with everything but subr's, from which execute-extended-command is the one that matters (what is binded to M-x). But we can get what we want from M-x
(global-set-key
"\M-x"
(lambda ()
(interactive)
(call-interactively
(intern
(ido-completing-read
"M-x "
(all-completions "" obarray 'commandp))))))
I don't think ido-mode is ready for this quite yet. In particular, ido-completing-read currently only works with strings, while completing-read supports alists as well. This is very important once you want to have a different user-level description of the items you want to complete on.
Therefore I am not surprised that it doesn't work out of the box, yet. Short of modifying the code yourself your best bet is probably to just file a bug report/feature request.
Ido comes with a function that should do this, so just call it in your .emacs file:
(ido-everywhere t)
Using Emacs 24.3, ido-ubiquitous didn't work for me. So tried this and it is working fine so far:
(defun my-completing-read (prompt collection &optional predicate
require-match initial-input
hist def inherit-input-method)
(if (listp collection)
(ido-completing-read prompt collection predicate require-match
initial-input hist def inherit-input-method)
(completing-read-default prompt collection predicate require-match
initial-input hist def inherit-input-method)))
(setq completing-read-function 'my-completing-read)
Just a thought: have you tried editing ido-completing-read to call original-completing-read instead of completing-read, defining original-completing-read to be the current completing-read and then doing your defalias or setf thing?