Ensure that we can find definitions when buffer is narrowed
authorWilfred Hughes <me@wilfred.me.uk>
Sun, 10 Dec 2017 13:34:06 +0000 (13:34 +0000)
committerWilfred Hughes <me@wilfred.me.uk>
Sun, 10 Dec 2017 14:52:54 +0000 (14:52 +0000)
find-function-search-for-symbol will reuse the existing buffer if
we've already opened the file that contains this symbol. However, if
the user has narrowed that buffer, we can't find definitions outside
the narrowed area.

Instead, search the whole file to find definitions, and teach the help
buttons to widen if necessary.

* lisp/emacs-lisp/find-func.el (find-function-search-for-symbol):
  Search the whole buffer for the target symbol.

* lisp/help-mode.el: Help buttons now widen the target buffer, if
  narrowing is in effect and the target position is not in that range.

lisp/emacs-lisp/find-func.el
lisp/help-mode.el

index 29c42f369388a04542cf528cebdb42a37a42cd81..84cc8bc9b7212382eee0db443e2ff1ee83478fc9 100644 (file)
@@ -368,28 +368,30 @@ The search is done in the source for library LIBRARY."
                                 (concat "\\\\?"
                                         (regexp-quote (symbol-name symbol))))))
              (case-fold-search))
-         (with-syntax-table emacs-lisp-mode-syntax-table
-           (goto-char (point-min))
-           (if (if (functionp regexp)
-                    (funcall regexp symbol)
-                  (or (re-search-forward regexp nil t)
-                      ;; `regexp' matches definitions using known forms like
-                      ;; `defun', or `defvar'.  But some functions/variables
-                      ;; are defined using special macros (or functions), so
-                      ;; if `regexp' can't find the definition, we look for
-                      ;; something of the form "(SOMETHING <symbol> ...)".
-                      ;; This fails to distinguish function definitions from
-                      ;; variable declarations (or even uses thereof), but is
-                      ;; a good pragmatic fallback.
-                      (re-search-forward
-                       (concat "^([^ ]+" find-function-space-re "['(]?"
-                               (regexp-quote (symbol-name symbol))
-                               "\\_>")
-                       nil t)))
-               (progn
-                 (beginning-of-line)
-                 (cons (current-buffer) (point)))
-             (cons (current-buffer) nil))))))))
+          (save-restriction
+            (widen)
+            (with-syntax-table emacs-lisp-mode-syntax-table
+              (goto-char (point-min))
+              (if (if (functionp regexp)
+                      (funcall regexp symbol)
+                    (or (re-search-forward regexp nil t)
+                        ;; `regexp' matches definitions using known forms like
+                        ;; `defun', or `defvar'.  But some functions/variables
+                        ;; are defined using special macros (or functions), so
+                        ;; if `regexp' can't find the definition, we look for
+                        ;; something of the form "(SOMETHING <symbol> ...)".
+                        ;; This fails to distinguish function definitions from
+                        ;; variable declarations (or even uses thereof), but is
+                        ;; a good pragmatic fallback.
+                        (re-search-forward
+                         (concat "^([^ ]+" find-function-space-re "['(]?"
+                                 (regexp-quote (symbol-name symbol))
+                                 "\\_>")
+                         nil t)))
+                  (progn
+                    (beginning-of-line)
+                    (cons (current-buffer) (point)))
+                (cons (current-buffer) nil)))))))))
 
 (defun find-function-library (function &optional lisp-only verbose)
   "Return the pair (ORIG-FUNCTION . LIBRARY) for FUNCTION.
index 8bafa46aa978f1843150d3e35bfda1a5176e98fb..1e1ae1126ca16a6691f5562e5cdb6aa3f88892e6 100644 (file)
@@ -203,12 +203,18 @@ The format is (FUNCTION ARGS...).")
                              (help-C-file-name (indirect-function fun) 'fun)))
                      ;; Don't use find-function-noselect because it follows
                      ;; aliases (which fails for built-in functions).
-                     (let ((location
-                            (find-function-search-for-symbol fun type file)))
+                     (let* ((location
+                             (find-function-search-for-symbol fun type file))
+                            (position (cdr location)))
                        (pop-to-buffer (car location))
                        (run-hooks 'find-function-after-hook)
-                       (if (cdr location)
-                           (goto-char (cdr location))
+                       (if position
+                           (progn
+                             ;; Widen the buffer if necessary to go to this position.
+                             (when (or (< position (point-min))
+                                       (> position (point-max)))
+                               (widen))
+                             (goto-char position))
                          (message "Unable to find location in file")))))
   'help-echo (purecopy "mouse-2, RET: find function's definition"))
 
@@ -219,6 +225,7 @@ The format is (FUNCTION ARGS...).")
                   (if (and file (file-readable-p file))
                       (progn
                         (pop-to-buffer (find-file-noselect file))
+                         (widen)
                         (goto-char (point-min))
                         (if (re-search-forward
                              (format "^[ \t]*(\\(cl-\\)?define-compiler-macro[ \t]+%s"
@@ -234,12 +241,18 @@ The format is (FUNCTION ARGS...).")
   'help-function (lambda (var &optional file)
                   (when (eq file 'C-source)
                     (setq file (help-C-file-name var 'var)))
-                  (let ((location (find-variable-noselect var file)))
+                  (let* ((location (find-variable-noselect var file))
+                          (position (cdr location)))
                     (pop-to-buffer (car location))
                     (run-hooks 'find-function-after-hook)
-                    (if (cdr location)
-                      (goto-char (cdr location))
-                      (message "Unable to find location in file"))))
+                     (if position
+                           (progn
+                             ;; Widen the buffer if necessary to go to this position.
+                             (when (or (< position (point-min))
+                                       (> position (point-max)))
+                               (widen))
+                             (goto-char position))
+                       (message "Unable to find location in file"))))
   'help-echo (purecopy "mouse-2, RET: find variable's definition"))
 
 (define-button-type 'help-face-def
@@ -248,12 +261,18 @@ The format is (FUNCTION ARGS...).")
                   (require 'find-func)
                   ;; Don't use find-function-noselect because it follows
                   ;; aliases (which fails for built-in functions).
-                  (let ((location
-                         (find-function-search-for-symbol fun 'defface file)))
+                  (let* ((location
+                         (find-function-search-for-symbol fun 'defface file))
+                         (position (cdr location)))
                     (pop-to-buffer (car location))
-                    (if (cdr location)
-                        (goto-char (cdr location))
-                      (message "Unable to find location in file"))))
+                     (if position
+                           (progn
+                             ;; Widen the buffer if necessary to go to this position.
+                             (when (or (< position (point-min))
+                                       (> position (point-max)))
+                               (widen))
+                             (goto-char position))
+                       (message "Unable to find location in file"))))
   'help-echo (purecopy "mouse-2, RET: find face's definition"))
 
 (define-button-type 'help-package