When using elisp function in the link in org-mode, like


after clicking the link, the function itself will be printed in *Message* buffer. How should I prevent it from being printed? I've tried

(let ((inhibit-output t))

but it doesn't work.

3 Answers 3


[Editorial comment: I'm not convinced this is a good idea - what difference does it make if the *Messages* buffer has an extra line in it? Despite my misgivings, I provide an answer below.]

The relevant function is org-link--open-elisp. If you check its implementation, you will see that it uses message to print the result of the evaluation to the echo area. But message also copies whatever it prints to the echo area, to the *Messages* buffer. A quick perusal of the doc string for message shows that you can avoid copying to the *Messages* buffer if you set message-log-max to nil. Unfortunately, that is going to turn off all output to the Messages buffer which is a bad thing.

One way to accomplish what you want is to patch the org-link--open-elisp function to bind message-log-max to nil temporarily (as Marco Wahl suggests in his answer), but my suggestion would be to write a new function for this, which is an exact copy of org-link--open-elisp except that it binds message-log-max to nil before calling message:

(defun org-link--open-elisp-silent (path)
  "Open a \"elisp-silent\" type link.
PATH is the sexp to evaluate, as a string."
  (if (or (and (org-string-nw-p org-link-elisp-skip-confirm-regexp)
           (string-match-p org-link-elisp-skip-confirm-regexp path))
      (not org-link-elisp-confirm-function)
      (funcall org-link-elisp-confirm-function
           (format "Execute %S as Elisp? "
               (org-add-props path nil 'face 'org-warning))))
      (let ((message-log-max nil))
         (message "%s => %s" path
           (if (eq ?\( (string-to-char path))
           (eval (read path))
         (call-interactively (read path)))))
    (user-error "Abort")))

You can then add a new link type "elisp-silent" that is handled by this function:

(org-link-set-parameters "elisp-silent" :follow #'org-link--open-elisp-silent)

Now [[elisp:(func)][verbose]] works as before and [[elisp-silent:(func)][silent]] works the same way but avoids writing to the *Messages* buffer.

This technique of binding a variable around a function call is general and well-worth understanding if you are going to be doing elisp programming.

  • I like the idea of introducing a new protocol for that purpose.
    – Tobias
    Commented Mar 6, 2020 at 0:26
  • What is wrong on (defun org-link--open-elisp-silent (path) (let (message-log-max) (org-link--open-elisp path)))?
    – Tobias
    Commented Mar 6, 2020 at 0:33
  • Nothing (as I know you know :-)): I was just being stupid.
    – NickD
    Commented Mar 6, 2020 at 3:17

A shorter way to accomplish this is by Advising Emacs Lisp Functions. You can use :around advice to let-bind the variable and then call the original function with its arguments like this:

(defun silence (orig-func &rest args)
  (let ((message-log-max nil))
    (apply orig-func args)))

(advice-add 'org-link--open-elisp :around 'silence)

Later you can remove the advice like this:

(advice-remove 'org-link--open-elisp 'silence)

Since the message comes from the respective org mode function you need to somehow circumvent that function. You could patch that function.

Actually I think it's a good idea to see the message since this gives transparency to the evaluation. Note that the code evaluation could bring irritation and even harm.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.