helpful

a fork of Wilfred's helpful
git clone https://git.trogloxene.org/helpful.git
Log | Files | Refs | README

commit cc270e0e0753cfd16d172cc9e6d3e415fc93122f
parent a2fe48573173341fdeed9991b7c62702bc1fee0e
Author: Wilfred Hughes <me@wilfred.me.uk>
Date:   Fri,  6 Jul 2018 16:08:16 +0100

Merge pull request #134 from Wilfred/fix_repeated_calls

Fix repeated calls
Diffstat:
Mhelpful.el | 120+++++++++++++++++++++++++++++++++----------------------------------------------
Mtest/unit-test.el | 20+++++++++++++-------
2 files changed, 63 insertions(+), 77 deletions(-)

diff --git a/helpful.el b/helpful.el @@ -353,7 +353,7 @@ source code to primitives." (and (consp fn-end) (eq (car fn-end) 'edebug-enter)))))) -(defun helpful--can-edebug-p (sym callable-p) +(defun helpful--can-edebug-p (sym callable-p buf pos) "Can we use edebug with SYM?" (and ;; SYM must be a function. @@ -362,11 +362,7 @@ source code to primitives." (not (helpful--primitive-p sym callable-p)) ;; We need to be able to find its definition, or we can't step ;; through the source. - (-let* (((buf pos opened) (helpful--definition sym t)) - (have-definition (and buf pos))) - (when opened - (kill-buffer buf)) - have-definition))) + buf pos)) (defun helpful--toggle-edebug (sym) "Enable edebug when function SYM is called, @@ -1036,35 +1032,32 @@ hooks.") 'face 'font-lock-comment-face) source))) -(defun helpful--source (sym callable-p) +(defun helpful--source (sym callable-p buf pos) "Return the source code of SYM. If the source code cannot be found, return the sexp used." (catch 'source (unless (symbolp sym) (throw 'source sym)) - (-let (((buf start-pos created) (helpful--definition sym callable-p)) - (source nil)) - (when (and buf start-pos) + (let ((source nil)) + (when (and buf pos) (with-current-buffer buf (save-excursion (save-restriction - (goto-char start-pos) + (goto-char pos) (narrow-to-defun t) - ;; If there was a preceding comment, START-POS will be + ;; If there was a preceding comment, POS will be ;; after that comment. Move the position to include that comment. - (setq start-pos (point-min)) + (setq pos (point-min)) (setq source (buffer-substring-no-properties (point-min) (point-max)))))) (setq source (s-trim-right source)) (when (and source (buffer-file-name buf)) (setq source (propertize source 'helpful-path (buffer-file-name buf) - 'helpful-pos start-pos + 'helpful-pos pos 'helpful-pos-is-start t))) - (when (and buf created) - (kill-buffer buf)) (throw 'source source))) (when callable-p @@ -1113,6 +1106,12 @@ buffer." ;; variables. It prompts the user, and we discard the buffer ;; afterwards anyway. (enable-local-variables nil)) + ;; We shouldn't be called on primitive functions if we don't have + ;; a directory of Emacs C sourcecode. + (cl-assert + (or find-function-C-source-directory + (not primitive-p))) + (when (and (symbolp sym) callable-p) (-let [(_ . src-path) (find-function-library sym)] (setq path src-path))) @@ -1185,26 +1184,6 @@ buffer." (error nil)))) (list buf pos opened))) -(defun helpful--source-path (sym callable-p) - "Return the path where SYM is defined." - (-let* (((buf _ opened) (helpful--definition sym callable-p)) - (path nil)) - (when buf - (setq path (buffer-file-name buf)) - (when opened - ;; If we've just created this buffer, close it. - (kill-buffer buf))) - path)) - -(defun helpful--source-pos (sym callable-p) - "Return the file position where SYM is defined." - (-let (((buf pos opened) (helpful--definition sym callable-p))) - ;; If we've just created this buffer, close it. - (when opened - ;; If we've just created this buffer, close it. - (kill-buffer buf)) - pos)) - (defun helpful--reference-positions (sym callable-p buf) "Return all the buffer positions of references to SYM in BUF." (-let* ((forms-and-bufs @@ -1503,15 +1482,11 @@ OBJ may be a symbol or a compiled function object." 'symbol sym 'callable-p callable-p)) -(defun helpful--summary (sym callable-p) +(defun helpful--summary (sym callable-p buf pos) "Return a one sentence summary for SYM." (-let* ((primitive-p (helpful--primitive-p sym callable-p)) (canonical-sym (helpful--canonical-symbol sym callable-p)) (alias-p (not (eq canonical-sym sym))) - ((buf pos opened) - (if (or (not primitive-p) find-function-C-source-directory) - (helpful--definition sym callable-p) - '(nil nil nil))) (alias-button (if callable-p ;; Show a link to 'defalias' in the manual. @@ -1584,8 +1559,6 @@ OBJ may be a symbol or a compiled function object." "defined in C source code") (t "without a source file")))) - (when opened - (kill-buffer buf)) (s-word-wrap 70 @@ -1697,27 +1670,31 @@ state of the current symbol." (cl-assert (not (null helpful--sym))) (unless (buffer-live-p helpful--associated-buffer) (setq helpful--associated-buffer nil)) - (let* ((inhibit-read-only t) - (start-line (line-number-at-pos)) - (start-column (current-column)) - (primitive-p (helpful--primitive-p helpful--sym helpful--callable-p)) - (sym-type (cond - ((not helpful--callable-p) "Variable") - ((macrop helpful--sym) "Macro") - (t "Function"))) - (look-for-src (or (not primitive-p) - find-function-C-source-directory)) - (source (when look-for-src - (helpful--source helpful--sym helpful--callable-p))) - (source-path (when (and look-for-src (symbolp helpful--sym)) - (helpful--source-path helpful--sym helpful--callable-p))) - (references (helpful--calculate-references - helpful--sym helpful--callable-p - source-path))) + (-let* ((inhibit-read-only t) + (start-line (line-number-at-pos)) + (start-column (current-column)) + (primitive-p (helpful--primitive-p helpful--sym helpful--callable-p)) + (sym-type (cond + ((not helpful--callable-p) "Variable") + ((macrop helpful--sym) "Macro") + (t "Function"))) + (look-for-src (or (not primitive-p) + find-function-C-source-directory)) + ((buf pos opened) + (if look-for-src + (helpful--definition helpful--sym helpful--callable-p) + '(nil nil nil))) + (source (when look-for-src + (helpful--source helpful--sym helpful--callable-p buf pos))) + (source-path (when buf + (buffer-file-name buf))) + (references (helpful--calculate-references + helpful--sym helpful--callable-p + source-path))) (erase-buffer) - (insert (helpful--summary helpful--sym helpful--callable-p)) + (insert (helpful--summary helpful--sym helpful--callable-p buf pos)) (when helpful--callable-p (helpful--insert-section-break) @@ -1737,8 +1714,8 @@ state of the current symbol." (when (not helpful--callable-p) (helpful--insert-section-break) (let* ((sym helpful--sym) - (buf (or helpful--associated-buffer (current-buffer))) - (val (helpful--sym-value sym buf)) + (val-buf (or helpful--associated-buffer (current-buffer))) + (val (helpful--sym-value sym val-buf)) (multiple-views-p (or (stringp val) (keymapp val) @@ -1766,9 +1743,9 @@ state of the current symbol." "\n\n") (when multiple-views-p (insert (helpful--make-toggle-literal-button) " ")) - (when (memq (helpful--sym-value helpful--sym buf) '(nil t)) - (insert (helpful--make-toggle-button helpful--sym buf) " ")) - (insert (helpful--make-set-button helpful--sym buf)) + (when (memq (helpful--sym-value helpful--sym val-buf) '(nil t)) + (insert (helpful--make-toggle-button helpful--sym val-buf) " ")) + (insert (helpful--make-set-button helpful--sym val-buf)) (when (custom-variable-p helpful--sym) (insert " " (helpful--make-customize-button helpful--sym))))) @@ -1789,7 +1766,7 @@ state of the current symbol." (helpful--navigate-button (file-name-nondirectory source-path) source-path - (or (helpful--source-pos helpful--sym helpful--callable-p) + (or pos 0))))) (cond ((and source-path references) @@ -1827,7 +1804,7 @@ state of the current symbol." (format "This %s is advised." (downcase sym-type)))) (let ((can-edebug - (helpful--can-edebug-p helpful--sym helpful--callable-p)) + (helpful--can-edebug-p helpful--sym helpful--callable-p buf pos)) (can-trace (and (symbolp helpful--sym) helpful--callable-p @@ -1885,7 +1862,7 @@ state of the current symbol." (helpful--navigate-button (f-abbrev source-path) source-path - (helpful--source-pos helpful--sym helpful--callable-p)) + pos) "\n")) (primitive-p (concat @@ -1923,7 +1900,10 @@ state of the current symbol." (goto-char (point-min)) (forward-line (1- start-line)) - (forward-char start-column))) + (forward-char start-column) + + (when opened + (kill-buffer buf)))) ;; TODO: this isn't sufficient for `edebug-eval-defun'. (defun helpful--skip-advice (docstring) diff --git a/test/unit-test.el b/test/unit-test.el @@ -546,13 +546,15 @@ associated a lambda with a keybinding." (global-set-key (kbd "C-c M-S-c") nil)) (ert-deftest helpful--source () - (let* ((source (helpful--source #'helpful--source t))) + (-let* (((buf pos opened) (helpful--definition #'helpful--source t)) + (source (helpful--source #'helpful--source t buf pos))) (should (s-starts-with-p "(defun " source)))) (ert-deftest helpful--source-autoloaded () "We should include the autoload cookie." - (let* ((source (helpful--source #'helpful-at-point t))) + (-let* (((buf pos opened) (helpful--definition #'helpful-at-point t)) + (source (helpful--source #'helpful-at-point t buf pos))) (should (s-starts-with-p ";;;###autoload" source)))) @@ -560,10 +562,11 @@ associated a lambda with a keybinding." "We should return the raw sexp for functions where we can't find the source code." (eval '(defun test-foo-defined-interactively () 42)) - (should - (not - (null - (helpful--source #'test-foo-defined-interactively t))))) + (-let* (((buf pos opened) (helpful--definition #'test-foo-defined-interactively t))) + (should + (not + (null + (helpful--source #'test-foo-defined-interactively t buf pos)))))) (ert-deftest helpful--outer-sexp () ;; If point is in the middle of a form, we should return its position. @@ -596,7 +599,10 @@ find the source code." (ert-deftest helpful--summary--aliases () ;; exclude the sym itself "Ensure we mention that a symbol is an alias." - (let* ((summary (helpful--summary '-select t))) + (-let* (((buf pos opened) (helpful--definition '-select t)) + (summary (helpful--summary '-select t buf pos))) + (when opened + (kill-buffer buf)) ;; Strip properties to make assertion messages more readable. (set-text-properties 0 (1- (length summary)) nil summary) (should