Function: activities-debug

activities-debug is a macro defined in activities.el.

Signature

(activities-debug &rest ARGS)

Documentation

Display a debug warning showing the runtime value of ARGS.

The warning automatically includes the name of the containing function, and it is only displayed if warning-minimum-log-level is :debug at expansion time (otherwise the macro expands to a call to ignore with ARGS and is eliminated by the byte-compiler). When debugging, the form also returns nil so, e.g. it may be used in a conditional in place of nil.

Each of ARGS may be a string, which is displayed as-is, or a symbol, the value of which is displayed prefixed by its name, or a Lisp form, which is displayed prefixed by its first symbol.

Before the actual ARGS arguments, you can write keyword arguments, i.e. alternating keywords and values. The following keywords are supported:

  :buffer BUFFER Name of buffer to pass to display-warning.
  :level LEVEL Level passed to display-warning, which see.
                   Default is :debug.

Source Code

;; Defined in ~/.emacs.d/elpa/activities-0.7.2/activities.el
;; NOTE: Uncomment this form and `emacs-lisp-byte-compile-and-load'
;; the file to enable `activities-debug' messages.  This is commented
;; out by default because, even though the messages are only displayed
;; when `warning-minimum-log-level' is `:debug' at runtime, if that is
;; so at expansion time, the expanded macro calls format the message
;; and check the log level at runtime, which is not zero-cost.

;; (eval-and-compile (setq-local warning-minimum-log-level nil) (setq-local warning-minimum-log-level :debug))

(cl-defmacro activities-debug (&rest args)
  "Display a debug warning showing the runtime value of ARGS.
The warning automatically includes the name of the containing
function, and it is only displayed if `warning-minimum-log-level'
is `:debug' at expansion time (otherwise the macro expands to a
call to `ignore' with ARGS and is eliminated by the
byte-compiler).  When debugging, the form also returns nil so,
e.g. it may be used in a conditional in place of nil.

Each of ARGS may be a string, which is displayed as-is, or a
symbol, the value of which is displayed prefixed by its name, or
a Lisp form, which is displayed prefixed by its first symbol.

Before the actual ARGS arguments, you can write keyword
arguments, i.e. alternating keywords and values.  The following
keywords are supported:

  :buffer BUFFER   Name of buffer to pass to `display-warning'.
  :level  LEVEL    Level passed to `display-warning', which see.
                   Default is :debug."
  ;; TODO: Can we use a compiler macro to handle this more elegantly?
  (pcase-let* ((fn-name (when byte-compile-current-buffer
                          (with-current-buffer byte-compile-current-buffer
                            ;; This is a hack, but a nifty one.
                            (save-excursion
                              (beginning-of-defun)
                              (cl-second (read (current-buffer)))))))
               (plist-args (cl-loop while (keywordp (car args))
                                    collect (pop args)
                                    collect (pop args)))
               ((map (:buffer buffer) (:level level)) plist-args)
               (level (or level :debug))
               (string (cl-loop for arg in args
                                concat (pcase arg
                                         ((pred stringp) "%S ")
                                         ((pred symbolp)
                                          (concat (upcase (symbol-name arg)) ":%S "))
                                         ((pred listp)
                                          (concat "(" (upcase (symbol-name (car arg)))
                                                  (pcase (length arg)
                                                    (1 ")")
                                                    (_ "...)"))
                                                  ":%S "))))))
    (if (eq :debug warning-minimum-log-level)
        `(let ((fn-name ,(if fn-name
                             `',fn-name
                           ;; In an interpreted function: use `backtrace-frame' to get the
                           ;; function name (we have to use a little hackery to figure out
                           ;; how far up the frame to look, but this seems to work).
                           `(cl-loop for frame in (backtrace-frames)
                                     for fn = (cl-second frame)
                                     when (not (or (subrp fn)
                                                   (special-form-p fn)
                                                   (eq 'backtrace-frames fn)))
                                     return (make-symbol (format "%s [interpreted]" fn))))))
           (display-warning fn-name (format ,string ,@args) ,level ,buffer)
           nil)
      `(ignore ,@args))))