diff --git a/exwm-core.el b/exwm-core.el index ab5159c6a..66b79171f 100644 --- a/exwm-core.el +++ b/exwm-core.el @@ -31,6 +31,7 @@ (require 'xcb) (require 'xcb-icccm) (require 'xcb-ewmh) +(require 'exwm-debug) (eval-and-compile (defvar exwm-debug-on nil "Non-nil to turn on debug for EXWM.")) @@ -70,10 +71,18 @@ (declare-function exwm-workspace-move-window "exwm-workspace.el" (frame-or-index &optional id)) -(defmacro exwm--log (format-string &rest args) - "Print debug message." +(defmacro exwm--log (&optional format-string &rest objects) + "Emit a message prepending the name of the function being executed. + +FORMAT-STRING is a string specifying the message to output, as in +`format'. The OBJECTS arguments specify the substitutions." (when exwm-debug-on - `(message (concat "[EXWM] " ,format-string) ,@args))) + (unless format-string (setq format-string "")) + `(progn + (exwm-debug--message (concat "%s:\t" ,format-string "\n") + (exwm-debug--compile-time-function-name) + ,@objects) + nil))) (defmacro exwm--debug (&rest forms) (when exwm-debug-on `(progn ,@forms))) diff --git a/exwm-debug.el b/exwm-debug.el new file mode 100644 index 000000000..89421da65 --- /dev/null +++ b/exwm-debug.el @@ -0,0 +1,104 @@ +;;; exwm-debug.el --- Debugging helpers for EXWM -*- lexical-binding: t -*- + +;; Copyright (C) 2015-2016 Free Software Foundation, Inc. + +;; Author: Chris Feng +;; Adrián Medraño Calvo + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;; This module collects functions that help in debugging EXWM. + +;;; Code: + +(eval-and-compile + (defvar exwm-debug-on nil "Non-nil to turn on debug for EXWM.")) + +(defvar exwm-debug-buffer + (when exwm-debug-on + (let ((buffer (get-buffer-create "*EXWM-DEBUG*"))) + (buffer-disable-undo buffer) + buffer)) + "Buffer to write debug messages to.") + +(defun exwm-debug--call-stack () + "Return the current call stack frames." + (let (frames frame + ;; No need to acount for our setq, while, let, ... + (index 5)) + (while (setq frame (backtrace-frame index)) + (push frame frames) + (cl-incf index)) + (cl-remove-if-not 'car frames))) + +(defmacro exwm-debug--compile-time-function-name () + "Get the name of outermost definition at expansion time." + (let* ((frame (cl-find-if + (lambda (frame) + (ignore-errors + (let ((clause (car (cl-third frame)))) + (or (equal clause 'defalias) + (equal clause 'cl-defmethod))))) + (reverse (exwm-debug--call-stack)))) + (defn (cl-third frame)) + (deftype (car defn))) + (cl-case deftype + ((defalias) (symbol-name (cl-cadadr defn))) + ((cl-defmethod) (symbol-name (cadr defn))) + (t "")))) + +(defmacro exwm-debug--with-debug-buffer (&rest forms) + "Evaluate FORMS making sure `exwm-debug-buffer' is correctly updated." + `(with-current-buffer exwm-debug-buffer + (let (windows-eob) + ;; Note windows whose point is at EOB. + (dolist (w (get-buffer-window-list exwm-debug-buffer t t)) + (when (= (window-point w) (point-max)) + (push w windows-eob))) + (save-excursion + (goto-char (point-max)) + ,@forms) + ;; Restore point. + (dolist (w windows-eob) + (set-window-point w (point-max)))))) + +(defun exwm-debug--message (format-string &rest objects) + "Print a message to `exwm-debug-buffer'. + +The FORMAT-STRING argument follows the speficies how to print each of +the passed OBJECTS. See `format' for details." + (exwm-debug--with-debug-buffer + (insert (apply #'format format-string objects)))) + +(defmacro exwm-debug--backtrace () + "Print a backtrace to the `exwm-debug-buffer'." + '(exwm-debug--with-debug-buffer + (let ((standard-output exwm-debug-buffer)) + (backtrace)))) + +(defmacro exwm-debug--backtrace-on-error (&rest forms) + "Evaluate FORMS. Printing a backtrace if an error is signaled." + `(let ((debug-on-error t) + (debugger (lambda (&rest _) (exwm-debug--backtrace)))) + ,@forms)) + + + +(provide 'exwm-debug) + +;;; exwm-debug.el ends here