]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/elisp-mode.el
Use eldoc-documentation-functions
[gnu-emacs] / lisp / progmodes / elisp-mode.el
index bcabf3cdf594b5e76e69dfca73883bf605977839..5f9bdaccd0f98e544538e798b1ecf249e152b6d4 100644 (file)
@@ -1,6 +1,6 @@
 ;;; elisp-mode.el --- Emacs Lisp mode  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1985-1986, 1999-2015 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1986, 1999-2016 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: lisp, languages
@@ -228,32 +228,25 @@ Blank lines separate paragraphs.  Semicolons start comments.
 
 \\{emacs-lisp-mode-map}"
   :group 'lisp
-  (defvar xref-find-function)
-  (defvar xref-identifier-completion-table-function)
-  (defvar project-search-path-function)
+  (defvar project-vc-external-roots-function)
   (lisp-mode-variables nil nil 'elisp)
   (add-hook 'after-load-functions #'elisp--font-lock-flush-elisp-buffers)
   (setq-local electric-pair-text-pairs
               (append '((?\` . ?\') (?‘ . ?’)) electric-pair-text-pairs))
   (setq-local electric-quote-string t)
   (setq imenu-case-fold-search nil)
-  (add-function :before-until (local 'eldoc-documentation-function)
-                #'elisp-eldoc-documentation-function)
-  (setq-local xref-find-function #'elisp-xref-find)
-  (setq-local xref-identifier-completion-table-function
-              #'elisp--xref-identifier-completion-table)
-  (setq-local project-search-path-function #'elisp-search-path)
+  (add-hook 'eldoc-documentation-functions
+            #'elisp-eldoc-documentation-function nil t)
+  (add-hook 'xref-backend-functions #'elisp--xref-backend nil t)
+  (setq-local project-vc-external-roots-function #'elisp-load-path-roots)
   (add-hook 'completion-at-point-functions
             #'elisp-completion-at-point nil 'local))
 
 ;; Font-locking support.
 
 (defun elisp--font-lock-flush-elisp-buffers (&optional file)
-  ;; FIXME: Aren't we only ever called from after-load-functions?
-  ;; Don't flush during load unless called from after-load-functions.
-  ;; In that case, FILE is non-nil.  It's somehow strange that
-  ;; load-in-progress is t when an after-load-function is called since
-  ;; that should run *after* the load...
+  ;; We're only ever called from after-load-functions, load-in-progress can
+  ;; still be t in case of nested loads.
   (when (or (not load-in-progress) file)
     ;; FIXME: If the loaded file did not define any macros, there shouldn't
     ;; be any need to font-lock-flush all the Elisp buffers.
@@ -579,8 +572,9 @@ It can be quoted, or be inside a quoted form."
                                        " " (cadr table-etc)))
                     (cddr table-etc)))))))))
 
-(define-obsolete-function-alias
-  'lisp-completion-at-point 'elisp-completion-at-point "25.1")
+(defun lisp-completion-at-point (&optional _predicate)
+  (declare (obsolete elisp-completion-at-point "25.1"))
+  (elisp-completion-at-point))
 
 ;;; Xref backend
 
@@ -588,21 +582,7 @@ It can be quoted, or be inside a quoted form."
 (declare-function xref-make "xref" (summary location))
 (declare-function xref-collect-references "xref" (symbol dir))
 
-(defun elisp-xref-find (action id)
-  (require 'find-func)
-  ;; FIXME: use information in source near point to filter results:
-  ;; (dvc-log-edit ...) - exclude 'feature
-  ;; (require 'dvc-log-edit) - only 'feature
-  ;; Semantic may provide additional information
-  (pcase action
-    (`definitions
-      (let ((sym (intern-soft id)))
-        (when sym
-          (elisp--xref-find-definitions sym))))
-    (`references
-     (elisp--xref-find-references id))
-    (`apropos
-     (elisp--xref-find-apropos id))))
+(defun elisp--xref-backend () 'elisp)
 
 ;; WORKAROUND: This is nominally a constant, but the text properties
 ;; are not preserved thru dump if use defconst.  See bug#21237.
@@ -632,16 +612,26 @@ otherwise build the summary from TYPE and SYMBOL."
             (xref-make-elisp-location symbol type file)))
 
 (defvar elisp-xref-find-def-functions nil
-  "List of functions to be run from ‘elisp--xref-find-definitions’ to add additional xrefs.
+  "List of functions to be run from `elisp--xref-find-definitions' to add additional xrefs.
 Called with one arg; the symbol whose definition is desired.
 Each function should return a list of xrefs, or nil; the first
 non-nil result supercedes the xrefs produced by
-‘elisp--xref-find-definitions’.")
+`elisp--xref-find-definitions'.")
+
+(cl-defmethod xref-backend-definitions ((_backend (eql elisp)) identifier)
+  (require 'find-func)
+  ;; FIXME: use information in source near point to filter results:
+  ;; (dvc-log-edit ...) - exclude 'feature
+  ;; (require 'dvc-log-edit) - only 'feature
+  ;; Semantic may provide additional information
+  ;;
+  (let ((sym (intern-soft identifier)))
+    (when sym
+      (elisp--xref-find-definitions sym))))
 
-;; FIXME: name should be singular; match xref-find-definition
 (defun elisp--xref-find-definitions (symbol)
   ;; The file name is not known when `symbol' is defined via interactive eval.
-  (let (xrefs temp)
+  (let (xrefs)
 
     (let ((temp elisp-xref-find-def-functions))
       (while (and (null xrefs)
@@ -652,6 +642,7 @@ non-nil result supercedes the xrefs produced by
       ;; alphabetical by result type symbol
 
       ;; FIXME: advised function; list of advice functions
+      ;; FIXME: aliased variable
 
       ;; Coding system symbols do not appear in ‘load-history’,
       ;; so we can’t get a location for them.
@@ -720,10 +711,15 @@ non-nil result supercedes the xrefs produced by
               (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 (cons symbol 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 specializers   ;; default method has null specializers
+                             (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))))
@@ -796,16 +792,9 @@ non-nil result supercedes the xrefs produced by
 
     xrefs))
 
-(declare-function project-search-path "project")
-(declare-function project-current "project")
-
-(defun elisp--xref-find-references (symbol)
-  (cl-mapcan
-   (lambda (dir)
-     (xref-collect-references symbol dir))
-   (project-search-path (project-current))))
+(declare-function project-external-roots "project")
 
-(defun elisp--xref-find-apropos (regexp)
+(cl-defmethod xref-backend-apropos ((_backend (eql elisp)) regexp)
   (apply #'nconc
          (let (lst)
            (dolist (sym (apropos-internal regexp))
@@ -822,7 +811,7 @@ non-nil result supercedes the xrefs produced by
                          (facep sym)))
                    'strict))
 
-(defun elisp--xref-identifier-completion-table ()
+(cl-defmethod xref-backend-identifier-completion-table ((_backend (eql elisp)))
   elisp--xref-identifier-completion-table)
 
 (cl-defstruct (xref-elisp-location
@@ -834,15 +823,17 @@ non-nil result supercedes the xrefs produced by
   (pcase-let (((cl-struct xref-elisp-location symbol type file) l))
     (let ((buffer-point (find-function-search-for-symbol symbol type file)))
       (with-current-buffer (car buffer-point)
-        (goto-char (or (cdr buffer-point) (point-min)))
-        (point-marker)))))
+        (save-excursion
+          (goto-char (or (cdr buffer-point) (point-min)))
+          (point-marker))))))
 
 (cl-defmethod xref-location-group ((l xref-elisp-location))
   (xref-elisp-location-file l))
 
-(defun elisp-search-path ()
-  (defvar package-user-dir)
-  (cons package-user-dir load-path))
+(defun elisp-load-path-roots ()
+  (if (boundp 'package-user-dir)
+      (cons package-user-dir load-path)
+    load-path))
 
 ;;; Elisp Interaction mode
 
@@ -928,6 +919,7 @@ Semicolons start comments.
             (goto-char end)))))))
 
 (defun elisp-byte-code-syntax-propertize (start end)
+  (goto-char start)
   (elisp--byte-code-comment end (point))
   (funcall
    (syntax-propertize-rules
@@ -1060,6 +1052,17 @@ If CHAR is not a character, return nil."
              ((or (eq (following-char) ?\')
                   (eq (preceding-char) ?\'))
               (setq left-quote ?\`)))
+
+        ;; When after a named character literal, skip over the entire
+        ;; literal, not only its last word.
+        (when (= (preceding-char) ?})
+          (let ((begin (save-excursion
+                         (backward-char)
+                         (skip-syntax-backward "w-")
+                         (backward-char 3)
+                         (when (looking-at-p "\\\\N{") (point)))))
+            (when begin (goto-char begin))))
+
        (forward-sexp -1)
        ;; If we were after `?\e' (or similar case),
        ;; use the whole thing, not just the `e'.
@@ -1113,7 +1116,6 @@ character)."
      (eval (eval-sexp-add-defvars (elisp--preceding-sexp)) lexical-binding)
      eval-last-sexp-arg-internal)))
 
-
 (defun elisp--eval-last-sexp-print-value (value &optional eval-last-sexp-arg-internal)
   (let ((unabbreviated (let ((print-length nil) (print-level nil))
                         (prin1-to-string value)))
@@ -1240,7 +1242,7 @@ If the current defun is actually a call to `defvar',
 then reset the variable using the initial value expression
 even if the variable already has some other value.
 \(Normally `defvar' does not change the variable's value
-if it already has a value.\)
+if it already has a value.)
 
 Return the result of evaluation."
   ;; FIXME: the print-length/level bindings should only be applied while
@@ -1322,7 +1324,7 @@ which see."
   0 - contains the last symbol read from the buffer.
   1 - contains the string last displayed in the echo area for variables,
       or argument string for functions.
-  2 - 'function if function args, 'variable if variable documentation.")
+  2 - `function' if function args, `variable' if variable documentation.")
 
 (defun elisp-eldoc-documentation-function ()
   "`eldoc-documentation-function' (which see) for Emacs Lisp."
@@ -1564,7 +1566,8 @@ In the absence of INDEX, just call `eldoc-docstring-format-sym-doc'."
 ARGLIST is either a string, or a list of strings or symbols."
   (let ((str (cond ((stringp arglist) arglist)
                    ((not (listp arglist)) nil)
-                   (t (help--make-usage-docstring 'toto arglist)))))
+                   (t (substitute-command-keys
+                       (help--make-usage-docstring 'toto arglist))))))
     (if (and str (string-match "\\`([^ )]+ ?" str))
         (replace-match "(" t t str)
       str)))