diff options
| author | Dmitry Gutov | 2014-12-27 16:06:37 +0200 |
|---|---|---|
| committer | Dmitry Gutov | 2014-12-27 16:07:31 +0200 |
| commit | 6d14e0d361cfb3589874fe1b559e30b4fd3eb284 (patch) | |
| tree | d358b0ef77e8e814113d274df1596c2489634d70 | |
| parent | 09d2e8477aa64308447395a0f01cfe5414619811 (diff) | |
| download | emacs-6d14e0d361cfb3589874fe1b559e30b4fd3eb284.tar.gz emacs-6d14e0d361cfb3589874fe1b559e30b4fd3eb284.zip | |
elisp-xref-find: Don't create buffers eagerly
* lisp/emacs-lisp/find-func.el (find-function-library): New function,
extracted from `find-function-noselect'.
* lisp/progmodes/elisp-mode.el (elisp--identifier-location): Fold back
into `elisp--company-location'.
(elisp--identifier-completion-table): Rename to
`elisp--identifier-completion-table', and do not include just any
symbols with a property list.
(elisp-completion-at-point): Revert the 2014-12-25 change.
(elisp--xref-identifier-file): New function.
(elisp--xref-find-definitions): Use it.
* lisp/progmodes/xref.el (xref-elisp-location): New class.
(xref-make-elisp-location): New function.
(xref-location-marker): New implementation.
| -rw-r--r-- | lisp/ChangeLog | 20 | ||||
| -rw-r--r-- | lisp/emacs-lisp/find-func.el | 59 | ||||
| -rw-r--r-- | lisp/progmodes/elisp-mode.el | 90 | ||||
| -rw-r--r-- | lisp/progmodes/xref.el | 25 |
4 files changed, 129 insertions, 65 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 5a42e506d35..5829ec2fae5 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,23 @@ | |||
| 1 | 2014-12-27 Dmitry Gutov <dgutov@yandex.ru> | ||
| 2 | |||
| 3 | elisp-xref-find: Don't create buffers eagerly. | ||
| 4 | |||
| 5 | * progmodes/elisp-mode.el (elisp--identifier-location): Fold back | ||
| 6 | into `elisp--company-location'. | ||
| 7 | (elisp--identifier-completion-table): Rename to | ||
| 8 | `elisp--identifier-completion-table', and do not include just any | ||
| 9 | symbols with a property list. | ||
| 10 | (elisp-completion-at-point): Revert the 2014-12-25 change. | ||
| 11 | (elisp--xref-identifier-file): New function. | ||
| 12 | (elisp--xref-find-definitions): Use it. | ||
| 13 | |||
| 14 | * emacs-lisp/find-func.el (find-function-library): New function, | ||
| 15 | extracted from `find-function-noselect'. | ||
| 16 | |||
| 17 | * progmodes/xref.el (xref-elisp-location): New class. | ||
| 18 | (xref-make-elisp-location): New function. | ||
| 19 | (xref-location-marker): New implementation. | ||
| 20 | |||
| 1 | 2014-12-27 Juri Linkov <juri@linkov.net> | 21 | 2014-12-27 Juri Linkov <juri@linkov.net> |
| 2 | 22 | ||
| 3 | * minibuffer.el (minibuffer-completion-help): | 23 | * minibuffer.el (minibuffer-completion-help): |
diff --git a/lisp/emacs-lisp/find-func.el b/lisp/emacs-lisp/find-func.el index c372117b104..e1586a96716 100644 --- a/lisp/emacs-lisp/find-func.el +++ b/lisp/emacs-lisp/find-func.el | |||
| @@ -311,6 +311,39 @@ The search is done in the source for library LIBRARY." | |||
| 311 | (cons (current-buffer) (point))) | 311 | (cons (current-buffer) (point))) |
| 312 | (cons (current-buffer) nil)))))))) | 312 | (cons (current-buffer) nil)))))))) |
| 313 | 313 | ||
| 314 | (defun find-function-library (function &optional lisp-only verbose) | ||
| 315 | "Return the library FUNCTION is defined in. | ||
| 316 | |||
| 317 | If FUNCTION is a built-in function and LISP-ONLY is non-nil, | ||
| 318 | signal an error. | ||
| 319 | |||
| 320 | If VERBOSE is non-nil, and FUNCTION is an alias, display a | ||
| 321 | message about the whole chain of aliases." | ||
| 322 | (let ((def (symbol-function (find-function-advised-original function))) | ||
| 323 | aliases) | ||
| 324 | ;; FIXME for completeness, it might be nice to print something like: | ||
| 325 | ;; foo (which is advised), which is an alias for bar (which is advised). | ||
| 326 | (while (symbolp def) | ||
| 327 | (or (eq def function) | ||
| 328 | (not verbose) | ||
| 329 | (if aliases | ||
| 330 | (setq aliases (concat aliases | ||
| 331 | (format ", which is an alias for `%s'" | ||
| 332 | (symbol-name def)))) | ||
| 333 | (setq aliases (format "`%s' is an alias for `%s'" | ||
| 334 | function (symbol-name def))))) | ||
| 335 | (setq function (symbol-function (find-function-advised-original function)) | ||
| 336 | def (symbol-function (find-function-advised-original function)))) | ||
| 337 | (if aliases | ||
| 338 | (message "%s" aliases)) | ||
| 339 | (cond | ||
| 340 | ((autoloadp def) (nth 1 def)) | ||
| 341 | ((subrp def) | ||
| 342 | (if lisp-only | ||
| 343 | (error "%s is a built-in function" function)) | ||
| 344 | (help-C-file-name def 'subr)) | ||
| 345 | ((symbol-file function 'defun))))) | ||
| 346 | |||
| 314 | ;;;###autoload | 347 | ;;;###autoload |
| 315 | (defun find-function-noselect (function &optional lisp-only) | 348 | (defun find-function-noselect (function &optional lisp-only) |
| 316 | "Return a pair (BUFFER . POINT) pointing to the definition of FUNCTION. | 349 | "Return a pair (BUFFER . POINT) pointing to the definition of FUNCTION. |
| @@ -329,30 +362,8 @@ searched for in `find-function-source-path' if non-nil, otherwise | |||
| 329 | in `load-path'." | 362 | in `load-path'." |
| 330 | (if (not function) | 363 | (if (not function) |
| 331 | (error "You didn't specify a function")) | 364 | (error "You didn't specify a function")) |
| 332 | (let ((def (symbol-function (find-function-advised-original function))) | 365 | (let ((library (find-function-library function lisp-only t))) |
| 333 | aliases) | 366 | (find-function-search-for-symbol function nil library))) |
| 334 | ;; FIXME for completeness, it might be nice to print something like: | ||
| 335 | ;; foo (which is advised), which is an alias for bar (which is advised). | ||
| 336 | (while (symbolp def) | ||
| 337 | (or (eq def function) | ||
| 338 | (if aliases | ||
| 339 | (setq aliases (concat aliases | ||
| 340 | (format ", which is an alias for `%s'" | ||
| 341 | (symbol-name def)))) | ||
| 342 | (setq aliases (format "`%s' is an alias for `%s'" | ||
| 343 | function (symbol-name def))))) | ||
| 344 | (setq function (symbol-function (find-function-advised-original function)) | ||
| 345 | def (symbol-function (find-function-advised-original function)))) | ||
| 346 | (if aliases | ||
| 347 | (message "%s" aliases)) | ||
| 348 | (let ((library | ||
| 349 | (cond ((autoloadp def) (nth 1 def)) | ||
| 350 | ((subrp def) | ||
| 351 | (if lisp-only | ||
| 352 | (error "%s is a built-in function" function)) | ||
| 353 | (help-C-file-name def 'subr)) | ||
| 354 | ((symbol-file function 'defun))))) | ||
| 355 | (find-function-search-for-symbol function nil library)))) | ||
| 356 | 367 | ||
| 357 | (defun find-function-read (&optional type) | 368 | (defun find-function-read (&optional type) |
| 358 | "Read and return an interned symbol, defaulting to the one near point. | 369 | "Read and return an interned symbol, defaulting to the one near point. |
diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index ef619f0899a..347560a484e 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el | |||
| @@ -418,40 +418,19 @@ It can be quoted, or be inside a quoted form." | |||
| 418 | (match-string 0 doc)))) | 418 | (match-string 0 doc)))) |
| 419 | 419 | ||
| 420 | (declare-function find-library-name "find-func" (library)) | 420 | (declare-function find-library-name "find-func" (library)) |
| 421 | 421 | (declare-function find-function-library "find-func" (function &optional l-o v)) | |
| 422 | (defvar elisp--identifier-types '(defun defvar feature defface)) | ||
| 423 | |||
| 424 | (defun elisp--identifier-location (type sym) | ||
| 425 | (pcase (cons type sym) | ||
| 426 | (`(defun . ,(pred fboundp)) | ||
| 427 | (find-definition-noselect sym nil)) | ||
| 428 | (`(defvar . ,(pred boundp)) | ||
| 429 | (find-definition-noselect sym 'defvar)) | ||
| 430 | (`(defface . ,(pred facep)) | ||
| 431 | (find-definition-noselect sym 'defface)) | ||
| 432 | (`(feature . ,(pred featurep)) | ||
| 433 | (require 'find-func) | ||
| 434 | (cons (find-file-noselect (find-library-name | ||
| 435 | (symbol-name sym))) | ||
| 436 | 1)))) | ||
| 437 | 422 | ||
| 438 | (defun elisp--company-location (str) | 423 | (defun elisp--company-location (str) |
| 439 | (catch 'res | 424 | (let ((sym (intern-soft str))) |
| 440 | (let ((sym (intern-soft str))) | 425 | (cond |
| 441 | (when sym | 426 | ((fboundp sym) (find-definition-noselect sym nil)) |
| 442 | (dolist (type elisp--identifier-types) | 427 | ((boundp sym) (find-definition-noselect sym 'defvar)) |
| 443 | (let ((loc (elisp--identifier-location type sym))) | 428 | ((featurep sym) |
| 444 | (and loc (throw 'res loc)))))))) | 429 | (require 'find-func) |
| 445 | 430 | (cons (find-file-noselect (find-library-name | |
| 446 | (defvar elisp--identifier-completion-table | 431 | (symbol-name sym))) |
| 447 | (apply-partially #'completion-table-with-predicate | 432 | 0)) |
| 448 | obarray | 433 | ((facep sym) (find-definition-noselect sym 'defface))))) |
| 449 | (lambda (sym) | ||
| 450 | (or (boundp sym) | ||
| 451 | (fboundp sym) | ||
| 452 | (featurep sym) | ||
| 453 | (symbol-plist sym))) | ||
| 454 | 'strict)) | ||
| 455 | 434 | ||
| 456 | (defun elisp-completion-at-point () | 435 | (defun elisp-completion-at-point () |
| 457 | "Function used for `completion-at-point-functions' in `emacs-lisp-mode'." | 436 | "Function used for `completion-at-point-functions' in `emacs-lisp-mode'." |
| @@ -493,8 +472,13 @@ It can be quoted, or be inside a quoted form." | |||
| 493 | :company-docsig #'elisp--company-doc-string | 472 | :company-docsig #'elisp--company-doc-string |
| 494 | :company-location #'elisp--company-location)) | 473 | :company-location #'elisp--company-location)) |
| 495 | ((elisp--form-quoted-p beg) | 474 | ((elisp--form-quoted-p beg) |
| 496 | ;; Don't include all symbols (bug#16646). | 475 | (list nil obarray |
| 497 | (list nil elisp--identifier-completion-table | 476 | ;; Don't include all symbols (bug#16646). |
| 477 | :predicate (lambda (sym) | ||
| 478 | (or (boundp sym) | ||
| 479 | (fboundp sym) | ||
| 480 | (featurep sym) | ||
| 481 | (symbol-plist sym))) | ||
| 498 | :annotation-function | 482 | :annotation-function |
| 499 | (lambda (str) (if (fboundp (intern-soft str)) " <f>")) | 483 | (lambda (str) (if (fboundp (intern-soft str)) " <f>")) |
| 500 | :company-doc-buffer #'elisp--company-doc-buffer | 484 | :company-doc-buffer #'elisp--company-doc-buffer |
| @@ -572,11 +556,12 @@ It can be quoted, or be inside a quoted form." | |||
| 572 | 556 | ||
| 573 | ;;; Xref backend | 557 | ;;; Xref backend |
| 574 | 558 | ||
| 575 | (declare-function xref-make-buffer-location "xref" (buffer position)) | 559 | (declare-function xref-make-elisp-location "xref" (symbol type file)) |
| 576 | (declare-function xref-make-bogus-location "xref" (message)) | 560 | (declare-function xref-make-bogus-location "xref" (message)) |
| 577 | (declare-function xref-make "xref" (description location)) | 561 | (declare-function xref-make "xref" (description location)) |
| 578 | 562 | ||
| 579 | (defun elisp-xref-find (action id) | 563 | (defun elisp-xref-find (action id) |
| 564 | (require 'find-func) | ||
| 580 | (pcase action | 565 | (pcase action |
| 581 | (`definitions | 566 | (`definitions |
| 582 | (let ((sym (intern-soft id))) | 567 | (let ((sym (intern-soft id))) |
| @@ -585,16 +570,29 @@ It can be quoted, or be inside a quoted form." | |||
| 585 | (`apropos | 570 | (`apropos |
| 586 | (elisp--xref-find-apropos id)))) | 571 | (elisp--xref-find-apropos id)))) |
| 587 | 572 | ||
| 573 | (defun elisp--xref-identifier-file (type sym) | ||
| 574 | (pcase type | ||
| 575 | (`defun (when (fboundp sym) | ||
| 576 | (find-function-library sym))) | ||
| 577 | (`defvar (when (boundp sym) | ||
| 578 | (or (symbol-file sym 'defvar) | ||
| 579 | (help-C-file-name sym 'var)))) | ||
| 580 | (`feature (when (featurep sym) | ||
| 581 | (find-library-name (symbol-name sym)))) | ||
| 582 | (`defface (when (facep sym) | ||
| 583 | (symbol-file sym 'defface))))) | ||
| 584 | |||
| 588 | (defun elisp--xref-find-definitions (symbol) | 585 | (defun elisp--xref-find-definitions (symbol) |
| 589 | (save-excursion | 586 | (save-excursion |
| 590 | (let (lst) | 587 | (let (lst) |
| 591 | (dolist (type elisp--identifier-types) | 588 | (dolist (type '(feature defface defvar defun)) |
| 592 | (let ((loc | 589 | (let ((loc |
| 593 | (condition-case err | 590 | (condition-case err |
| 594 | (let ((buf-pos (elisp--identifier-location type symbol))) | 591 | (let ((file (elisp--xref-identifier-file type symbol))) |
| 595 | (when buf-pos | 592 | (when file |
| 596 | (xref-make-buffer-location (car buf-pos) | 593 | (when (string-match-p "\\.elc\\'" file) |
| 597 | (or (cdr buf-pos) 1)))) | 594 | (setq file (substring file 0 -1))) |
| 595 | (xref-make-elisp-location symbol type file))) | ||
| 598 | (error | 596 | (error |
| 599 | (xref-make-bogus-location (error-message-string err)))))) | 597 | (xref-make-bogus-location (error-message-string err)))))) |
| 600 | (when loc | 598 | (when loc |
| @@ -611,8 +609,18 @@ It can be quoted, or be inside a quoted form." | |||
| 611 | (push (elisp--xref-find-definitions sym) lst)) | 609 | (push (elisp--xref-find-definitions sym) lst)) |
| 612 | (nreverse lst)))) | 610 | (nreverse lst)))) |
| 613 | 611 | ||
| 612 | (defvar elisp--xref-identifier-completion-table | ||
| 613 | (apply-partially #'completion-table-with-predicate | ||
| 614 | obarray | ||
| 615 | (lambda (sym) | ||
| 616 | (or (boundp sym) | ||
| 617 | (fboundp sym) | ||
| 618 | (featurep sym) | ||
| 619 | (facep sym))) | ||
| 620 | 'strict)) | ||
| 621 | |||
| 614 | (defun elisp--xref-identifier-completion-table () | 622 | (defun elisp--xref-identifier-completion-table () |
| 615 | elisp--identifier-completion-table) | 623 | elisp--xref-identifier-completion-table) |
| 616 | 624 | ||
| 617 | ;;; Elisp Interaction mode | 625 | ;;; Elisp Interaction mode |
| 618 | 626 | ||
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index 21c0d6aa6a4..8221aebd871 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el | |||
| @@ -136,6 +136,31 @@ actual location is not known.") | |||
| 136 | 136 | ||
| 137 | (defmethod xref-location-group ((_ xref-bogus-location)) "(No location)") | 137 | (defmethod xref-location-group ((_ xref-bogus-location)) "(No location)") |
| 138 | 138 | ||
| 139 | ;; This should be in elisp-mode.el, but it's preloaded, and we can't | ||
| 140 | ;; preload defclass and defmethod (at least, not yet). | ||
| 141 | (defclass xref-elisp-location (xref-location) | ||
| 142 | ((symbol :type symbol :initarg :symbol) | ||
| 143 | (type :type symbol :initarg :type) | ||
| 144 | (file :type string :initarg :file | ||
| 145 | :reader xref-location-group)) | ||
| 146 | :documentation "Location of an Emacs Lisp symbol definition.") | ||
| 147 | |||
| 148 | (defun xref-make-elisp-location (symbol type file) | ||
| 149 | (make-instance 'xref-elisp-location :symbol symbol :type type :file file)) | ||
| 150 | |||
| 151 | (defmethod xref-location-marker ((l xref-elisp-location)) | ||
| 152 | (with-slots (symbol type file) l | ||
| 153 | (let ((buffer-point | ||
| 154 | (pcase type | ||
| 155 | (`defun (find-function-search-for-symbol symbol nil file)) | ||
| 156 | ((or `defvar `defface) | ||
| 157 | (find-function-search-for-symbol symbol type file)) | ||
| 158 | (`feature | ||
| 159 | (cons (find-file-noselect file) 1))))) | ||
| 160 | (with-current-buffer (car buffer-point) | ||
| 161 | (goto-char (or (cdr buffer-point) (point-min))) | ||
| 162 | (point-marker))))) | ||
| 163 | |||
| 139 | 164 | ||
| 140 | ;;; Cross-reference | 165 | ;;; Cross-reference |
| 141 | 166 | ||