]> code.delx.au - gnu-emacs-elpa/blobdiff - packages/bug-hunter/bug-hunter.el
Merge commit 'bc335af4d94d80d3605b66ed51a15d2476ad2179' from swiper
[gnu-emacs-elpa] / packages / bug-hunter / bug-hunter.el
index bd6c06da340af50b30500b047fe17d7b2d6283b5..2d0fc5011b8ddad984e637cfda9650d77b424df8 100644 (file)
@@ -2,9 +2,9 @@
 
 ;; Copyright (C) 2015 Free Software Foundation, Inc.
 
-;; Author: Artur Malabarba <bruce.connor.am@gmail.com>
-;; URL: http://github.com/Bruce-Connor/elisp-bug-hunter
-;; Version: 0.1
+;; Author: Artur Malabarba <emacs@endlessparentheses.com>
+;; URL: http://github.com/Malabarba/elisp-bug-hunter
+;; Version: 0.2
 ;; Keywords: lisp
 ;; Package-Requires: ((seq "1.3") (cl-lib "0.5"))
 
 ;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Commentary:
-;; `bug-hunter' is an Emacs library that finds the source of an error or
-;; unexpected behavior inside an elisp configuration file (tipically
+;;
+;; The Bug Hunter is an Emacs library that finds the source of an error or
+;; unexpected behavior inside an elisp configuration file (typically
 ;; `init.el' or `.emacs').
-;; 
-;; 
+;;
 ;; Usage Examples
 ;; ==============
-;; 
+;;
 ;;   If your Emacs init file signals an error during startup, but you don’t
 ;;   know why, simply issue
 ;;   ,----
 ;;   | M-x bug-hunter-init-file RET RET
 ;;   `----
-;;   and `bug-hunter' will find it for you.
-;; 
+;;   and The Bug Hunter will find it for you. Note that your `init.el' (or
+;;   `.emacs') must be idempotent for this to work.
+;;
 ;;   If Emacs starts up without errors but something is not working as it
 ;;   should, invoke the same command, but give it in an assertion.
 ;;   Essentially, if you can write a snippet that detects the issue and
 ;;   returns non-nil, just provide this snippet as the assertion and the
 ;;   Bug Hunter will do a bisection search for you.
-;; 
+;;
 ;;   For example, let’s say there’s something in your init file that’s
 ;;   loading the `cl' library, and you don’t want that. You /know/ you’re
 ;;   not loading it yourself, but how can you figure out which external
 ;;   package is responsible for this outrage?
-;; 
+;;
 ;;   ,----
 ;;   | M-x bug-hunter-init-file RET (featurep 'cl) RET
 ;;   `----
-;; 
+;;
 ;;   *That’s it!* You’ll be given a nice buffer reporting the results:
-;; 
+;;
 ;;   - Are you getting obscure errors when trying to open /“.tex”/ files?
-;;     Don’t despair! Just use `(find-file "dummy.tex")' as the assertion.
-;;   - Did `ox-html' stop working due to some arcane misconfiguration? Just
-;;     write an assertion that does an export and checks the result.
+;;     - Don’t despair! Just use `(find-file "dummy.tex")' as the
+;;       assertion.
+;;   - Did `ox-html' stop working due to some arcane misconfiguration?
+;;     - Just write an assertion that does an export and checks the result.
 ;;   - Does some random command suddenly bind itself to `C-j' and you can’t
-;;     figure out why? `(eq (key-binding "\n") 'unwanted-command)' is the
-;;     assertion for you!
-;; 
+;;     figure out why?
+;;     - `(eq (key-binding "\n") 'unwanted-command)' is the assertion for
+;;       you!
+;;
 ;;   Finally, you can also use `bug-hunter-file' to hunt in other files.
-;; 
-
-;; Installation
-;; ============
-;; 
-;;   Bug Hunter will be on Gelpa shortly. For now, do the following:
-;;   1. Open the `bug-hunter.el` file.
-;;   2. Issue `M-x package-install-from-buffer`.
 
 \f
 ;;; Code:
@@ -229,8 +224,7 @@ the file."
           (with-temp-file file-name
             (print (list 'prin1 form) (current-buffer)))
           (call-process exec nil out-buf nil
-                        "-Q" "--batch" "-l"
-                        (shell-quote-argument file-name))
+                        "-Q" "--batch" "-l" file-name)
           (with-current-buffer out-buf
             (goto-char (point-max))
             (forward-sexp -1)
@@ -263,25 +257,29 @@ ASSERTION is received by `bug-hunter--bisect-start'.
 SAFE is a list of forms confirmed to not match the ASSERTION,
 HEAD is a list of forms to be tested now, and TAIL is a list
 which will be inspected if HEAD doesn't match ASSERTION."
-  (cond
-   ((not tail)
-    (vector (length safe)
-            ;; Sometimes we already ran this, sometimes not. So it's
-            ;; easier to just run it anyway to get the return value.
-            (bug-hunter--run-and-test (append safe head) assertion)))
-   ((and (message "Testing: %s/%s"
-           (cl-incf bug-hunter--i)
-           bug-hunter--estimate)
-         (setq bug-hunter--current-head head)
-         (bug-hunter--run-and-test (append safe head) assertion))
-    (apply #'bug-hunter--bisect
-      assertion
-      safe
-      (bug-hunter--split head)))
-   (t (apply #'bug-hunter--bisect
+  (message "Testing: %s/%s" (cl-incf bug-hunter--i) bug-hunter--estimate)
+  ;; Used if the user quits.
+  (setq bug-hunter--current-head head)
+  (let ((ret-val (bug-hunter--run-and-test (append safe head) assertion)))
+    (cond
+     ((not tail)
+      (cl-assert ret-val nil)
+      (vector (length safe) ret-val))
+     ;; Issue in the head.
+     ((and ret-val (< (length head) 2))
+      (vector (length safe) ret-val))
+     (ret-val
+      (apply #'bug-hunter--bisect
         assertion
-        (append safe head)
-        (bug-hunter--split tail)))))
+        safe
+        (bug-hunter--split head)))
+     ;; Issue in the tail.
+     (t (apply #'bug-hunter--bisect
+          assertion
+          (append safe head)
+          ;; If tail has length 1, we already know where the issue is,
+          ;; but we still do this to get the return value.
+          (bug-hunter--split tail))))))
 
 (defun bug-hunter--bisect-start (forms assertion)
   "Run a bisection search on list of FORMS using ASSERTION.
@@ -380,9 +378,6 @@ Wraps them in a progn if necessary."
            (let ((minibuffer-completing-symbol t))
              (minibuffer-with-setup-hook
                  (lambda ()
-                   ;; FIXME: call emacs-lisp-mode?
-                   (add-function :before-until (local 'eldoc-documentation-function)
-                                 #'elisp-eldoc-documentation-function)
                    (add-hook 'completion-at-point-functions
                              #'elisp-completion-at-point nil t)
                    (run-hooks 'eval-expression-minibuffer-setup-hook))