Enter Beg End parameters automatically in Evil-Vis

2019-07-30 05:56发布

问题:

I see some functions like evil-change or evil-delete are take in the beginning and end of a visual region in evil-visual-state. I've looked at the source code in "evil-commands.el" of these functions but their 'beg' and 'end' parameters just seem to come out of nowhere. And some (such as the one below) aren't even interactive.

Why this is and how I can do the same thing in my own methods?

Below is just an example of one of the methods I looked at:

;; Defined in ~/.emacs.d/elpa/evil-20170712.2350/evil-commands.el
(evil-define-operator evil-invert-char (beg end type)
  "Invert case of character."
  :motion evil-forward-char
  (if (eq type 'block)
      (evil-apply-on-block #'evil-invert-case beg end nil)
    (evil-invert-case beg end)
    (when evil-this-motion
      (goto-char end)
      (when (and evil-cross-lines
                 evil-move-cursor-back
                 (not evil-move-beyond-eol)
                 (not (evil-visual-state-p))
                 (not (evil-operator-state-p))
                 (eolp) (not (eobp)) (not (bolp)))
        (forward-char)))))

回答1:

evil-invert-char is not defined using a regular defun, but using the macro evil-define-operator, which can be found in evil-macros.el. Using M-x describe-function RET evil-define-operator RET:

evil-define-operator is a Lisp macro in ‘evil-macros.el’.

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

Define an operator command OPERATOR.

You can use the excellent macrostep mode (which is bound to , d m in my Spacemacs, when in emacs-lisp-mode) to expand evil-define-operator. The first expansion will rewrite the evil-define-operator-macro into an evil-define-command-macro, which includes a call to interactive. As this macroexpansion is done by the elisp interpreter or before byte compilation, the variables BEG and END can be assigned using the interactive call inserted by the macro.