]> git.eshelyaron.com Git - emacs.git/commitdiff
In end-of-defun, terminate early if no further defun exists
authorYuan Fu <casouri@gmail.com>
Thu, 10 Nov 2022 23:00:29 +0000 (15:00 -0800)
committerYuan Fu <casouri@gmail.com>
Thu, 10 Nov 2022 23:00:29 +0000 (15:00 -0800)
Before this change, end-of-defun calls end-of-defun-function even if
point is not necessarily at the beginning of a defun (contrary to what
end-of-defun-function's docstring claims).  Now it terminates early
and doesn't call end-of-defun-function.

* lisp/emacs-lisp/lisp.el (beginning-of-defun-raw): Update docstring
clarifying the return value.
(end-of-defun): Terminate early if beginning-of-defun-raw returns nil.

lisp/emacs-lisp/lisp.el

index acae1a0b0a923ea7a19654f55d9dc3f36ddecdd4..c8d05a084bbf20a3db0740c098938f28ba21f868 100644 (file)
@@ -375,7 +375,10 @@ does not move to the beginning of the line when `defun-prompt-regexp'
 is non-nil.
 
 If variable `beginning-of-defun-function' is non-nil, its value
-is called as a function to find the defun's beginning."
+is called as a function to find the defun's beginning.
+
+Return non-nil if this function successfully found the beginning
+of a defun, nil if it failed to find one."
   (interactive "^p")   ; change this to "P", maybe, if we ever come to pass ARG
                       ; to beginning-of-defun-function.
   (unless arg (setq arg 1))
@@ -543,6 +546,7 @@ report errors as appropriate for this kind of usage."
         (push-mark))
     (if (or (null arg) (= arg 0)) (setq arg 1))
     (let ((pos (point))
+          (success nil)
           (beg (progn (when end-of-defun-moves-to-eol
                         (end-of-line 1))
                       (beginning-of-defun-raw 1) (point)))
@@ -567,9 +571,12 @@ report errors as appropriate for this kind of usage."
             (setq arg (1- arg))
           ;; We started from after the end of the previous function.
           (goto-char pos))
+        ;; At this point, point either didn't move (because we started
+        ;; in between two defun's), or is at the end of a defun
+        ;; (because we started in the middle of a defun).
         (unless (zerop arg)
-          (beginning-of-defun-raw (- arg))
-          (funcall end-of-defun-function)))
+          (when (setq success (beginning-of-defun-raw (- arg)))
+            (funcall end-of-defun-function))))
        ((< arg 0)
         ;; Moving backward.
         (if (< (point) pos)
@@ -579,16 +586,18 @@ report errors as appropriate for this kind of usage."
           ;; We started from inside a function.
           (goto-char beg))
         (unless (zerop arg)
-          (beginning-of-defun-raw (- arg))
-         (setq beg (point))
-          (funcall end-of-defun-function))))
+          (when (setq success (beginning-of-defun-raw (- arg)))
+            (setq beg (point))
+            (funcall end-of-defun-function)))))
       (funcall skip)
-      (while (and (< arg 0) (>= (point) pos))
+      (while (and (< arg 0) (>= (point) pos) success)
         ;; We intended to move backward, but this ended up not doing so:
         ;; Try harder!
         (goto-char beg)
-        (beginning-of-defun-raw (- arg))
-        (if (>= (point) beg)
+        (setq success (beginning-of-defun-raw (- arg)))
+        ;; If we successfully moved pass point, or there is no further
+        ;; defun beginnings anymore, stop.
+        (if (or (>= (point) beg) (not success))
            (setq arg 0)
          (setq beg (point))
           (funcall end-of-defun-function)