Function: mark-defun

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

Signature

(mark-defun &optional ARG INTERACTIVE)

Documentation

Put mark at end of this defun, point at beginning.

The defun marked is the one that contains point or follows point. With positive ARG, mark this and that many next defuns; with negative ARG, change the direction of marking.

If the mark is active, it marks the next or previous defun(s) after the one(s) already marked.

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

View in manual

Probably introduced at or before Emacs version 22.1.

Key Bindings

Aliases

tcl-mark-defun (obsolete since 28.1)

Source Code

;; Defined in /usr/src/emacs/lisp/emacs-lisp/lisp.el.gz
(defun mark-defun (&optional arg interactive)
  "Put mark at end of this defun, point at beginning.
The defun marked is the one that contains point or follows point.
With positive ARG, mark this and that many next defuns; with negative
ARG, change the direction of marking.

If the mark is active, it marks the next or previous defun(s) after
the one(s) already marked.

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
          (mark-defun arg nil)
        (scan-error (user-error (cadr e))))
    (setq arg (or arg 1))
    ;; There is no `mark-defun-back' function - see
    ;; https://lists.gnu.org/r/bug-gnu-emacs/2016-11/msg00079.html
    ;; for explanation
    (when (eq last-command 'mark-defun-back)
      (setq arg (- arg)))
    (when (< arg 0)
      (setq this-command 'mark-defun-back))
    (cond ((use-region-p)
           (if (>= arg 0)
               (set-mark
                (save-excursion
                  (goto-char (mark))
                  ;; change the dotimes below to (end-of-defun arg)
                  ;; once bug #24427 is fixed
                  (dotimes (_ignore arg)
                    (end-of-defun))
                  (point)))
             (beginning-of-defun-comments (- arg))))
          (t
           (let ((opoint (point))
                 beg end)
             (push-mark opoint)
             ;; Try first in this order for the sake of languages with nested
             ;; functions where several can end at the same place as with the
             ;; offside rule, e.g. Python.
             (beginning-of-defun-comments)
             (setq beg (point))
             (end-of-defun)
             (setq end (point))
             (when (or (and (<= (point) opoint)
                            (> arg 0))
                       (= beg (point-min))) ; we were before the first defun!
               ;; beginning-of-defun moved back one defun so we got the wrong
               ;; one.  If ARG < 0, however, we actually want to go back.
               (goto-char opoint)
               (end-of-defun)
               (setq end (point))
               (beginning-of-defun-comments)
               (setq beg (point)))
             (goto-char beg)
             (cond ((> arg 0)
                    ;; change the dotimes below to (end-of-defun arg)
                    ;; once bug #24427 is fixed
                    (dotimes (_ignore arg)
                      (end-of-defun))
                    (setq end (point))
                    (push-mark end nil t)
                    (goto-char beg))
                   (t
                    (goto-char beg)
                    (unless (= arg -1)
                      ;; beginning-of-defun behaves strange with zero arg - see
                      ;; lists.gnu.org/r/bug-gnu-emacs/2017-02/msg00196.html
                      (beginning-of-defun (1- (- arg))))
                    (push-mark end nil t))))))
    (skip-chars-backward "[:space:]\n")
    (unless (bobp)
      (forward-line 1))))