diff options
Diffstat (limited to 'lisp/emacs-lisp')
-rw-r--r-- | lisp/emacs-lisp/lisp-mode.el | 64 |
1 files changed, 46 insertions, 18 deletions
diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el index c906ee6e31d..2e7f019aa9e 100644 --- a/lisp/emacs-lisp/lisp-mode.el +++ b/lisp/emacs-lisp/lisp-mode.el @@ -728,30 +728,58 @@ font-lock keywords will not be case sensitive." len)))) (defun lisp-current-defun-name () - "Return the name of the defun at point, or nil." + "Return the name of the defun at point. +If there is no defun at point, return the first symbol from the +top-level form. If there is no top-level form, return nil. + +(\"defun\" here means \"form that defines something\", and is +decided heuristically.)" (save-excursion - (let ((location (point))) + (let ((location (point)) + name) ;; If we are now precisely at the beginning of a defun, make sure ;; beginning-of-defun finds that one rather than the previous one. - (or (eobp) (forward-char 1)) + (unless (eobp) + (forward-char 1)) (beginning-of-defun) ;; Make sure we are really inside the defun found, not after it. - (when (and (looking-at "\\s(") - (progn (end-of-defun) - (< location (point))) - (progn (forward-sexp -1) - (>= location (point)))) - (if (looking-at "\\s(") - (forward-char 1)) - ;; Skip the defining construct name, typically "defun" or + (when (and (looking-at "(") + (progn + (end-of-defun) + (< location (point))) + (progn + (forward-sexp -1) + (>= location (point)))) + (when (looking-at "(") + (forward-char 1)) + ;; Read the defining construct name, typically "defun" or ;; "defvar". - (forward-sexp 1) - ;; The second element is usually a symbol being defined. If it - ;; is not, use the first symbol in it. - (skip-chars-forward " \t\n'(") - (buffer-substring-no-properties (point) - (progn (forward-sexp 1) - (point))))))) + (let ((symbol (ignore-errors (read (current-buffer))))) + (when (and symbol (not (symbolp symbol))) + (setq symbol nil)) + ;; If there's an edebug spec, use that to determine what the + ;; name is. + (when symbol + (let ((spec (get symbol 'edebug-form-spec))) + (save-excursion + (when (and (eq (car spec) '&define) + (memq 'name spec)) + (pop spec) + (while (and spec (not name)) + (let ((candidate (ignore-errors (read (current-buffer))))) + (when (eq (pop spec) 'name) + (setq name candidate + spec nil)))))))) + ;; We didn't have an edebug spec (or couldn't find the + ;; name). If the symbol starts with \"def\", then it's + ;; likely that the next symbol is the name. + (when (and (not name) + (string-match-p "\\`def" (symbol-name symbol))) + (when-let ((candidate (ignore-errors (read (current-buffer))))) + (when (symbolp candidate) + (setq name candidate)))) + (when-let ((result (or name symbol))) + (symbol-name result))))))) (defvar-keymap lisp-mode-shared-map :doc "Keymap for commands shared by all sorts of Lisp modes." |