2018-05-20 12:13:05 +02:00
|
|
|
;;; core/autoload/debug.el -*- lexical-binding: t; -*-
|
2018-05-11 00:00:02 +02:00
|
|
|
|
2018-05-20 12:13:59 +02:00
|
|
|
(defun doom-template-insert (template)
|
|
|
|
"TODO"
|
2018-05-25 12:49:23 +02:00
|
|
|
(let ((file (expand-file-name (format "templates/%s" template) doom-core-dir)))
|
|
|
|
(when (file-exists-p file)
|
|
|
|
(insert-file-contents file))))
|
2018-05-20 12:13:59 +02:00
|
|
|
|
2018-02-10 17:27:02 -05:00
|
|
|
;;;###autoload
|
|
|
|
(defun doom-info ()
|
|
|
|
"Returns diagnostic information about the current Emacs session in markdown,
|
|
|
|
ready to be pasted in a bug report on github."
|
|
|
|
(require 'vc-git)
|
2018-08-16 01:26:28 +02:00
|
|
|
(let ((default-directory doom-emacs-dir)
|
|
|
|
(doom-modules (doom-modules)))
|
2018-02-10 17:27:02 -05:00
|
|
|
(format
|
|
|
|
(concat "- OS: %s (%s)\n"
|
|
|
|
"- Emacs: %s (%s)\n"
|
2018-03-20 20:45:16 -04:00
|
|
|
"- Doom: %s (%s %s)\n"
|
2018-02-10 17:27:02 -05:00
|
|
|
"- Graphic display: %s (daemon: %s)\n"
|
|
|
|
"- System features: %s\n"
|
|
|
|
"- Details:\n"
|
|
|
|
" ```elisp\n"
|
2018-06-10 17:16:50 +02:00
|
|
|
" elc count: %s\n"
|
2018-03-20 20:45:16 -04:00
|
|
|
" uname -a: %s\n"
|
2018-02-10 17:27:02 -05:00
|
|
|
" modules: %s\n"
|
|
|
|
" packages: %s\n"
|
|
|
|
" exec-path: %s\n"
|
2018-05-20 12:13:05 +02:00
|
|
|
" ```")
|
2018-02-10 17:27:02 -05:00
|
|
|
system-type system-configuration
|
|
|
|
emacs-version (format-time-string "%b %d, %Y" emacs-build-time)
|
|
|
|
doom-version
|
2018-06-10 17:16:50 +02:00
|
|
|
(or (vc-git--symbolic-ref "core/core.el")
|
|
|
|
"n/a")
|
|
|
|
(or (vc-git-working-revision "core/core.el")
|
|
|
|
"n/a")
|
2018-02-10 17:27:02 -05:00
|
|
|
(display-graphic-p) (daemonp)
|
|
|
|
(bound-and-true-p system-configuration-features)
|
|
|
|
;; details
|
2018-06-10 17:16:50 +02:00
|
|
|
(length (doom-files-in `(,@doom-modules-dirs
|
|
|
|
,doom-core-dir
|
|
|
|
,doom-private-dir)
|
|
|
|
:type 'files :match "\\.elc$"))
|
2018-07-17 13:59:17 +02:00
|
|
|
(if IS-WINDOWS
|
|
|
|
"n/a"
|
|
|
|
(with-temp-buffer
|
|
|
|
(unless (zerop (call-process "uname" nil t nil "-a"))
|
|
|
|
(insert (format "%s" system-type)))
|
|
|
|
(string-trim (buffer-string))))
|
2018-02-10 17:27:02 -05:00
|
|
|
(or (cl-loop with cat = nil
|
2018-08-16 01:26:28 +02:00
|
|
|
for key being the hash-keys of doom-modules
|
2018-02-10 17:27:02 -05:00
|
|
|
if (or (not cat) (not (eq cat (car key))))
|
2018-10-12 14:07:25 -04:00
|
|
|
do (setq cat (car key))
|
|
|
|
and collect cat
|
|
|
|
and collect (cdr key)
|
2018-02-10 17:27:02 -05:00
|
|
|
else collect
|
2018-03-02 17:45:15 -05:00
|
|
|
(let ((flags (doom-module-get cat (cdr key) :flags)))
|
2018-05-15 02:33:19 +02:00
|
|
|
(if flags
|
|
|
|
`(,(cdr key) ,@flags)
|
|
|
|
(cdr key))))
|
2018-02-10 17:27:02 -05:00
|
|
|
"n/a")
|
|
|
|
(or (ignore-errors
|
2018-06-10 17:16:50 +02:00
|
|
|
(require 'use-package)
|
2019-03-06 00:26:33 -05:00
|
|
|
(cl-loop for (name . plist) in (doom-find-packages :private t)
|
2019-03-15 17:24:23 -04:00
|
|
|
if (use-package-plist-delete (copy-sequence plist) :modules)
|
2018-06-11 23:21:56 +02:00
|
|
|
collect (format "%s" (cons name it))
|
2018-06-10 17:16:50 +02:00
|
|
|
else
|
2018-06-11 23:21:56 +02:00
|
|
|
collect (symbol-name name)))
|
2018-02-10 17:27:02 -05:00
|
|
|
"n/a")
|
2018-05-20 12:13:05 +02:00
|
|
|
;; abbreviate $HOME to hide username
|
|
|
|
(mapcar #'abbreviate-file-name exec-path))))
|
|
|
|
|
|
|
|
|
|
|
|
;;
|
|
|
|
;; Commands
|
2018-02-10 17:27:02 -05:00
|
|
|
|
2017-12-31 17:49:27 -05:00
|
|
|
;;;###autoload
|
2018-05-24 16:40:37 +02:00
|
|
|
(defun doom/info ()
|
2018-02-04 01:38:59 -05:00
|
|
|
"Collects some debug information about your Emacs session, formats it into
|
|
|
|
markdown and copies it to your clipboard, ready to be pasted into bug reports!"
|
2017-12-31 17:49:27 -05:00
|
|
|
(interactive)
|
2018-05-20 12:13:05 +02:00
|
|
|
(message "Generating Doom info...")
|
2018-02-10 17:27:02 -05:00
|
|
|
(if noninteractive
|
2018-05-20 12:13:05 +02:00
|
|
|
(print! (doom-info))
|
2018-02-10 17:27:02 -05:00
|
|
|
(kill-new (doom-info))
|
|
|
|
(message "Done! Copied to clipboard.")))
|
2018-02-04 17:53:05 -05:00
|
|
|
|
|
|
|
;;;###autoload
|
2018-05-24 16:40:37 +02:00
|
|
|
(defun doom/am-i-secure ()
|
2018-05-20 12:13:05 +02:00
|
|
|
"Test to see if your root certificates are securely configured in emacs."
|
|
|
|
(declare (interactive-only t))
|
|
|
|
(interactive)
|
|
|
|
(unless (string-match-p "\\_<GNUTLS\\_>" system-configuration-features)
|
|
|
|
(warn "gnutls support isn't built into Emacs, there may be problems"))
|
|
|
|
(if-let* ((bad-hosts
|
|
|
|
(cl-loop for bad
|
|
|
|
in '("https://wrong.host.badssl.com/"
|
|
|
|
"https://self-signed.badssl.com/")
|
|
|
|
if (condition-case _e
|
|
|
|
(url-retrieve-synchronously bad)
|
|
|
|
(error nil))
|
|
|
|
collect bad)))
|
|
|
|
(error "tls seems to be misconfigured (it got %s)."
|
|
|
|
bad-hosts)
|
|
|
|
(url-retrieve "https://badssl.com"
|
|
|
|
(lambda (status)
|
|
|
|
(if (or (not status) (plist-member status :error))
|
|
|
|
(warn "Something went wrong.\n\n%s" (pp-to-string status))
|
|
|
|
(message "Your trust roots are set up properly.\n\n%s" (pp-to-string status))
|
|
|
|
t)))))
|
|
|
|
|
|
|
|
;;;###autoload
|
2018-05-24 16:40:37 +02:00
|
|
|
(defun doom/version ()
|
2018-05-20 12:13:05 +02:00
|
|
|
"Display the current version of Doom & Emacs, including the current Doom
|
|
|
|
branch and commit."
|
2018-02-04 17:53:05 -05:00
|
|
|
(interactive)
|
2018-05-20 12:13:05 +02:00
|
|
|
(require 'vc-git)
|
2019-02-24 13:58:56 -05:00
|
|
|
(print! "Doom v%s (Emacs v%s)\nBranch: %s\nCommit: %s"
|
2018-05-20 12:13:05 +02:00
|
|
|
doom-version
|
|
|
|
emacs-version
|
|
|
|
(or (vc-git--symbolic-ref doom-core-dir)
|
|
|
|
"n/a")
|
|
|
|
(or (vc-git-working-revision doom-core-dir)
|
|
|
|
"n/a")))
|
|
|
|
|
2018-07-13 13:00:42 +02:00
|
|
|
;;;###autoload
|
|
|
|
(defun doom/copy-backtrace ()
|
2018-08-10 19:13:31 +02:00
|
|
|
"Copy the contents of the *Backtrace* window into your clipboard for easy
|
|
|
|
pasting into a bug report or discord."
|
2018-07-13 13:00:42 +02:00
|
|
|
(interactive)
|
|
|
|
(if-let* ((buf (get-buffer "*Backtrace*")))
|
|
|
|
(with-current-buffer buf
|
|
|
|
(kill-new
|
2018-08-10 19:13:31 +02:00
|
|
|
(string-trim (buffer-string))))
|
2018-07-13 13:00:42 +02:00
|
|
|
(user-error "No backtrace buffer detected")))
|
|
|
|
|
2018-05-20 12:13:05 +02:00
|
|
|
|
2018-09-07 19:36:16 -04:00
|
|
|
;;; Vanilla sandbox
|
2018-05-20 12:13:59 +02:00
|
|
|
|
2018-08-12 02:41:20 +02:00
|
|
|
(defvar doom--sandbox-init-doom-p nil)
|
|
|
|
|
2019-03-09 04:51:31 -05:00
|
|
|
(defun doom--run-vanilla-sandbox (&optional mode)
|
2018-05-20 12:13:59 +02:00
|
|
|
(interactive)
|
2018-07-02 23:32:11 +02:00
|
|
|
(let ((contents (buffer-string))
|
2018-08-30 13:28:43 +02:00
|
|
|
(file (make-temp-file "doom-sandbox-")))
|
2019-03-09 04:51:31 -05:00
|
|
|
(require 'package)
|
2018-08-30 13:28:43 +02:00
|
|
|
(with-temp-file file
|
|
|
|
(insert
|
|
|
|
(prin1-to-string
|
2019-03-09 04:51:31 -05:00
|
|
|
(macroexp-progn
|
|
|
|
(append `((setq debug-on-error t
|
|
|
|
package--init-file-ensured t
|
|
|
|
package-user-dir ,package-user-dir
|
|
|
|
package-archives ',package-archives
|
|
|
|
user-emacs-directory ,doom-emacs-dir
|
|
|
|
doom-modules ,doom-modules))
|
|
|
|
(pcase mode
|
|
|
|
(`vanilla-doom+ ; Doom core + modules - private config
|
|
|
|
`((setq doom-private-dir "/tmp/does/not/exist")
|
|
|
|
(load-file ,user-init-file)
|
|
|
|
(doom|run-all-startup-hooks)))
|
|
|
|
(`vanilla-doom ; only Doom core
|
|
|
|
`((setq doom-private-dir "/tmp/does/not/exist"
|
|
|
|
doom-init-modules-p t)
|
|
|
|
(load-file ,user-init-file)
|
|
|
|
(doom|run-all-startup-hooks)))
|
|
|
|
(`vanilla ; nothing loaded
|
|
|
|
`((package-initialize)))))))
|
2018-08-30 13:28:43 +02:00
|
|
|
"\n(unwind-protect (progn\n" contents "\n)\n"
|
|
|
|
(format "(delete-file %S))" file)))
|
2019-03-09 04:51:31 -05:00
|
|
|
(let ((args (if (eq mode 'doom)
|
|
|
|
(list "-l" file)
|
|
|
|
(list "-Q" "-l" file))))
|
2018-08-30 13:28:43 +02:00
|
|
|
(require 'restart-emacs)
|
|
|
|
(condition-case e
|
2018-08-23 16:17:52 +02:00
|
|
|
(cond ((display-graphic-p)
|
|
|
|
(if (memq system-type '(windows-nt ms-dos))
|
2018-08-30 13:28:43 +02:00
|
|
|
(restart-emacs--start-gui-on-windows args)
|
|
|
|
(restart-emacs--start-gui-using-sh args)))
|
2018-08-23 16:17:52 +02:00
|
|
|
((memq system-type '(windows-nt ms-dos))
|
|
|
|
(user-error "Cannot start another Emacs from Windows shell."))
|
|
|
|
((suspend-emacs
|
|
|
|
(format "%s %s -nw; fg"
|
|
|
|
(shell-quote-argument (restart-emacs--get-emacs-binary))
|
2018-08-30 13:28:43 +02:00
|
|
|
(string-join (mapcar #'shell-quote-argument args) " ")))))
|
|
|
|
(error
|
|
|
|
(delete-file file)
|
|
|
|
(signal (car e) (cdr e)))))))
|
2018-08-12 02:41:20 +02:00
|
|
|
|
2019-03-09 04:51:31 -05:00
|
|
|
(fset 'doom--run-vanilla-emacs (lambda! (doom--run-vanilla-sandbox 'vanilla)))
|
|
|
|
(fset 'doom--run-vanilla-doom (lambda! (doom--run-vanilla-sandbox 'vanilla-doom)))
|
|
|
|
(fset 'doom--run-vanilla-doom+ (lambda! (doom--run-vanilla-sandbox 'vanilla-doom+)))
|
|
|
|
(fset 'doom--run-full-doom (lambda! (doom--run-vanilla-sandbox 'doom)))
|
|
|
|
|
|
|
|
(defvar doom-sandbox-emacs-lisp-mode-map
|
|
|
|
(let ((map (make-sparse-keymap)))
|
|
|
|
(define-key map (kbd "C-c C-c") #'doom--run-vanilla-emacs)
|
|
|
|
(define-key map (kbd "C-c C-d") #'doom--run-vanilla-doom)
|
|
|
|
(define-key map (kbd "C-c C-p") #'doom--run-vanilla-doom+)
|
|
|
|
(define-key map (kbd "C-c C-f") #'doom--run-full-doom)
|
|
|
|
(define-key map (kbd "C-c C-k") #'kill-this-buffer)
|
|
|
|
map))
|
|
|
|
|
|
|
|
(define-derived-mode doom-sandbox-emacs-lisp-mode emacs-lisp-mode "Sandbox Elisp"
|
|
|
|
"TODO")
|
2018-05-20 12:13:59 +02:00
|
|
|
|
|
|
|
;;;###autoload
|
2018-05-24 16:40:37 +02:00
|
|
|
(defun doom/open-vanilla-sandbox ()
|
2019-03-09 04:51:31 -05:00
|
|
|
"Open the Emacs Lisp sandbox.
|
|
|
|
|
|
|
|
This is a test bed for running Emacs Lisp in an instance of Emacs with varying
|
|
|
|
amounts of Doom loaded, including:
|
|
|
|
|
|
|
|
a) vanilla Emacs (nothing loaded),
|
|
|
|
b) vanilla Doom (only Doom core) and
|
|
|
|
c) Doom + modules - your private config.
|
2018-05-20 12:13:59 +02:00
|
|
|
|
2019-03-09 04:51:31 -05:00
|
|
|
This is done without sacrificing access to installed packages. Use the sandbox
|
|
|
|
to reproduce bugs and determine if Doom is to blame."
|
2018-05-20 12:13:59 +02:00
|
|
|
(interactive)
|
2018-08-30 13:28:43 +02:00
|
|
|
(let* ((buffer-name "*doom:vanilla-sandbox*")
|
|
|
|
(exists (get-buffer buffer-name))
|
|
|
|
(buf (get-buffer-create buffer-name)))
|
2018-05-20 12:13:59 +02:00
|
|
|
(with-current-buffer buf
|
2019-03-09 04:51:31 -05:00
|
|
|
(doom-sandbox-emacs-lisp-mode)
|
|
|
|
(setq header-line-format
|
|
|
|
(concat "C-c C-c = vanilla Emacs"
|
|
|
|
" / "
|
|
|
|
"C-c C-d = Doom core"
|
|
|
|
" / "
|
|
|
|
"C-c C-p = Doom core + modules - private config"
|
|
|
|
" / "
|
|
|
|
"C-c C-f = Full Doom"
|
|
|
|
" / "
|
|
|
|
"C-c C-k to abort"))
|
2018-05-20 12:13:59 +02:00
|
|
|
(setq-local default-directory doom-emacs-dir)
|
2018-08-30 13:28:43 +02:00
|
|
|
(unless (buffer-live-p exists)
|
2019-03-09 04:51:31 -05:00
|
|
|
(doom-template-insert "VANILLA_SANDBOX")
|
|
|
|
(let ((contents (substitute-command-keys (buffer-string))))
|
|
|
|
(erase-buffer)
|
|
|
|
(insert contents "\n")))
|
2018-05-20 12:13:59 +02:00
|
|
|
(goto-char (point-max)))
|
|
|
|
(pop-to-buffer buf)))
|
|
|
|
|
|
|
|
|
2018-09-07 19:36:16 -04:00
|
|
|
;;; Reporting bugs
|
2018-05-20 12:13:59 +02:00
|
|
|
|
|
|
|
(defun doom--open-bug-report ()
|
|
|
|
"TODO"
|
|
|
|
(interactive)
|
|
|
|
(let ((url "https://github.com/hlissner/doom-emacs/issues/new?body="))
|
|
|
|
;; TODO Refactor me
|
|
|
|
(save-restriction
|
|
|
|
(widen)
|
|
|
|
(goto-char (point-min))
|
|
|
|
(re-search-forward "^-------------------------------------------------------------------\n" nil t)
|
|
|
|
(skip-chars-forward " \n\t")
|
|
|
|
(condition-case e
|
|
|
|
(progn
|
|
|
|
(save-excursion
|
|
|
|
(when (and (re-search-backward "\\+ [ ] " nil t)
|
|
|
|
(not (y-or-n-p "You haven't checked all the boxes. Continue anyway?")))
|
|
|
|
(error "Aborted submit")))
|
|
|
|
(narrow-to-region (point) (point-max))
|
|
|
|
(let ((text (buffer-string)))
|
|
|
|
;; `url-encode-url' doesn't encode ampersands
|
|
|
|
(setq text (replace-regexp-in-string "&" "%26" text))
|
|
|
|
(setq url (url-encode-url (concat url text)))
|
|
|
|
;; HACK: encode some characters according to HTML URL Encoding Reference
|
|
|
|
;; http://www.w3schools.com/tags/ref_urlencode.asp
|
|
|
|
(setq url (replace-regexp-in-string "#" "%23" url))
|
|
|
|
(setq url (replace-regexp-in-string ";" "%3B" url))
|
|
|
|
(browse-url url)))
|
|
|
|
(error (signal (car e) (car e)))))))
|
|
|
|
|
|
|
|
;;;###autoload
|
2018-05-24 16:40:37 +02:00
|
|
|
(defun doom/open-bug-report ()
|
2018-05-20 12:13:59 +02:00
|
|
|
"Open a markdown buffer destinated to populate the New Issue page on Doom
|
|
|
|
Emacs' issue tracker.
|
|
|
|
|
|
|
|
If called when a backtrace buffer is present, it and the output of `doom-info'
|
|
|
|
will be automatically appended to the result."
|
|
|
|
(interactive)
|
|
|
|
;; TODO Refactor me
|
|
|
|
(let ((backtrace
|
|
|
|
(when (get-buffer "*Backtrace*")
|
|
|
|
(with-current-buffer "*Backtrace*"
|
|
|
|
(string-trim
|
|
|
|
(buffer-substring-no-properties
|
|
|
|
(point-min)
|
|
|
|
(min (point-max) 1000))))))
|
|
|
|
(buf (get-buffer-create "*doom:vanilla-sandbox*")))
|
|
|
|
(with-current-buffer buf
|
|
|
|
(erase-buffer)
|
|
|
|
(condition-case _ (gfm-mode)
|
|
|
|
(error (text-mode)))
|
|
|
|
(doom-template-insert "SUBMIT_BUG_REPORT")
|
|
|
|
(goto-char (point-max))
|
|
|
|
(let ((pos (point)))
|
|
|
|
(save-excursion
|
|
|
|
(insert
|
|
|
|
"\n" (doom-info) "\n"
|
|
|
|
(if (and backtrace (not (string-empty-p backtrace)))
|
|
|
|
(format "\n<details>\n<summary>Backtrace</summary>\n\n```\n%s\n```\n</details>\n"
|
|
|
|
backtrace)
|
|
|
|
"")))
|
|
|
|
(local-set-key (kbd "C-c C-c") #'doom--open-bug-report)
|
|
|
|
(local-set-key (kbd "C-c C-k") #'kill-this-buffer)
|
|
|
|
(setq header-line-format "C-c C-c to submit / C-c C-k to close")
|
|
|
|
;;
|
|
|
|
(narrow-to-region (point-min) pos)
|
|
|
|
(goto-char (point-min)))
|
|
|
|
(pop-to-buffer buf))))
|
|
|
|
|
|
|
|
|
2018-09-07 19:36:16 -04:00
|
|
|
;;; Profiling
|
2018-05-20 12:13:05 +02:00
|
|
|
|
|
|
|
(defvar doom--profiler nil)
|
|
|
|
;;;###autoload
|
2018-05-24 16:40:37 +02:00
|
|
|
(defun doom/toggle-profiler ()
|
2018-05-20 12:13:05 +02:00
|
|
|
"Toggle the Emacs profiler. Run it again to see the profiling report."
|
|
|
|
(interactive)
|
|
|
|
(if (not doom--profiler)
|
|
|
|
(profiler-start 'cpu+mem)
|
|
|
|
(profiler-report)
|
|
|
|
(profiler-stop))
|
|
|
|
(setq doom--profiler (not doom--profiler)))
|
|
|
|
|
|
|
|
;;;###autoload
|
2018-05-24 16:40:37 +02:00
|
|
|
(defun doom/profile-emacs ()
|
2018-05-20 12:13:05 +02:00
|
|
|
"Profile the startup time of Emacs in the background with ESUP.
|
|
|
|
If INIT-FILE is non-nil, profile that instead of USER-INIT-FILE."
|
|
|
|
(interactive)
|
|
|
|
(require 'esup)
|
|
|
|
(let ((init-file esup-user-init-file))
|
|
|
|
(message "Starting esup...")
|
|
|
|
(esup-reset)
|
|
|
|
(setq esup-server-process (esup-server-create (esup-select-port)))
|
|
|
|
(setq esup-server-port (process-contact esup-server-process :service))
|
|
|
|
(message "esup process started on port %s" esup-server-port)
|
2018-08-13 03:45:58 +02:00
|
|
|
(let ((process-args
|
|
|
|
(append `("*esup-child*"
|
|
|
|
"*esup-child*"
|
|
|
|
,esup-emacs-path
|
|
|
|
"-Q"
|
|
|
|
"--eval=(setq after-init-time nil)"
|
|
|
|
"-L" ,esup-load-path)
|
|
|
|
(when (bound-and-true-p early-init-file)
|
|
|
|
`("-l" ,early-init-file))
|
|
|
|
`("-l" "esup-child"
|
|
|
|
,(format "--eval=(let ((load-file-name \"%s\")) (esup-child-run \"%s\" \"%s\" %d))"
|
|
|
|
init-file
|
|
|
|
init-file
|
|
|
|
esup-server-port
|
|
|
|
esup-depth)
|
|
|
|
"--eval=(doom|run-all-startup-hooks)"))))
|
2018-05-20 12:13:05 +02:00
|
|
|
(when esup-run-as-batch-p
|
|
|
|
(setq process-args (append process-args '("--batch"))))
|
|
|
|
(setq esup-child-process (apply #'start-process process-args)))
|
|
|
|
(set-process-sentinel esup-child-process 'esup-child-process-sentinel)))
|
|
|
|
|
2018-08-13 03:49:55 +02:00
|
|
|
;;;###autoload
|
|
|
|
(advice-add #'esup :override #'doom/profile-emacs)
|
2019-03-07 23:26:38 -05:00
|
|
|
|
|
|
|
;;;###autoload
|
2019-03-10 22:56:53 +10:00
|
|
|
(defun doom/toggle-debug-mode (&optional arg)
|
|
|
|
"Toggle `debug-on-error' and `doom-debug-mode' for verbose logging."
|
|
|
|
(interactive (list (or current-prefix-arg 'toggle)))
|
|
|
|
(let ((value
|
|
|
|
(cond ((eq arg 'toggle) (not doom-debug-mode))
|
|
|
|
((> (prefix-numeric-value arg) 0)))))
|
|
|
|
(setq doom-debug-mode value
|
|
|
|
debug-on-error value)
|
|
|
|
(message "Debug mode %s" (if value "on" "off"))))
|