Skip to content

Commit d48013d

Browse files
committed
Change: (debug-warn) Compile out when not debugging; tangle it
1 parent b4608c1 commit d48013d

File tree

3 files changed

+1064
-956
lines changed

3 files changed

+1064
-956
lines changed

README.org

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -958,16 +958,18 @@ Probably should first replace the ~:bindings~ part with this, which correctly ma
958958

959959
**** =debug-warn= macro
960960

961-
This macro simplifies print-style debugging by automatically including the names of the containing function and argument forms, rather than requiring the programmer to write =format= strings manually.
961+
This macro simplifies print-style debugging by automatically including the names of the containing function and argument forms, rather than requiring the programmer to write =format= strings manually. If ~warning-minimum-log-level~ is not ~:debug~ at expansion time, the macro expands to nil, which the byte-compiler eliminates, therefore the macro has no overhead at runtime when not debugging. When debugging, the expanded form also returns nil so, e.g. it may be used in a conditional in place of nil. The macro is tangled to =epdh.el=, but it may also be added directly to source files.
962962

963963
For example, when used like:
964964

965965
#+BEGIN_SRC elisp :exports code
966+
(eval-and-compile
967+
(setq-local warning-minimum-log-level :debug))
968+
966969
(defun argh (var)
967970
(debug-warn (current-buffer) "This is bad!" (point) var)
968971
var)
969972

970-
(setq warning-minimum-log-level :debug)
971973
(argh 1)
972974
#+END_SRC
973975

@@ -977,15 +979,38 @@ This warning would be shown in the =*Warnings*= buffer:
977979
Debug (argh): (CURRENT-BUFFER):*scratch* This is bad! (POINT):491845 VAR:1
978980
#+END_EXAMPLE
979981

980-
The macro is not tangled to =epdh.el=, so you may add it to your code as necessary.
982+
But if ~warning-minimum-log-level~ had any other value, and the buffer were recompiled, there would be no output, and none of the arguments to the macro would be evaluated at runtime.
981983

982-
#+BEGIN_SRC elisp :exports code
983-
(cl-defmacro debug-warn (&rest args)
984+
It may even be used in place of comments! For example, instead of:
985+
986+
#+BEGIN_SRC elisp
987+
(if (foo-p thing)
988+
;; It's a foo: frob it.
989+
(frob thing)
990+
;; Not a foo: flub it.
991+
(flub thing))
992+
#+END_SRC
993+
994+
You could write:
995+
996+
#+BEGIN_SRC elisp
997+
(if (foo-p thing)
998+
(progn
999+
(debug-warn "It's a foo: frob it." thing)
1000+
(frob thing))
1001+
(debug-warn "Not a foo: flub it." thing)
1002+
(flub thing))
1003+
#+END_SRC
1004+
1005+
#+BEGIN_SRC elisp :exports code :results silent :tangle epdh.el
1006+
(cl-defmacro epdh/debug-warn (&rest args)
9841007
"Display a debug warning showing the runtime value of ARGS.
9851008
The warning automatically includes the name of the containing
9861009
function, and it is only displayed if `warning-minimum-log-level'
987-
is `:debug' at runtime (which avoids formatting messages that
988-
won't be shown).
1010+
is `:debug' at expansion time (otherwise the macro expands to nil
1011+
and is eliminated by the byte-compiler). When debugging, the
1012+
expanded form also returns nil so, e.g. it may be used in a
1013+
conditional in place of nil.
9891014

9901015
Each of ARGS may be a string, which is displayed as-is, or a
9911016
symbol, the value of which is displayed prefixed by its name, or
@@ -995,9 +1020,9 @@ The macro is not tangled to =epdh.el=, so you may add it to your code as necessa
9951020
arguments, i.e. alternating keywords and values. The following
9961021
keywords are supported:
9971022

998-
:buffer BUFFER Name of buffer to pass to `display-warning'.
999-
:level LEVEL Level passed to `display-warning', which see.
1000-
Default is :debug."
1023+
:buffer BUFFER Name of buffer to pass to `display-warning'.
1024+
:level LEVEL Level passed to `display-warning', which see.
1025+
Default is :debug."
10011026
(pcase-let* ((fn-name (with-current-buffer
10021027
(or byte-compile-current-buffer (current-buffer))
10031028
;; This is a hack, but a nifty one.
@@ -1020,8 +1045,10 @@ The macro is not tangled to =epdh.el=, so you may add it to your code as necessa
10201045
(1 ")")
10211046
(_ "...)"))
10221047
":%S "))))))
1023-
`(when (eq :debug warning-minimum-log-level)
1024-
(display-warning ',fn-name (format ,string ,@args) ,level ,buffer))))
1048+
(when (eq :debug warning-minimum-log-level)
1049+
`(progn
1050+
(display-warning ',fn-name (format ,string ,@args) ,level ,buffer)
1051+
nil))))
10251052
#+END_SRC
10261053

10271054
** Destructuring :destructuring:

epdh.el

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,53 @@
3535
(require 'dash)
3636
(require 's)
3737

38+
(cl-defmacro epdh/debug-warn (&rest args)
39+
"Display a debug warning showing the runtime value of ARGS.
40+
The warning automatically includes the name of the containing
41+
function, and it is only displayed if `warning-minimum-log-level'
42+
is `:debug' at expansion time (otherwise the macro expands to nil
43+
and is eliminated by the byte-compiler). When debugging, the
44+
expanded form also returns nil so, e.g. it may be used in a
45+
conditional in place of nil.
46+
47+
Each of ARGS may be a string, which is displayed as-is, or a
48+
symbol, the value of which is displayed prefixed by its name, or
49+
a Lisp form, which is displayed prefixed by its first symbol.
50+
51+
Before the actual ARGS arguments, you can write keyword
52+
arguments, i.e. alternating keywords and values. The following
53+
keywords are supported:
54+
55+
:buffer BUFFER Name of buffer to pass to `display-warning'.
56+
:level LEVEL Level passed to `display-warning', which see.
57+
Default is :debug."
58+
(pcase-let* ((fn-name (with-current-buffer
59+
(or byte-compile-current-buffer (current-buffer))
60+
;; This is a hack, but a nifty one.
61+
(save-excursion
62+
(beginning-of-defun)
63+
(cl-second (read (current-buffer))))))
64+
(plist-args (cl-loop while (keywordp (car args))
65+
collect (pop args)
66+
collect (pop args)))
67+
((map (:buffer buffer) (:level level)) plist-args)
68+
(level (or level :debug))
69+
(string (cl-loop for arg in args
70+
concat (pcase arg
71+
((pred stringp) "%S ")
72+
((pred symbolp)
73+
(concat (upcase (symbol-name arg)) ":%S "))
74+
((pred listp)
75+
(concat "(" (upcase (symbol-name (car arg)))
76+
(pcase (length arg)
77+
(1 ")")
78+
(_ "...)"))
79+
":%S "))))))
80+
(when (eq :debug warning-minimum-log-level)
81+
`(progn
82+
(display-warning ',fn-name (format ,string ,@args) ,level ,buffer)
83+
nil))))
84+
3885
;;;; General tools
3986

4087
;;;###autoload

0 commit comments

Comments
 (0)