2

During the compilation of sources, I would like GNU Make to call an emacs defun. For this I have 2 options:

  • Start a new emacs instance, and load the desired function and call it.
  • Call the defun from the emacsclient like:

    emacsclient --eval "(my-emacs-defun)"
    

The latter has the advantage, it is faster, because the emacs server is already running and has the desired defun loaded.

But this also has a disadvantage, if (message ...) is called from (my-emacs-defun), it interrupts my active emacs session. I could try to modify (my-emacs-defun) so (message ...) isn't called, but is really hard when using emacs built-in functions.

Therefore I would like to know how to suppress the (message ...) from (my-emacs-defun). Is it possible to alter the (message ...) behavior when being called (my-emacs-defun)? Can I use(defadvice)` for this?

EDIT The real problem is, the message is displayed the minibuffer. It is irritating when using the minibuffer at that time (e.g. during (find-file)).

To1ne
  • 1,108
  • 2
  • 12
  • 22
  • 2
    Your function is probably calling Emacs functions that are only intended to be used in interactive commands, not functions. Check the documentation for these functions, to see if they suggest alternatives to be called programmatically. An example is `set-mark`. – Barmar Feb 12 '13 at 11:34

6 Answers6

2

Just redefine the message function for your call (temporarily):

(flet ((message (msg) ))
  (my-emacs-defun)))

Because of dynamic scoping for global functions, the name message will be redefined while the execution is inside the flet-expression, and it will return it's original sense after it exits the flet.

Example:

(defun verbose ()
  (message "hi"))

(let ()
  (message "one")
  (flet ((message (msg) ))
     (verbose))
  (message "two"))
; ->
; one
; two

You could've also temporarily rebind s Messages buffer, but I don't know where is it stored.

Necto
  • 2,594
  • 1
  • 20
  • 45
  • 1
    Does not work when `(message)` is called from C code. For example `(write-region nil nil (buffer-file-name) nil)` will display "Wrote file". – To1ne Feb 13 '13 at 08:42
1

You can restore the message displayed in the echo area before the function call like this:

(let ((msg (current-message)))
  (do-something-that-calls-message)
  (message "%s" (or msg "")))
legoscia
  • 39,593
  • 22
  • 116
  • 167
1

(with-temp-message "" (my-emacs-func))

jpkotta
  • 9,237
  • 3
  • 29
  • 34
  • This does restore the previous message in the minibuffer, but does not prevent messages being generated. – To1ne Feb 13 '13 at 08:57
1

I've looked in the emacs source code and I found this hack:

  (let ((message-log-max nil)
        (executing-kbd-macro t))
    (my-emacs-defun))

This does suppress all message, but still while (find-file) the focus of the minibuffer is lost.

To1ne
  • 1,108
  • 2
  • 12
  • 22
1

I decided to go for the first option: without emacsclient.

To be more precise I now use:

emacs --batch --eval "(my-emacs-defun)"

In my Makefile it looks like this:

sometarget:
        @emacs --batch --eval "$${elisp_code}"

define elisp_code
   (require 'something)
   (my-emacs-defun)
endif

This also seems to be fast.

To1ne
  • 1,108
  • 2
  • 12
  • 22
1

Even better:

define emacs_script_content=
  (require 'something)
  (my-emacs-defun)
endef
export emacs_script_content

emacs-script:
    @echo $${emacs_script_content} > $@
.INTERMEDIATE: emacs-script

some-target: emacs-script
    @emacs --script $<

This way you won't get errors when calling make functions or when having quoted "text" in the script.

To1ne
  • 1,108
  • 2
  • 12
  • 22