Function: end-of-defun

end-of-defun is an interactive and byte-compiled function defined in lisp.el.gz.

Signature

(end-of-defun &optional ARG INTERACTIVE)

Documentation

Move forward to next end of defun.

With argument, do it that many times. Negative argument -N means move back to Nth preceding end of defun.

An end of a defun occurs right after the close-parenthesis that matches the open-parenthesis that starts a defun; see function beginning-of-defun.

If variable end-of-defun-function is non-nil, its value is called as a function to find the defun's end.

If INTERACTIVE is non-nil, as it is interactively, report errors as appropriate for this kind of usage.

Probably introduced at or before Emacs version 22.1.

Key Bindings

Aliases

tcl-end-of-defun (obsolete since 28.1)

Source Code

;; Defined in /usr/src/emacs/lisp/emacs-lisp/lisp.el.gz
(defun end-of-defun (&optional arg interactive)
  "Move forward to next end of defun.
With argument, do it that many times.
Negative argument -N means move back to Nth preceding end of defun.

An end of a defun occurs right after the close-parenthesis that
matches the open-parenthesis that starts a defun; see function
`beginning-of-defun'.

If variable `end-of-defun-function' is non-nil, its value
is called as a function to find the defun's end.

If INTERACTIVE is non-nil, as it is interactively,
report errors as appropriate for this kind of usage."
  (interactive "^p\nd")
  (if interactive
      (condition-case e
          (end-of-defun arg nil)
        (scan-error (user-error (cadr e))))
    (or (not (eq this-command 'end-of-defun))
        (eq last-command 'end-of-defun)
        (and transient-mark-mode mark-active)
        (push-mark))
    (if (or (null arg) (= arg 0)) (setq arg 1))
    (let ((pos (point))
          (beg (progn (end-of-line 1) (beginning-of-defun-raw 1) (point)))
	  (skip (lambda ()
		  ;; When comparing point against pos, we want to consider that
		  ;; if point was right after the end of the function, it's
		  ;; still considered as "in that function".
		  ;; E.g. `eval-defun' from right after the last close-paren.
		  (unless (bolp)
		    (skip-chars-forward " \t")
		    (if (looking-at "\\s<\\|\n")
                        (forward-line 1))))))
      (funcall end-of-defun-function)
      (when (<= arg 1)
        (funcall skip))
      (cond
       ((> arg 0)
        ;; Moving forward.
        (if (> (point) pos)
            ;; We already moved forward by one because we started from
            ;; within a function.
            (setq arg (1- arg))
          ;; We started from after the end of the previous function.
          (goto-char pos))
        (unless (zerop arg)
          (beginning-of-defun-raw (- arg))
          (funcall end-of-defun-function)))
       ((< arg 0)
        ;; Moving backward.
        (if (< (point) pos)
            ;; We already moved backward because we started from between
            ;; two functions.
            (setq arg (1+ arg))
          ;; 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))))
      (funcall skip)
      (while (and (< arg 0) (>= (point) pos))
        ;; 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 arg 0)
	  (setq beg (point))
          (funcall end-of-defun-function)
	  (funcall skip))))))