Subject: 29.0.50; [PATCH] M-. into a .gz; we've all been there.

From: [email-masked]
Date: Fri, 03 Jun 2022 02:27:59 -0400

Was https://lists.gnu.org/archive/html/emacs-devel/2021-08/msg00340.html

Some guys symlink their PATH emacs to src/emacs.

Other guys still prefer `make install`, and live in constant fear of
meta-dotting into a .gz file.  Well, live in fear no more.

emacs -Q --eval "(custom-set-variables '(xref-prefer-source-directory t))"
>From fb6f100bb1f588322c6a501ff2876a773189a9b9 Mon Sep 17 00:00:00 2001
From: dickmao <[email-masked]>
Date: Fri, 3 Jun 2022 02:11:20 -0400
Subject: [PATCH] xref-prefer-source-directory

emacs -Q --eval "(custom-set-variables '(xref-prefer-source-directory t))"

* lisp/emacs-lisp/find-func.el (find-function-regexp-alist):
Was crashing on this missing entry in find-function-regexp-alist.
(find-function-C-source-directory): Style.
(find-function-C-source): Style.
(find-function-search-for-symbol): English.
* lisp/help-fns.el (help-C-file-name): English.
(find-lisp-object-file-name): Use it.
* lisp/help-mode.el (xref): Require.
(help-function-def--button-function): Use it.
(help-face-def): Use it.
* lisp/progmodes/elisp-mode.el (xref-backend-definitions): Style.
(elisp--xref-find-definitions): Style.
(xref-location-marker): Use it.
* lisp/progmodes/project.el (project-root): Snuff bytecomp warning.
* lisp/progmodes/xref.el (xref-prefer-source-directory): New defcustom.
(xref-preferred-message): Message user.
(xref-preferred-source): Act on new defcustom.
(xref-show-definitions-buffer): Style.
(xref--create-fetcher): Style.
* src/emacs.c (syms_of_emacs): English.
* src/lread.c (load_path_default): English.
(init_lread): Style.
(syms_of_lread): New defvar.
* test/lisp/progmodes/elisp-mode-tests.el (xref-tests-prefer-source):
Test it.
* test/lisp/progmodes/xref-tests.el
(xref-matches-in-directory-finds-none-for-some-regexp): Style.
(xref--buf-pairs-iterator-groups-markers-by-buffers-1): Style.
(xref--buf-pairs-iterator-groups-markers-by-buffers-2): Style.
(xref--buf-pairs-iterator-cleans-up-markers): Style.
---
 lisp/emacs-lisp/find-func.el            | 119 +++++++------
 lisp/help-fns.el                        |  55 +++---
 lisp/help-mode.el                       |  13 +-
 lisp/progmodes/elisp-mode.el            | 214 +++++++++++-------------
 lisp/progmodes/project.el               |   2 +-
 lisp/progmodes/xref.el                  |  56 +++++--
 src/emacs.c                             |  13 +-
 src/lread.c                             | 154 ++++++-----------
 test/lisp/progmodes/elisp-mode-tests.el |  42 +++++
 test/lisp/progmodes/xref-tests.el       |  14 +-
 10 files changed, 343 insertions(+), 339 deletions(-)

