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)))))