helpful

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

commit 2c8feeb3ff818606b15ca08ad90e2116afef001c
parent 850c316513558a0ced66f004cd8825a209755bfc
Author: Wilfred Hughes <me@wilfred.me.uk>
Date:   Sun, 12 Aug 2018 17:28:56 -0700

Clearly separate library names from absolute paths

We need an absolute path for opening the file, but
`find-function-search-for-symbol` expects a relative path for
primitive functions.

Using the library name allows us to avoid `find-function-C-source`,
which doesn't support Rust primitives. This should fix Remacs support.

See discussion in
https://github.com/Wilfred/remacs/pull/800

Diffstat:
Mhelpful.el | 42++++++++++++++++++++----------------------
Mtest/helpful-unit-test.el | 8++++++++
2 files changed, 28 insertions(+), 22 deletions(-)

diff --git a/helpful.el b/helpful.el @@ -1111,14 +1111,19 @@ If the source code cannot be found, return the sexp used." (or (assoc sym completions) (assoc-string sym completions)))) -(defun helpful--find-library-name (path) - "A wrapper around `find-library-name' that returns nil if PATH -has no library with that name. - -This can happen when users have installed Emacs without its -source code: they have e.g. org.elc but no org.el." - (condition-case _err - (find-library-name path) +(defun helpful--library-path (library-name) + "Find the absolute path for the source of LIBRARY-NAME. + +LIBRARY-NAME takes the form \"foo.el\" , \"foo.el\" or +\"src/foo.c\". + +If .elc files exist without the corresponding .el, return nil." + (when (member (f-ext library-name) '("c" "rs")) + (setq library-name + (f-expand library-name + (f-parent find-function-C-source-directory)))) + (condition-case nil + (find-library-name library-name) (error nil))) (defun helpful--definition (sym callable-p) @@ -1132,7 +1137,7 @@ POS is the position of the start of the definition within the buffer." (let ((initial-buffers (buffer-list)) (primitive-p (helpful--primitive-p sym callable-p)) - (path nil) + (library-name nil) (buf nil) (pos nil) (opened nil) @@ -1149,22 +1154,17 @@ buffer." (not primitive-p))) (when (and (symbolp sym) callable-p) - (-let [(_ . src-path) (find-function-library sym)] - (setq path src-path))) - (when (and primitive-p path find-function-C-source-directory) - ;; Convert relative to absolute path. - (setq path (f-expand path - (f-parent find-function-C-source-directory)))) + (setq library-name (cdr (find-function-library sym)))) (cond ((and (not (symbolp sym)) (functionp sym)) (list nil nil nil)) - ((and callable-p path) + ((and callable-p library-name) ;; Convert foo.elc to foo.el. - (-when-let (src-path (helpful--find-library-name path)) - ;; Open `path' ourselves, so we can widen before searching. + (-when-let (src-path (helpful--library-path library-name)) + ;; Open `src-path' ourselves, so we can widen before searching. ;; - ;; Opening large.c files can be slow (e.g. when looking at + ;; Opening large .c files can be slow (e.g. when looking at ;; `defalias'), especially if the user has configured mode hooks. ;; ;; Bind `auto-mode-alist' to nil, so we open the buffer in @@ -1193,9 +1193,7 @@ buffer." (save-restriction (widen) (setq pos - (if primitive-p - (cdr (find-function-C-source sym path nil)) - (cdr (find-function-search-for-symbol sym nil path))))))))) + (cdr (find-function-search-for-symbol sym nil library-name)))))))) (callable-p ;; Functions defined interactively may have an edebug property ;; that contains the location of the definition. diff --git a/test/helpful-unit-test.el b/test/helpful-unit-test.el @@ -295,6 +295,14 @@ symbol (not a form)." (skip-unless find-function-C-source-directory) (helpful--definition 'default-directory nil)) +(ert-deftest helpful--definition-special-form () + "Ensure we find the position of special forms." + (skip-unless find-function-C-source-directory) + (-let [(buf pos _) + (helpful--definition 'if t)] + (should buf) + (should pos))) + (setq helpful-var-without-defvar 'foo) (ert-deftest helpful--definition-no-defvar ()