diff --git a/lisp/emacs-lisp/find-func.el b/lisp/emacs-lisp/find-func.el
index 96eaf1ab642..063e3c8bcd7 100644
--- a/lisp/emacs-lisp/find-func.el
+++ b/lisp/emacs-lisp/find-func.el
@@ -143,6 +143,7 @@ find-function--defface
 
 (defvar find-function-regexp-alist
   '((nil . find-function-regexp)
+    (define-type . find-function-regexp)
     (defvar . find-variable-regexp)
     (defface . find-function--defface)
     (feature . find-feature-regexp)
@@ -257,7 +258,7 @@ find-library--from-load-history
 
 (defvar find-function-C-source-directory
   (let ((dir (expand-file-name "src" source-directory)))
-    (if (file-accessible-directory-p dir) dir))
+    (when (file-accessible-directory-p dir) dir))
   "Directory where the C source files of Emacs can be found.
 If nil, do not try to find the source code of functions and variables
 defined in C.")
@@ -283,8 +284,8 @@ find-function-C-source
                  (read-directory-name "Emacs C source dir: " nil nil t))))
     (setq file (expand-file-name file dir))
     (if (file-readable-p file)
-        (if (null find-function-C-source-directory)
-            (setq find-function-C-source-directory dir))
+        (unless find-function-C-source-directory
+          (setq find-function-C-source-directory dir))
       (error "The C source file %s is not available"
              (file-name-nondirectory file))))
   (unless type
@@ -391,16 +392,18 @@ find-library-other-frame
 
 ;;;###autoload
 (defun find-function-search-for-symbol (symbol type library)
-  "Search for SYMBOL's definition of type TYPE in LIBRARY.
-Visit the library in a buffer, and return a cons cell (BUFFER . POSITION),
-or just (BUFFER . nil) if the definition can't be found in the file.
-
-If TYPE is nil, look for a function definition.
-Otherwise, TYPE specifies the kind of definition,
-and it is interpreted via `find-function-regexp-alist'.
-The search is done in the source for library LIBRARY."
-  (if (null library)
-      (error "Don't know where `%s' is defined" symbol))
+  "Find SYMBOL's defun, or other definitional TYPE, in LIBRARY.
+When TYPE is a non-nil key in `find-function-regexp-alist',
+interpret SYMBOL according to the corresponding definitional,
+e.g., defvar or defface.
+
+After visiting file LIBRARY, return a cons cell (BUFFER
+. POS), where POS is the character position of the definition,
+or nil if not found.
+
+LIBRARY can be an absolute or relative path."
+  (unless library
+    (error "Don't know where `%s' is defined" symbol))
   ;; Some functions are defined as part of the construct
   ;; that defines something else.
   (while (and (symbolp symbol) (get symbol 'definition-name))
@@ -413,48 +416,54 @@ find-function-search-for-symbol
     ;; .emacs too.
     (when (string-match "\\.emacs\\(.el\\)" library)
       (setq library (substring library 0 (match-beginning 1))))
-    (let* ((filename (find-library-name library))
-	   (regexp-symbol (cdr (assq type find-function-regexp-alist))))
-      (with-current-buffer (find-file-noselect filename)
-	(let ((regexp (if (functionp regexp-symbol) regexp-symbol
-                        (format (symbol-value regexp-symbol)
-                                ;; Entry for ` (backquote) macro in loaddefs.el,
-                                ;; (defalias (quote \`)..., has a \ but
-                                ;; (symbol-name symbol) doesn't.  Add an
-                                ;; optional \ to catch this.
-                                (concat "\\\\?"
-                                        (regexp-quote (symbol-name symbol))))))
-	      (case-fold-search))
-          (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)))
-                ;; If the regexp search didn't find the location of
-                ;; the symbol (for example, because it is generated by
-                ;; a macro), try a slightly more expensive search that
-                ;; expands macros until it finds the symbol.
-                (cons (current-buffer)
-                      (find-function--search-by-expanding-macros
-                       (current-buffer) symbol type))))))))))
+    (let ((filename (find-library-name library))
+	  (regexp-symbol (cdr (assq type find-function-regexp-alist))))
+      (cond ((not filename)
+             (error "Could not find '%s'" library))
+            ((not regexp-symbol)
+             (error "No find-function regexp entry for '%s'" type))
+            (t
+             (with-current-buffer (find-file-noselect filename)
+	       (let ((regexp (if (functionp regexp-symbol)
+                                 regexp-symbol
+                               (format (symbol-value regexp-symbol)
+                                       ;; Entry for ` (backquote) macro in loaddefs.el,
+                                       ;; (defalias (quote \`)..., has a \ but
+                                       ;; (symbol-name symbol) doesn't.  Add an
+                                       ;; optional \ to catch this.
+                                       (concat "\\\\?"
+                                               (regexp-quote (symbol-name symbol))))))
+	             (case-fold-search))
+                 (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)))
+                       ;; If the regexp search didn't find the location of
+                       ;; the symbol (for example, because it is generated by
+                       ;; a macro), try a slightly more expensive search that
+                       ;; expands macros until it finds the symbol.
+                       (cons (current-buffer)
+                             (find-function--search-by-expanding-macros
+                              (current-buffer) symbol type))))))))))))
 
 (defun find-function--try-macroexpand (form)
   "Try to macroexpand FORM in full or partially.
diff --git a/lisp/help-fns.el b/lisp/help-fns.el
index f200077faec..cab712a2f1f 100644
--- a/lisp/help-fns.el
+++ b/lisp/help-fns.el
@@ -299,8 +299,8 @@ describe-command
 ;;;###autoload
 (defun help-C-file-name (subr-or-var kind)
   "Return the name of the C file where SUBR-OR-VAR is defined.
-KIND should be `var' for a variable or `subr' for a subroutine.
-If we can't find the file name, nil is returned."
+KIND should be 'var for a variable or 'subr for a subroutine.  If
+we can't find the file name, nil is returned."
   (let ((docbuf (get-buffer-create " *DOC*"))
 	(name (if (eq 'var kind)
 		  (concat "V" (symbol-name subr-or-var))
@@ -309,29 +309,28 @@ help-C-file-name
                               (subr-name (advice--cd*r subr-or-var)))))))
     (with-current-buffer docbuf
       (goto-char (point-min))
-      (if (eobp)
-	  (insert-file-contents-literally
-	   (expand-file-name internal-doc-file-name doc-directory)))
-      (let ((file (catch 'loop
+      (when (eobp)
+	(insert-file-contents-literally
+	 (expand-file-name internal-doc-file-name doc-directory)))
+      (when-let ((file
+                  (catch 'loop
 		    (while t
-		      (let ((pnt (search-forward (concat "\^_" name "\n")
-                                                 nil t)))
-                        (if (not pnt)
-                            (throw 'loop nil)
-			  (re-search-backward "\^_S\\(.*\\)")
-			  (let ((file (match-string 1)))
-			    (if (member file build-files)
-			        (throw 'loop file)
-			      (goto-char pnt)))))))))
-        (if (not file)
-            nil
-	  (if (string-match "^ns.*\\(\\.o\\|obj\\)\\'" file)
-	      (setq file (replace-match ".m" t t file 1))
-	    (if (string-match "\\.\\(o\\|obj\\)\\'" file)
-	        (setq file (replace-match ".c" t t file))))
-	  (if (string-match "\\.\\(c\\|m\\)\\'" file)
-	      (concat "src/" file)
-	    file))))))
+		      (if-let ((pnt (search-forward (concat "\^_" name "\n")
+                                                    nil t)))
+                          (progn
+			    (re-search-backward "\^_S\\(.*\\)")
+			    (let ((file (match-string 1)))
+			      (if (member file build-files)
+			          (throw 'loop file)
+			        (goto-char pnt))))
+                        (throw 'loop nil))))))
+        (if (string-match "^ns.*\\(\\.o\\|obj\\)\\'" file)
+	    (setq file (replace-match ".m" t t file 1))
+	  (if (string-match "\\.\\(o\\|obj\\)\\'" file)
+	      (setq file (replace-match ".c" t t file))))
+	(if (string-match "\\.\\(c\\|m\\)\\'" file)
+	    (concat "src/" file)
+	  file)))))
 
 (defcustom help-downcase-arguments nil
   "If non-nil, argument names in *Help* buffers are downcased."
@@ -440,10 +439,10 @@ find-lisp-object-file-name
       ;; An autoloaded variable or face.  Visit loaddefs.el in a buffer
       ;; and try to extract the defining file.  The following form is
       ;; from `describe-function-1' and `describe-variable'.
-      (let ((location
-	     (condition-case nil
-		 (find-function-search-for-symbol object nil file-name)
-	       (error nil))))
+      (let* ((prefer-file (xref-preferred-source file-name))
+             (location
+	      (ignore-errors
+	        (find-function-search-for-symbol object nil prefer-file))))
 	(when (cdr location)
 	  (with-current-buffer (car location)
 	    (goto-char (cdr location))
diff --git a/lisp/help-mode.el b/lisp/help-mode.el
index 2fcb8b9f3e6..ba3b9d4f4b5 100644
--- a/lisp/help-mode.el
+++ b/lisp/help-mode.el
@@ -30,6 +30,7 @@
 ;;; Code:
 
 (require 'cl-lib)
+(require 'xref)
 
 (defvar help-mode-map
   (let ((map (make-sparse-keymap)))
@@ -265,8 +266,9 @@ help-function-def--button-function
             (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* ((prefer-file (xref-preferred-source file))
+           (location
+            (find-function-search-for-symbol fun type prefer-file))
            (position (cdr location)))
       (if help-window-keep-selected
           (pop-to-buffer-same-window (car location))
@@ -338,9 +340,10 @@ 'help-face-def
 		   (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))
-                         (position (cdr location)))
+		   (let* ((prefer-file (xref-preferred-source file))
+                          (location
+			   (find-function-search-for-symbol fun 'defface prefer-file))
+                          (position (cdr location)))
                      (if help-window-keep-selected
                          (pop-to-buffer-same-window (car location))
 		       (pop-to-buffer (car location)))
diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el
index 77bf3f1ed18..a59b2639b70 100644
--- a/lisp/progmodes/elisp-mode.el
+++ b/lisp/progmodes/elisp-mode.el
@@ -975,17 +975,16 @@ xref-backend-identifier-at-point
 
 (cl-defmethod xref-backend-definitions ((_backend (eql 'elisp)) identifier)
   (require 'find-func)
-  (let ((sym (intern-soft identifier)))
-    (when sym
-      (let* ((pos (get-text-property 0 'pos identifier))
-             (namespace (if pos
-                            (elisp--xref-infer-namespace pos)
-                          'any))
-             (defs (elisp--xref-find-definitions sym)))
-        (if (eq namespace 'maybe-variable)
-            (or (elisp--xref-filter-definitions defs 'variable sym)
-                (elisp--xref-filter-definitions defs 'any sym))
-          (elisp--xref-filter-definitions defs namespace sym))))))
+  (when-let ((sym (intern-soft identifier)))
+    (let* ((pos (get-text-property 0 'pos identifier))
+           (namespace (if pos
+                          (elisp--xref-infer-namespace pos)
+                        'any))
+           (defs (elisp--xref-find-definitions sym)))
+      (if (eq namespace 'maybe-variable)
+          (or (elisp--xref-filter-definitions defs 'variable sym)
+              (elisp--xref-filter-definitions defs 'any sym))
+        (elisp--xref-filter-definitions defs namespace sym)))))
 
 (defun elisp--xref-filter-definitions (definitions namespace symbol)
   (if (eq namespace 'any)
@@ -1019,11 +1018,10 @@ elisp--xref-filter-definitions
                collect d))))
 
 (defun elisp--xref-find-definitions (symbol)
-  ;; The file name is not known when `symbol' is defined via interactive eval.
+  ;; The file name is not known when SYMBOL is defined via interactive eval.
   (let (xrefs)
     (let ((temp elisp-xref-find-def-functions))
-      (while (and (null xrefs)
-                  temp)
+      (while (and temp (null xrefs))
         (setq xrefs (append xrefs (funcall (pop temp) symbol)))))
 
     (unless xrefs
@@ -1051,114 +1049,99 @@ elisp--xref-find-definitions
             (push (elisp--xref-make-xref 'defalias alias-symbol alias-file) xrefs))))
 
       (when (facep symbol)
-        (let ((file (find-lisp-object-file-name symbol 'defface)))
-          (when file
-            (push (elisp--xref-make-xref 'defface symbol file) xrefs))))
+        (when-let ((file (find-lisp-object-file-name symbol 'defface)))
+          (push (elisp--xref-make-xref 'defface symbol file) xrefs)))
 
       (when (fboundp symbol)
         (let ((file (find-lisp-object-file-name symbol (symbol-function symbol)))
               generic doc)
-          (when file
-            (cond
-             ((eq file 'C-source)
-              ;; First call to find-lisp-object-file-name for an object
-              ;; defined in C; the doc strings from the C source have
-              ;; not been loaded yet.  Second call will return "src/*.c"
-              ;; in file; handled by t case below.
-              (push (elisp--xref-make-xref nil symbol (help-C-file-name (symbol-function symbol) 'subr)) xrefs))
-
-             ((and (setq doc (documentation symbol t))
-                   ;; This doc string is defined in cl-macs.el cl-defstruct
-                   (string-match "Constructor for objects of type `\\(.*\\)'" doc))
-              ;; `symbol' is a name for the default constructor created by
-              ;; cl-defstruct, so return the location of the cl-defstruct.
-              (let* ((type-name (match-string 1 doc))
-                     (type-symbol (intern type-name))
-                     (file (find-lisp-object-file-name type-symbol 'define-type))
-                     (summary (format elisp--xref-format-extra
-                                      'cl-defstruct
-                                      (concat "(" type-name)
-                                      (concat "(:constructor " (symbol-name symbol) "))"))))
-                (push (elisp--xref-make-xref 'define-type type-symbol file summary) xrefs)
-                ))
-
-             ((setq generic (cl--generic symbol))
-              ;; FIXME: move this to elisp-xref-find-def-functions, in cl-generic.el
-              ;; XXX: How are we going to support using newer xref
-              ;; with older versions of Emacs, though?
-
-              ;; A generic function. If there is a default method, it
-              ;; will appear in the method table, with no
-              ;; specializers.
-              ;;
-              ;; If the default method is declared by the cl-defgeneric
-              ;; declaration, it will have the same location as the
-              ;; cl-defgeneric, so we want to exclude it from the
-              ;; result. In this case, it will have a null doc
-              ;; string. User declarations of default methods may also
-              ;; have null doc strings, but we hope that is
-              ;; rare. Perhaps this heuristic will discourage that.
-              (dolist (method (cl--generic-method-table generic))
-                (let* ((info (cl--generic-method-info method));; qual-string combined-args doconly
-                       (specializers (cl--generic-method-specializers method))
-                       (non-default nil)
-                       (met-name (cl--generic-load-hist-format
-                                  symbol
-                                  (cl--generic-method-qualifiers method)
-                                  specializers))
-                       (file (find-lisp-object-file-name met-name 'cl-defmethod)))
-                  (dolist (item specializers)
-                    ;; Default method has all t in specializers.
-                    (setq non-default (or non-default (not (equal t item)))))
-
-                  (when (and file
-                             (or non-default
-                                 (nth 2 info))) ;; assuming only co-located default has null doc string
-                    (if specializers
-                        (let ((summary (format elisp--xref-format-extra 'cl-defmethod symbol (nth 1 info))))
-                          (push (elisp--xref-make-xref 'cl-defmethod met-name file summary) xrefs))
-
-                      (let ((summary (format elisp--xref-format-extra 'cl-defmethod symbol "()")))
-                        (push (elisp--xref-make-xref 'cl-defmethod met-name file summary) xrefs))))
-                  ))
-
-              (if (and (setq doc (documentation symbol t))
-                       ;; This doc string is created somewhere in
-                       ;; cl--generic-make-function for an implicit
-                       ;; defgeneric.
-                       (string-match "\n\n(fn ARG &rest ARGS)" doc))
-                  ;; This symbol is an implicitly defined defgeneric, so
-                  ;; don't return it.
-                  nil
-                (push (elisp--xref-make-xref 'cl-defgeneric symbol file) xrefs))
-              )
-
-             (t
-              (push (elisp--xref-make-xref nil symbol file) xrefs))
-             ))))
+          (cond
+           ((not file) nil)
+           ((eq file 'C-source)
+            ;; First call to find-lisp-object-file-name for an object
+            ;; defined in C; the doc strings from the C source have
+            ;; not been loaded yet.  Second call will return "src/*.c"
+            ;; in file; handled by t case below.
+            (push (elisp--xref-make-xref
+                   nil symbol (help-C-file-name (symbol-function symbol) 'subr))
+                  xrefs))
+
+           ((and (setq doc (documentation symbol t))
+                 ;; This doc string is defined in cl-macs.el cl-defstruct
+                 (string-match "Constructor for objects of type `\\(.*\\)'" doc))
+            ;; SYMBOL is a name for the default constructor created by
+            ;; cl-defstruct, so return the location of the cl-defstruct.
+            (let* ((type-name (match-string 1 doc))
+                   (type-symbol (intern type-name))
+                   (file (find-lisp-object-file-name type-symbol 'define-type))
+                   (summary (format elisp--xref-format-extra
+                                    'cl-defstruct
+                                    (concat "(" type-name)
+                                    (concat "(:constructor " (symbol-name symbol) "))"))))
+              (push (elisp--xref-make-xref 'define-type type-symbol file summary) xrefs)))
+
+           ((setq generic (cl--generic symbol))
+            ;; FIXME: move this to elisp-xref-find-def-functions, in cl-generic.el
+            ;; XXX: How are we going to support using newer xref
+            ;; with older versions of Emacs, though?
+
+            ;; A generic function. If there is a default method, it
+            ;; will appear in the method table, with no
+            ;; specializers.
+            ;;
+            ;; If the default method is declared by the cl-defgeneric
+            ;; declaration, it will have the same location as the
+            ;; cl-defgeneric, so we want to exclude it from the
+            ;; result. In this case, it will have a null doc
+            ;; string. User declarations of default methods may also
+            ;; have null doc strings, but we hope that is
+            ;; rare. Perhaps this heuristic will discourage that.
+            (dolist (method (cl--generic-method-table generic))
+              (let* ((info (cl--generic-method-info method));; qual-string combined-args doconly
+                     (specializers (cl--generic-method-specializers method))
+                     (non-default nil)
+                     (met-name (cl--generic-load-hist-format
+                                symbol
+                                (cl--generic-method-qualifiers method)
+                                specializers))
+                     (file (find-lisp-object-file-name met-name 'cl-defmethod)))
+                (dolist (item specializers)
+                  ;; Default method has all t in specializers.
+                  (setq non-default (or non-default (not (equal t item)))))
+
+                (when (and file
+                           ;; only co-located default has null doc string
+                           (or non-default (nth 2 info)))
+                  (if specializers
+                      (let ((summary (format elisp--xref-format-extra 'cl-defmethod symbol (nth 1 info))))
+                        (push (elisp--xref-make-xref 'cl-defmethod met-name file summary) xrefs))
+
+                    (let ((summary (format elisp--xref-format-extra 'cl-defmethod symbol "()")))
+                      (push (elisp--xref-make-xref 'cl-defmethod met-name file summary) xrefs))))))
+
+            (unless (and (setq doc (documentation symbol t))
+                         ;; Fails when cl--generic-get-dispatcher changed.
+                         (string-match-p "\n\n(fn \\(ARG \\)?&rest ARGS[0-9]*)" doc))
+              ;; symbol is explicit defgeneric
+              (push (elisp--xref-make-xref 'cl-defgeneric symbol file) xrefs)))
+
+           (t
+            (push (elisp--xref-make-xref nil symbol file) xrefs)))))
 
       (when (boundp symbol)
-        ;; A variable
-        (let ((file (find-lisp-object-file-name symbol 'defvar)))
-          (when file
-            (cond
-             ((eq file 'C-source)
-              ;; The doc strings from the C source have not been loaded
-              ;; yet; help-C-file-name does that.  Second call will
-              ;; return "src/*.c" in file; handled below.
-              (push (elisp--xref-make-xref 'defvar symbol (help-C-file-name symbol 'var)) xrefs))
-
-             (t
-              (push (elisp--xref-make-xref 'defvar symbol file) xrefs))
-
-             ))))
+        (when-let ((file (find-lisp-object-file-name symbol 'defvar)))
+          (if (eq file 'C-source)
+           ;; The doc strings from the C source have not been loaded
+           ;; yet; help-C-file-name does that.  Second call will
+           ;; return "src/*.c" in file; handled below.
+              (push (elisp--xref-make-xref 'defvar symbol
+                                           (help-C-file-name symbol 'var)) xrefs)
+            (push (elisp--xref-make-xref 'defvar symbol file) xrefs))))
 
       (when (featurep symbol)
-        (let ((file (ignore-errors
-                      (find-library-name (symbol-name symbol)))))
-          (when file
-            (push (elisp--xref-make-xref 'feature symbol file) xrefs))))
-      );; 'unless xrefs'
+        (when-let ((file (ignore-errors
+                           (find-library-name (symbol-name symbol)))))
+          (push (elisp--xref-make-xref 'feature symbol file) xrefs))))
 
     xrefs))
 
@@ -1193,7 +1176,8 @@ xref-backend-identifier-completion-table
 
 (cl-defmethod xref-location-marker ((l xref-elisp-location))
   (pcase-let (((cl-struct xref-elisp-location symbol type file) l))
-    (let ((buffer-point (find-function-search-for-symbol symbol type file)))
+    (let* ((prefer-file (xref-preferred-source file))
+           (buffer-point (find-function-search-for-symbol symbol type prefer-file)))
       (with-current-buffer (car buffer-point)
         (save-excursion
           (save-restriction
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index 4dc4762176a..86c2497e9fb 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -227,7 +227,7 @@ project-root
 (cl-defmethod project-root (project
                             &context (project--within-roots-fallback
                                       (eql nil)))
-  (car (project-roots project)))
+  (cl-call-next-method project))
 
 (cl-defgeneric project-roots (project)
   "Return the list containing the current project root.
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index 683589d71c6..95714d0488b 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -427,8 +427,36 @@ xref-auto-jump-to-first-xref
   :version "28.1"
   :package-version '(xref . "1.2.0"))
 
+(defcustom xref-prefer-source-directory nil
+  "If non-nil, jump to the file in `source-directory' that
+corresponds to the target."
+  :type 'boolean
+  :version "29.1")
+
 (make-obsolete-variable 'xref--marker-ring 'xref--history "29.1")
 
+(defalias 'xref-preferred-message
+  (let (messaged-p)
+    (lambda (file)
+      "Heads-up to user that xref result may not reflect loaded definition."
+      (unless messaged-p
+        (setq messaged-p t)
+        (message "Showing result from %s" file)))))
+
+(defsubst xref-preferred-source (file)
+  (if-let ((preferred-p xref-prefer-source-directory)
+           (prefix (file-name-as-directory installed-directory))
+           ;; :end2 says PREFIX matches beginning of LIBRARY
+           (installed-p (cl-search prefix file
+                                   :end2 (length prefix)))
+           (preferred (expand-file-name
+                       (cl-subseq file (length prefix))
+                       source-directory))
+           (readable-p (file-readable-p preferred)))
+      (prog1 preferred
+        (funcall (symbol-function 'xref-preferred-message) preferred))
+    file))
+
 (defun xref-set-marker-ring-length (_var _val)
   (declare (obsolete nil "29.1"))
   nil)
@@ -1193,21 +1221,15 @@ xref--auto-jump-first
 
 (defun xref-show-definitions-buffer (fetcher alist)
   "Show the definitions list in a regular window.
-
 When only one definition found, jump to it right away instead."
-  (let ((xrefs (funcall fetcher))
-        buf)
-    (cond
-     ((not (cdr xrefs))
-      (xref-pop-to-location (car xrefs)
-                            (assoc-default 'display-action alist)))
-     (t
-      (setq buf
-            (xref--show-xref-buffer fetcher
-                                    (cons (cons 'fetched-xrefs xrefs)
-                                          alist)))
-      (xref--auto-jump-first buf (assoc-default 'auto-jump alist))
-      buf))))
+  (when-let ((xrefs (funcall fetcher)))
+    (if (= 1 (length xrefs))
+        (xref-pop-to-location (car xrefs)
+                              (assoc-default 'display-action alist))
+      (let ((buf (xref--show-xref-buffer
+                  fetcher (cons (cons 'fetched-xrefs xrefs) alist))))
+        (prog1 buf
+          (xref--auto-jump-first buf (assoc-default 'auto-jump alist)))))))
 
 (define-obsolete-function-alias
   'xref--show-defs-buffer #'xref-show-definitions-buffer "28.1")
@@ -1459,10 +1481,8 @@ xref--create-fetcher
         (when (buffer-live-p orig-buffer)
           (set-buffer orig-buffer)
           (ignore-errors (goto-char orig-position)))
-        (let ((xrefs (funcall method backend arg)))
-          (unless xrefs
-            (xref--not-found-error kind input))
-          xrefs)))))
+        (or (funcall method backend arg)
+            (xref--not-found-error kind input))))))
 
 (defun xref--not-found-error (kind input)
   (user-error "No %s found for: %s" (symbol-name kind) input))
diff --git a/src/emacs.c b/src/emacs.c
index 43b9901e081..f83923bc6af 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -3503,12 +3503,13 @@ syms_of_emacs (void)
 The value is nil if that directory's name is not known.  */);
 
   DEFVAR_LISP ("installation-directory", Vinstallation_directory,
-	       doc: /* A directory within which to look for the `lib-src' and `etc' directories.
-In an installed Emacs, this is normally nil.  It is non-nil if
-both `lib-src' (on MS-DOS, `info') and `etc' directories are found
-within the variable `invocation-directory' or its parent.  For example,
-this is the case when running an uninstalled Emacs executable from its
-build directory.  */);
+	       doc: /* Should have been named build-directory.
+Counter-intuitively, this variable is nil when Emacs is invoked from
+its `make install` executable.  It normally takes on the value of
+`source-directory' when Emacs is invoked from its within-repo `make`
+executable.  Its primary use is locating the lib-src and etc
+subdirectories of the build.  Not to be confused with
+`installed-directory'.  */);
   Vinstallation_directory = Qnil;
 
   DEFVAR_LISP ("system-messages-locale", Vsystem_messages_locale,
diff --git a/src/lread.c b/src/lread.c
index 4b7d38a8e6c..e953c1dc7be 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -5108,136 +5108,73 @@ load_path_check (Lisp_Object lpath)
     }
 }
 
-/* Return the default load-path, to be used if EMACSLOADPATH is unset.
-   This does not include the standard site-lisp directories
-   under the installation prefix (i.e., PATH_SITELOADSEARCH),
-   but it does (unless no_site_lisp is set) include site-lisp
-   directories in the source/build directories if those exist and we
-   are running uninstalled.
-
-   Uses the following logic:
-   If !will_dump: Use PATH_LOADSEARCH.
-   The remainder is what happens when dumping is about to happen:
-   If dumping, just use PATH_DUMPLOADSEARCH.
-   Otherwise use PATH_LOADSEARCH.
-
-   If !initialized, then just return PATH_DUMPLOADSEARCH.
-   If initialized:
-   If Vinstallation_directory is not nil (ie, running uninstalled):
-   If installation-dir/lisp exists and not already a member,
-   we must be running uninstalled.  Reset the load-path
-   to just installation-dir/lisp.  (The default PATH_LOADSEARCH
-   refers to the eventual installation directories.  Since we
-   are not yet installed, we should not use them, even if they exist.)
-   If installation-dir/lisp does not exist, just add
-   PATH_DUMPLOADSEARCH at the end instead.
-   Add installation-dir/site-lisp (if !no_site_lisp, and exists
-   and not already a member) at the front.
-   If installation-dir != source-dir (ie running an uninstalled,
-   out-of-tree build) AND install-dir/src/Makefile exists BUT
-   install-dir/src/Makefile.in does NOT exist (this is a sanity
-   check), then repeat the above steps for source-dir/lisp, site-lisp.  */
+/* Dig toplevel LOAD-PATH out of epaths.h.  */
 
 static Lisp_Object
 load_path_default (void)
 {
   if (will_dump_p ())
-    /* PATH_DUMPLOADSEARCH is the lisp dir in the source directory.
-       We used to add ../lisp (ie the lisp dir in the build
-       directory) at the front here, but that should not be
-       necessary, since in out of tree builds lisp/ is empty, save
-       for Makefile.  */
+    /* PATH_DUMPLOADSEARCH is the lisp dir in the source directory.  */
     return decode_env_path (0, PATH_DUMPLOADSEARCH, 0);
 
-  Lisp_Object lpath = Qnil;
-
-  lpath = decode_env_path (0, PATH_LOADSEARCH, 0);
+  Lisp_Object lpath = decode_env_path (0, PATH_LOADSEARCH, 0);
 
+  /* Counter-intuitively Vinstallation_directory is nil for
+     invocations of the `make install` executable, and is
+     Vsource_directory for invocations of the within-repo `make`
+     executable.
+  */
   if (!NILP (Vinstallation_directory))
     {
-      Lisp_Object tem, tem1;
-
-      /* Add to the path the lisp subdir of the installation
-         dir, if it is accessible.  Note: in out-of-tree builds,
-         this directory is empty save for Makefile.  */
-      tem = Fexpand_file_name (build_string ("lisp"),
-                               Vinstallation_directory);
-      tem1 = Ffile_accessible_directory_p (tem);
-      if (!NILP (tem1))
-        {
-          if (NILP (Fmember (tem, lpath)))
-            {
-              /* We are running uninstalled.  The default load-path
-                 points to the eventual installed lisp directories.
-                 We should not use those now, even if they exist,
-                 so start over from a clean slate.  */
-              lpath = list1 (tem);
-            }
-        }
-      else
-        /* That dir doesn't exist, so add the build-time
-           Lisp dirs instead.  */
-        {
-          Lisp_Object dump_path =
-            decode_env_path (0, PATH_DUMPLOADSEARCH, 0);
-          lpath = nconc2 (lpath, dump_path);
-        }
-
-      /* Add site-lisp under the installation dir, if it exists.  */
-      if (!no_site_lisp)
+      Lisp_Object tem = Fexpand_file_name (build_string ("lisp"),
+					   Vinstallation_directory),
+	tem1 = Ffile_accessible_directory_p (tem);
+
+      if (NILP (tem1))
+	/* Use build-time dirs instead.  */
+	lpath = nconc2 (lpath, decode_env_path (0, PATH_DUMPLOADSEARCH, 0));
+      else if (NILP (Fmember (tem, lpath)))
+	/* Override the inchoate LOAD-PATH.  */
+	lpath = list1 (tem);
+
+      /* Add the within-repo site-lisp (unusual).  */
+      if (! no_site_lisp)
         {
           tem = Fexpand_file_name (build_string ("site-lisp"),
                                    Vinstallation_directory);
           tem1 = Ffile_accessible_directory_p (tem);
-          if (!NILP (tem1))
-            {
-              if (NILP (Fmember (tem, lpath)))
-                lpath = Fcons (tem, lpath);
-            }
+          if (! NILP (tem1) && (NILP (Fmember (tem, lpath))))
+	    lpath = Fcons (tem, lpath);
         }
 
-      /* If Emacs was not built in the source directory,
-         and it is run from where it was built, add to load-path
-         the lisp and site-lisp dirs under that directory.  */
-
       if (NILP (Fequal (Vinstallation_directory, Vsource_directory)))
         {
-          Lisp_Object tem2;
-
+	  /* An out-of-tree build (unusual).  */
           tem = Fexpand_file_name (build_string ("src/Makefile"),
                                    Vinstallation_directory);
-          tem1 = Ffile_exists_p (tem);
+          tem1 = Fexpand_file_name (build_string ("src/Makefile.in"),
+				    Vinstallation_directory);
 
           /* Don't be fooled if they moved the entire source tree
              AFTER dumping Emacs.  If the build directory is indeed
              different from the source dir, src/Makefile.in and
              src/Makefile will not be found together.  */
-          tem = Fexpand_file_name (build_string ("src/Makefile.in"),
-                                   Vinstallation_directory);
-          tem2 = Ffile_exists_p (tem);
-          if (!NILP (tem1) && NILP (tem2))
+          if (! NILP (Ffile_exists_p (tem)) && NILP (Ffile_exists_p (tem1)))
             {
               tem = Fexpand_file_name (build_string ("lisp"),
                                        Vsource_directory);
-
               if (NILP (Fmember (tem, lpath)))
                 lpath = Fcons (tem, lpath);
-
-              if (!no_site_lisp)
+              if (! no_site_lisp)
                 {
                   tem = Fexpand_file_name (build_string ("site-lisp"),
                                            Vsource_directory);
-                  tem1 = Ffile_accessible_directory_p (tem);
-                  if (!NILP (tem1))
-                    {
-                      if (NILP (Fmember (tem, lpath)))
-                        lpath = Fcons (tem, lpath);
-                    }
+                  if (! NILP (tem) && (NILP (Fmember (tem, lpath))))
+		    lpath = Fcons (tem, lpath);
                 }
             }
-        } /* Vinstallation_directory != Vsource_directory */
-
-    } /* if Vinstallation_directory */
+        }
+    }
 
   return lpath;
 }
@@ -5248,7 +5185,7 @@ init_lread (void)
   /* First, set Vload_path.  */
 
   /* Ignore EMACSLOADPATH when dumping.  */
-  bool use_loadpath = !will_dump_p ();
+  bool use_loadpath = ! will_dump_p ();
 
   if (use_loadpath && egetenv ("EMACSLOADPATH"))
     {
@@ -5268,10 +5205,9 @@ init_lread (void)
           load_path_check (default_lpath);
 
           /* Add the site-lisp directories to the front of the default.  */
-          if (!no_site_lisp && PATH_SITELOADSEARCH[0] != '\0')
+          if (! no_site_lisp && PATH_SITELOADSEARCH[0] != '\0')
             {
-              Lisp_Object sitelisp;
-              sitelisp = decode_env_path (0, PATH_SITELOADSEARCH, 0);
+              Lisp_Object sitelisp = decode_env_path (0, PATH_SITELOADSEARCH, 0);
               if (! NILP (sitelisp))
                 default_lpath = nconc2 (sitelisp, default_lpath);
             }
@@ -5286,7 +5222,7 @@ init_lread (void)
               Vload_path = CALLN (Fappend, Vload_path,
 				  NILP (elem) ? default_lpath : list1 (elem));
             }
-        }                       /* Fmemq (Qnil, Vload_path) */
+        }
     }
   else
     {
@@ -5299,11 +5235,11 @@ init_lread (void)
       load_path_check (Vload_path);
 
       /* Add the site-lisp directories at the front.  */
-      if (!will_dump_p () && !no_site_lisp && PATH_SITELOADSEARCH[0] != '\0')
+      if (! will_dump_p () && !no_site_lisp && PATH_SITELOADSEARCH[0] != '\0')
         {
-          Lisp_Object sitelisp;
-          sitelisp = decode_env_path (0, PATH_SITELOADSEARCH, 0);
-          if (! NILP (sitelisp)) Vload_path = nconc2 (sitelisp, Vload_path);
+          Lisp_Object sitelisp = decode_env_path (0, PATH_SITELOADSEARCH, 0);
+          if (! NILP (sitelisp))
+	    Vload_path = nconc2 (sitelisp, Vload_path);
         }
     }
 
@@ -5544,6 +5480,16 @@ syms_of_lread (void)
     = Fexpand_file_name (build_string ("../"),
 			 Fcar (decode_env_path (0, PATH_DUMPLOADSEARCH, 0)));
 
+  DEFVAR_LISP ("installed-directory", Vinstalled_directory,
+	       doc: /* Install path of built-in lisp libraries.
+This directory contains the `etc`, `lisp`, and `site-lisp`
+installables, and is determined at configure time in the epaths-force
+make target.  Not to be confused with the legacy
+`installation-directory' nor `invocation-directory'.  */);
+  Vinstalled_directory
+    = Fexpand_file_name (build_string ("../"),
+			 Fcar (decode_env_path (0, PATH_LOADSEARCH, 0)));
+
   DEFVAR_LISP ("preloaded-file-list", Vpreloaded_file_list,
 	       doc: /* List of files that were preloaded (when dumping Emacs).  */);
   Vpreloaded_file_list = Qnil;
diff --git a/test/lisp/progmodes/elisp-mode-tests.el b/test/lisp/progmodes/elisp-mode-tests.el
index 8e4dfa8bb83..cf30765df23 100644
--- a/test/lisp/progmodes/elisp-mode-tests.el
+++ b/test/lisp/progmodes/elisp-mode-tests.el
@@ -1116,5 +1116,47 @@ test-indentation
                         (emacs-lisp-mode)
                         (indent-region (point-min) (point-max)))))
 
+(ert-deftest xref-tests-prefer-source ()
+  "Jump to the file in `source-directory' that corresponds to the target."
+  (let* ((xref-show-definitions-function 'xref-show-definitions-buffer)
+         (xref-prefer-source-directory t)
+         (what "xref-backend-definitions")
+         (ert-directory (file-name-directory
+                         (ert-resource-file "simple-shorthand-test.el")))
+         (installed-path (find-lisp-object-file-name (intern what) 'defun))
+         (preferred-path (string-replace (file-name-as-directory
+                                          source-directory)
+                                         (file-name-as-directory
+                                          ert-directory)
+                                         installed-path))
+         (installed-directory source-directory)
+         (source-directory ert-directory)
+         (buf (with-temp-buffer
+                (emacs-lisp-mode)
+                (xref-find-definitions what))))
+    (unwind-protect
+        (with-current-buffer buf
+          (mkdir (file-name-directory preferred-path) t)
+          (copy-file installed-path preferred-path t)
+          (save-excursion
+            (should (re-search-forward
+                     (regexp-quote (format "cl-defmethod %s" what))
+                     nil t)))
+          (should (re-search-forward
+                   (regexp-quote (regexp-quote (format "cl-defgeneric %s" what)))
+                   nil t))
+          (call-interactively #'xref-goto-xref)
+          (should (equal (buffer-file-name) preferred-path)))
+      (let (kill-buffer-query-functions)
+        (delete-directory (expand-file-name
+                           (reverse (file-name-nondirectory
+                                     (reverse (string-replace ert-directory
+                                                              "" preferred-path))))
+                           ert-directory) t)
+        (when (buffer-live-p (get-buffer preferred-path))
+          (kill-buffer (get-buffer preferred-path)))
+        (when (buffer-live-p buf)
+          (kill-buffer buf))))))
+
 (provide 'elisp-mode-tests)
 ;;; elisp-mode-tests.el ends here
diff --git a/test/lisp/progmodes/xref-tests.el b/test/lisp/progmodes/xref-tests.el
index f7af5055c78..b2222d95521 100644
--- a/test/lisp/progmodes/xref-tests.el
+++ b/test/lisp/progmodes/xref-tests.el
@@ -44,7 +44,7 @@ xref-tests--locations-in-data-dir
              :key #'xref-location-group)))
 
 (ert-deftest xref-matches-in-directory-finds-none-for-some-regexp ()
-  (should (null (xref-tests--matches-in-data-dir "zzz"))))
+  (should-not (xref-tests--matches-in-data-dir "zzz")))
 
 (ert-deftest xref-matches-in-directory-finds-some-for-bar ()
   (let ((locs (xref-tests--locations-in-data-dir "bar")))
@@ -99,7 +99,7 @@ xref--buf-pairs-iterator-groups-markers-by-buffers-1
   (let* ((xrefs (xref-tests--matches-in-data-dir "foo"))
          (iter (xref--buf-pairs-iterator xrefs))
          (cons (funcall iter :next)))
-    (should (null (funcall iter :next)))
+    (should-not (funcall iter :next))
     (should (string-match "file1\\.txt\\'" (buffer-file-name (car cons))))
     (should (= 2 (length (cdr cons))))))
 
@@ -108,7 +108,7 @@ xref--buf-pairs-iterator-groups-markers-by-buffers-2
          (iter (xref--buf-pairs-iterator xrefs))
          (cons1 (funcall iter :next))
          (cons2 (funcall iter :next)))
-    (should (null (funcall iter :next)))
+    (should-not (funcall iter :next))
     (should-not (equal (car cons1) (car cons2)))
     (should (= 1 (length (cdr cons1))))
     (should (= 1 (length (cdr cons2))))))
@@ -119,10 +119,10 @@ xref--buf-pairs-iterator-cleans-up-markers
          (cons1 (funcall iter :next))
          (cons2 (funcall iter :next)))
     (funcall iter :cleanup)
-    (should (null (marker-position (car (nth 0 (cdr cons1))))))
-    (should (null (marker-position (cdr (nth 0 (cdr cons1))))))
-    (should (null (marker-position (car (nth 0 (cdr cons2))))))
-    (should (null (marker-position (cdr (nth 0 (cdr cons2))))))))
+    (should-not (marker-position (car (nth 0 (cdr cons1)))))
+    (should-not (marker-position (cdr (nth 0 (cdr cons1)))))
+    (should-not (marker-position (car (nth 0 (cdr cons2)))))
+    (should-not (marker-position (cdr (nth 0 (cdr cons2)))))))
 
 (ert-deftest xref--xref-file-name-display-is-abs ()
   (let ((xref-file-name-display 'abs))
-- 
2.35.1

In Commercial Emacs 0.3.1snapshot 4cf5f33 in dev (upstream 29.0.50, x86_64-pc-linux-gnu) built on dick
Repository revision: 4cf5f33b61635a9f55bcfb345b144d3c12396013
Repository branch: dev
Windowing system distributor 'The X.Org Foundation', version 11.0.12013000
System Description: Ubuntu 20.04.3 LTS

Configured using:
 'configure --prefix=/home/dick/.local --with-tree-sitter'
Configured features:
CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GSETTINGS HARFBUZZ JPEG JSON
TREE_SITTER LCMS2 LIBSELINUX LIBXML2 MODULES NOTIFY INOTIFY PDUMPER PNG
RSVG SECCOMP SOUND THREADS TIFF TOOLKIT_SCROLL_BARS WEBP X11 XDBE XIM
XINPUT2 XPM GTK3 ZLIB
Important settings:
  value of $LANG: en_US.UTF-8
  locale-coding-system: utf-8-unix

Major mode: Group

Minor modes in effect:
  global-git-commit-mode: t
  shell-dirtrack-mode: t
  gnus-topic-mode: t
  gnus-undo-mode: t
  projectile-mode: t
  flx-ido-mode: t
  override-global-mode: t
  global-hl-line-mode: t
  hl-line-mode: t
  winner-mode: t
  tooltip-mode: t
  show-paren-mode: t
  mouse-wheel-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  buffer-read-only: t
  column-number-mode: t
  line-number-mode: t
  transient-mark-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t

Load-path shadows:
/home/dick/gomacro-mode/gomacro-mode hides /home/dick/.emacs.d/elpa/gomacro-mode-20200326.1103/gomacro-mode
/home/dick/org-gcal.el/org-gcal hides /home/dick/.emacs.d/elpa/org-gcal-0.3/org-gcal
/home/dick/.emacs.d/elpa/chess-2.0.5/_pkg hides /home/dick/.local/share/emacs/site-lisp/_pkg
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-pos hides /home/dick/.local/share/emacs/site-lisp/chess-pos
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-module hides /home/dick/.local/share/emacs/site-lisp/chess-module
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-ucb hides /home/dick/.local/share/emacs/site-lisp/chess-ucb
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-scid hides /home/dick/.local/share/emacs/site-lisp/chess-scid
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-puzzle hides /home/dick/.local/share/emacs/site-lisp/chess-puzzle
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-irc hides /home/dick/.local/share/emacs/site-lisp/chess-irc
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-network hides /home/dick/.local/share/emacs/site-lisp/chess-network
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-autosave hides /home/dick/.local/share/emacs/site-lisp/chess-autosave
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-engine hides /home/dick/.local/share/emacs/site-lisp/chess-engine
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-tutorial hides /home/dick/.local/share/emacs/site-lisp/chess-tutorial
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-german hides /home/dick/.local/share/emacs/site-lisp/chess-german
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-file hides /home/dick/.local/share/emacs/site-lisp/chess-file
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-random hides /home/dick/.local/share/emacs/site-lisp/chess-random
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-stockfish hides /home/dick/.local/share/emacs/site-lisp/chess-stockfish
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-pgn hides /home/dick/.local/share/emacs/site-lisp/chess-pgn
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-kibitz hides /home/dick/.local/share/emacs/site-lisp/chess-kibitz
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-eco hides /home/dick/.local/share/emacs/site-lisp/chess-eco
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-display hides /home/dick/.local/share/emacs/site-lisp/chess-display
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-var hides /home/dick/.local/share/emacs/site-lisp/chess-var
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-test hides /home/dick/.local/share/emacs/site-lisp/chess-test
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-ply hides /home/dick/.local/share/emacs/site-lisp/chess-ply
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-message hides /home/dick/.local/share/emacs/site-lisp/chess-message
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-ics1 hides /home/dick/.local/share/emacs/site-lisp/chess-ics1
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-phalanx hides /home/dick/.local/share/emacs/site-lisp/chess-phalanx
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-game hides /home/dick/.local/share/emacs/site-lisp/chess-game
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-log hides /home/dick/.local/share/emacs/site-lisp/chess-log
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-plain hides /home/dick/.local/share/emacs/site-lisp/chess-plain
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-perft hides /home/dick/.local/share/emacs/site-lisp/chess-perft
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-glaurung hides /home/dick/.local/share/emacs/site-lisp/chess-glaurung
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-ai hides /home/dick/.local/share/emacs/site-lisp/chess-ai
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-fruit hides /home/dick/.local/share/emacs/site-lisp/chess-fruit
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-uci hides /home/dick/.local/share/emacs/site-lisp/chess-uci
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-epd hides /home/dick/.local/share/emacs/site-lisp/chess-epd
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-database hides /home/dick/.local/share/emacs/site-lisp/chess-database
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-link hides /home/dick/.local/share/emacs/site-lisp/chess-link
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-transport hides /home/dick/.local/share/emacs/site-lisp/chess-transport
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-none hides /home/dick/.local/share/emacs/site-lisp/chess-none
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-polyglot hides /home/dick/.local/share/emacs/site-lisp/chess-polyglot
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-crafty hides /home/dick/.local/share/emacs/site-lisp/chess-crafty
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-chat hides /home/dick/.local/share/emacs/site-lisp/chess-chat
/home/dick/.emacs.d/elpa/chess-2.0.5/chess hides /home/dick/.local/share/emacs/site-lisp/chess
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-images hides /home/dick/.local/share/emacs/site-lisp/chess-images
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-gnuchess hides /home/dick/.local/share/emacs/site-lisp/chess-gnuchess
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-fen hides /home/dick/.local/share/emacs/site-lisp/chess-fen
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-ics hides /home/dick/.local/share/emacs/site-lisp/chess-ics
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-ics2 hides /home/dick/.local/share/emacs/site-lisp/chess-ics2
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-common hides /home/dick/.local/share/emacs/site-lisp/chess-common
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-input hides /home/dick/.local/share/emacs/site-lisp/chess-input
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-announce hides /home/dick/.local/share/emacs/site-lisp/chess-announce
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-clock hides /home/dick/.local/share/emacs/site-lisp/chess-clock
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-sound hides /home/dick/.local/share/emacs/site-lisp/chess-sound
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-sjeng hides /home/dick/.local/share/emacs/site-lisp/chess-sjeng
/home/dick/.emacs.d/elpa/chess-2.0.5/chess-algebraic hides /home/dick/.local/share/emacs/site-lisp/chess-algebraic
/home/dick/.emacs.d/elpa/transient-0.3.7snapshot/transient hides /home/dick/.local/share/emacs/0.3.1/lisp/transient

Features:
(shadow bbdb-message footnote emacsbug flow-fill shortdoc
emms-source-file locate loadhist markdown-mode edit-indirect
magit-extras face-remap magit-patch-changelog magit-patch
magit-submodule magit-obsolete magit-blame magit-stash magit-reflog
magit-bisect magit-push magit-pull magit-fetch magit-clone magit-remote
magit-commit magit-sequence magit-notes magit-worktree magit-tag
magit-merge magit-branch magit-reset magit-files magit-refs magit-status
magit magit-repos magit-apply magit-wip magit-log which-func imenu
magit-diff git-commit log-edit pcvs-util add-log magit-core magit-margin
magit-transient magit-process with-editor server magit-mode transient
smerge-mode diff pulse find-func misearch multi-isearch vc-git diff-mode
vc vc-dispatcher bug-reference cc-mode cc-fonts cc-guess cc-menus
cc-cmds cc-styles cc-align cc-engine cc-vars cc-defs tramp-archive
tramp-gvfs tramp-cache zeroconf gnus-html url-queue help-fns radix-tree
sort smiley shr-color qp mm-archive gnus-async gnus-ml gravatar dns
mail-extr textsec uni-scripts idna-mapping ucs-normalize uni-confusable
textsec-check gnus-notifications gnus-fun notifications gnus-kill
gnus-dup disp-table utf-7 blamer a tramp tramp-loaddefs trampver
tramp-integration cus-start files-x tramp-compat shell pcomplete ls-lisp
url-cache benchmark nnrss nnfolder nndiscourse rbenv nnhackernews
nntwitter nntwitter-api bbdb-gnus gnus-demon nntp nnmairix nnml nnreddit
gnus-topic url-http url-auth url-gw network-stream nsm request
virtualenvwrapper gud s json-rpc python gnus-score score-mode gnus-bcklg
gnus-srvr gnus-cite anaphora bbdb-mua bbdb-com bbdb bbdb-site timezone
gnus-delay gnus-draft gnus-cache gnus-agent gnus-msg gnus-art mm-uu
mml2015 mm-view mml-smime smime gnutls dig gnus-sum shr pixel-fill
kinsoku url-file url-dired svg dom nndraft nnmh gnus-group mm-url
gnus-undo use-package use-package-delight use-package-diminish
gnus-start gnus-dbus dbus xml gnus-cloud nnimap nnmail mail-source utf7
netrc nnoo parse-time iso8601 gnus-spec gnus-int gnus-range message
sendmail yank-media rmc puny dired-x dired dired-loaddefs rfc822 mml
mml-sec epa epg rfc6068 epg-config mm-decode mm-bodies mm-encode
mail-parse rfc2231 rfc2047 rfc2045 ietf-drums mailabbrev gmm-utils
mailheader gnus-win paredit-ext paredit subed subed-vtt subed-srt
subed-common subed-mpv subed-debug subed-config inf-ruby ruby-mode smie
company pcase haskell-interactive-mode haskell-presentation-mode
haskell-process haskell-session haskell-compile haskell-mode
haskell-cabal haskell-utils haskell-font-lock haskell-indentation
haskell-string haskell-sort-imports haskell-lexeme haskell-align-imports
haskell-complete-module haskell-ghc-support noutline outline
flymake-proc flymake warnings etags fileloop generator dabbrev
haskell-customize hydra lv use-package-ensure solarized-theme
solarized-definitions projectile lisp-mnt ibuf-ext ibuffer
ibuffer-loaddefs thingatpt magit-autorevert autorevert filenotify
magit-git magit-base magit-section format-spec crm dash rx compat-27
compat-26 compat grep compile comint ansi-color gnus nnheader range
mail-utils mm-util mail-prsvr gnus-util text-property-search time-date
flx-ido flx google-translate-default-ui google-translate-core-ui
facemenu color ido google-translate-core google-translate-tk
google-translate-backend use-package-bind-key bind-key auto-complete
easy-mmode advice edmacro kmacro popup cus-edit pp cus-load wid-edit
emms-player-mplayer emms-player-simple emms emms-compat cl-extra
help-mode xref project use-package-core derived hl-line winner ring
finder-inf json-reformat-autoloads json-snatcher-autoloads
sml-mode-autoloads tornado-template-mode-autoloads info package
browse-url url url-proxy url-privacy url-expand url-methods url-history
url-cookie url-domsuf url-util mailcap url-handlers url-parse
auth-source cl-seq eieio eieio-core cl-macs eieio-loaddefs
password-cache json map url-vars seq gv subr-x byte-opt bytecomp
byte-compile cconv cldefs cl-loaddefs cl-lib iso-transl tooltip eldoc
paren electric uniquify ediff-hook vc-hooks lisp-float-type elisp-mode
mwheel term/x-win x-win term/common-win x-dnd tool-bar dnd fontset image
regexp-opt fringe tree-sitter tabulated-list replace newcomment
text-mode lisp-mode prog-mode register page tab-bar menu-bar rfn-eshadow
isearch easymenu timer select scroll-bar mouse jit-lock font-lock syntax
font-core term/tty-colors frame minibuffer nadvice simple cl-generic
indonesian philippine cham georgian utf-8-lang misc-lang vietnamese
tibetan thai tai-viet lao korean japanese eucjp-ms cp51932 hebrew greek
romanian slovak czech european ethiopic indian cyrillic chinese
composite emoji-zwj charscript charprop case-table epa-hook
jka-cmpr-hook help abbrev obarray oclosure cl-preloaded button loaddefs
faces cus-face macroexp files window text-properties overlay sha1 md5
base64 format env code-pages mule custom widget keymap
hashtable-print-readable backquote threads dbusbind inotify lcms2
dynamic-setting system-font-setting font-render-setting cairo
move-toolbar gtk x-toolkit xinput2 x multi-tty make-network-process
emacs)

Memory information:
((conses 16 1225093 133296)
 (symbols 48 47046 1)
 (strings 32 212452 33657)
 (string-bytes 1 6343256)
 (vectors 16 136395)
 (vector-slots 8 3462861 170930)
 (floats 8 1238 1244)
 (intervals 56 67754 1262)
 (buffers 1000 45))