Function: evil-define-operator

evil-define-operator is a macro defined in evil-macros.el.

Signature

(evil-define-operator OPERATOR (BEG END ARGS...) DOC [[KEY VALUE]...] BODY...)

Documentation

Define an operator command OPERATOR.

The operator acts on the range of characters BEG through END. BODY must execute the operator by potentially manipulating the buffer contents, or otherwise causing side effects to happen.

Optional keyword arguments are:
- :type - force the input range to be of a given type (inclusive,
  line, block, and exclusive, or a self-defined motion type).
- :motion - use a predetermined motion instead of waiting for one
  from the keyboard. This does not affect the behavior in visual
  state, where selection boundaries are always used.
- :repeat - if non-nil (default), then . (evil-repeat) will repeat the
  operator.
- :move-point - if non-nil (default), the cursor will be moved to
  the beginning of the range before the body executes
- :keep-visual - if non-nil, the selection is not disabled when the
  operator is executed in visual state. By default, visual state is
  exited automatically.
- :restore-point - if non-nil, point is restored when the
  operator is executed from ex.

Source Code

;; Defined in ~/.emacs.d/elpa/evil-20251108.138/evil-macros.el
(defmacro evil-define-operator (operator args &rest body)
  "Define an operator command OPERATOR.
The operator acts on the range of characters BEG through
END. BODY must execute the operator by potentially manipulating
the buffer contents, or otherwise causing side effects to happen.

Optional keyword arguments are:
- `:type' - force the input range to be of a given type (`inclusive',
  `line', `block', and `exclusive', or a self-defined motion type).
- `:motion' - use a predetermined motion instead of waiting for one
  from the keyboard.  This does not affect the behavior in visual
  state, where selection boundaries are always used.
- `:repeat' - if non-nil (default), then \
  \\<evil-normal-state-map>\\[evil-repeat] will repeat the
  operator.
- `:move-point' - if non-nil (default), the cursor will be moved to
  the beginning of the range before the body executes
- `:keep-visual' - if non-nil, the selection is not disabled when the
  operator is executed in visual state.  By default, visual state is
  exited automatically.
- `:restore-point' - if non-nil, point is restored when the
  operator is executed from ex.

\(fn OPERATOR (BEG END ARGS...) DOC [[KEY VALUE]...] BODY...)"
  (declare (indent defun)
           (doc-string 3)
           (debug (&define name lambda-list
                           [&optional stringp]
                           [&rest keywordp sexp]
                           [&optional ("interactive" [&rest form])]
                           def-body)))
  (let* ((args (delq '&optional args))
         (interactive (if (> (length args) 2) '("<R>") '("<r>")))
         (args (if (> (length args) 2)
                   `(,(nth 0 args) ,(nth 1 args)
                     &optional ,@(nthcdr 2 args))
                 args))
         (end-marker (make-symbol "end-marker"))
         arg doc key keys visual)
    ;; collect docstring
    (when (and (> (length body) 1)
               (or (eq (car-safe (car-safe body)) 'format)
                   (stringp (car-safe body))))
      (setq doc (pop body)))
    ;; collect keywords
    (setq keys (plist-put keys :move-point t))
    (while (keywordp (car-safe body))
      (setq key (pop body)
            arg (pop body))
      (cond
       ((eq key :keep-visual)
        (setq visual arg))
       (t
        (setq keys (plist-put keys key arg)))))
    ;; collect `interactive' specification
    (when (eq (car-safe (car-safe body)) 'interactive)
      (setq interactive (cdr-safe (pop body))))
    ;; transform extended interactive specs
    (setq interactive (apply #'evil-interactive-form interactive))
    (setq keys (evil-concat-plists keys (cdr-safe interactive))
          interactive (car-safe interactive))
    ;; macro expansion
    `(evil-define-command ,operator ,args
       ,@(when doc `(,doc))
       ,@keys
       :keep-visual t
       :suppress-operator t
       (interactive
        (let* ((props (evil-command-properties ',operator))
               (evil-operator-range-motion
                (let ((p (plist-member props :motion)))
                  ;; :motion nil is equivalent to :motion undefined
                  (when p (or (cadr p) #'undefined))))
               (evil-operator-range-type (plist-get props :type))
               evil-operator-range-beginning evil-operator-range-end
               evil-inhibit-operator)
          (setq evil-inhibit-operator-value nil
                evil-this-operator this-command
                evil-operator-start-col (current-column))
          (prog1 ,interactive
            (setq evil-inhibit-operator-value evil-inhibit-operator)
            (if ,visual
                (when (evil-visual-state-p) (evil-visual-expand-region))
              (setq deactivate-mark t))
            (cond
             ((evil-visual-state-p)
              (evil-visual-rotate 'upper-left))
             ((plist-get props :move-point)
              (when evil-operator-range-beginning
                (goto-char evil-operator-range-beginning)))))))
       (unwind-protect
           (let ((evil-inhibit-operator evil-inhibit-operator-value)
                 (,end-marker (make-marker)))
             (set-marker ,end-marker ,(cadr args))
             (unless (and evil-inhibit-operator
                          (called-interactively-p 'any))
               ,@body)
             (evil-set-marker ?\[ (or ,(car args) (point-max)))
             (evil-set-marker ?\] (max (or ,(car args) (point-max))
                                       (1- (or (marker-position ,end-marker) (point-max)))))
             (set-marker ,end-marker nil))
         (setq evil-inhibit-operator-value nil)))))