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))
(success nil)
(beg (progn (when end-of-defun-moves-to-eol
(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))
;; 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)
(when (setq success (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)
(when (setq success (beginning-of-defun-raw (- arg)))
(setq beg (point))
(funcall end-of-defun-function)))))
(funcall skip)
(while (and (< arg 0) (>= (point) pos) success)
;; We intended to move backward, but this ended up not doing so:
;; Try harder!
(goto-char 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)
(funcall skip))))))