[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] scratch/evil 17c92495d8 4/8: (evil-with-delay): New macro, extr
From: |
Stefan Monnier |
Subject: |
[nongnu] scratch/evil 17c92495d8 4/8: (evil-with-delay): New macro, extracted from `evil-delay` |
Date: |
Mon, 3 Jul 2023 11:39:11 -0400 (EDT) |
branch: scratch/evil
commit 17c92495d804ec809d227084d3fae1e4731fccdc
Author: Stefan Monnier <monnier@iro.umontreal.ca>
Commit: Stefan Monnier <monnier@iro.umontreal.ca>
(evil-with-delay): New macro, extracted from `evil-delay`
Save some kitten by using a macro instead of using `eval`.
This also exposes more code to the compiler, so should result in
more efficient code and potentially better compiler warnings.
* evil-common.el (evil-unquote): Delete unused function.
(evil--with-delay): New function, extracted from `evil-delay`.
(evil-with-delay): New macro, extracted from `evil-delay`.
(evil-delay): Redefine using `evil-with-delay` and declare obsolete.
* evil-states.el (evil-visual-activate-hook):
* evil-core.el (evil-define-key):
* evil-commands.el (evil-execute-in-normal-state): Use `evil-with-delay`.
---
evil-commands.el | 68 +++++++++++++++++++++++++++++---------------------------
evil-common.el | 50 ++++++++++++++++++++++++-----------------
evil-core.el | 28 ++++++++++++++---------
evil-states.el | 21 +++++++++--------
4 files changed, 92 insertions(+), 75 deletions(-)
diff --git a/evil-commands.el b/evil-commands.el
index 5eb622711f..0d4d8980a9 100644
--- a/evil-commands.el
+++ b/evil-commands.el
@@ -5188,39 +5188,41 @@ Restore the disabled repeat hooks on insert-state exit."
(defun evil-execute-in-normal-state ()
"Execute the next command in Normal state."
(interactive)
- (evil-delay '(not (memq this-command
- '(nil
- evil-execute-in-normal-state
- evil-replace-state
- evil-use-register
- digit-argument
- negative-argument
- universal-argument
- universal-argument-minus
- universal-argument-more
- universal-argument-other-key)))
- `(with-current-buffer ,(current-buffer)
- ;; If cursor was after EOL before CTRL-O and is now at EOL,
- ;; put it after EOL.
- (and (or (when evil--execute-normal-eol-pos
- (= (1+ (point)) (save-excursion
- (goto-char evil--execute-normal-eol-pos)
- (set-marker evil--execute-normal-eol-pos
nil)
- (line-end-position))))
- (and (eq (or goal-column temporary-goal-column)
most-positive-fixnum)
- (memq this-command '(next-line previous-line))))
- (not (eolp))
- (not (memq this-command
- '(evil-insert evil-beginning-of-line
evil-first-non-blank)))
- (forward-char))
- (unless (memq evil-state '(replace insert))
- (evil-change-state ',evil-state))
- (when (eq 'insert evil-state)
- (remove-hook 'pre-command-hook #'evil-repeat-pre-hook)
- (remove-hook 'post-command-hook #'evil-repeat-post-hook)
- (add-hook 'evil-insert-state-exit-hook
#'evil--restore-repeat-hooks))
- (setq evil-execute-normal-keys nil))
- 'post-command-hook)
+ (let ((buf (current-buffer))
+ (estate evil-state))
+ (evil-with-delay (not (memq this-command
+ '(nil
+ evil-execute-in-normal-state
+ evil-replace-state
+ evil-use-register
+ digit-argument
+ negative-argument
+ universal-argument
+ universal-argument-minus
+ universal-argument-more
+ universal-argument-other-key)))
+ post-command-hook
+ (with-current-buffer buf
+ ;; If cursor was after EOL before CTRL-O and is now at EOL,
+ ;; put it after EOL.
+ (and (or (when evil--execute-normal-eol-pos
+ (= (1+ (point)) (save-excursion
+ (goto-char evil--execute-normal-eol-pos)
+ (set-marker evil--execute-normal-eol-pos
nil)
+ (line-end-position))))
+ (and (eq (or goal-column temporary-goal-column)
most-positive-fixnum)
+ (memq this-command '(next-line previous-line))))
+ (not (eolp))
+ (not (memq this-command
+ '(evil-insert evil-beginning-of-line
evil-first-non-blank)))
+ (forward-char))
+ (unless (memq evil-state '(replace insert))
+ (evil-change-state estate))
+ (when (eq 'insert evil-state)
+ (remove-hook 'pre-command-hook #'evil-repeat-pre-hook)
+ (remove-hook 'post-command-hook #'evil-repeat-post-hook)
+ (add-hook 'evil-insert-state-exit-hook #'evil--restore-repeat-hooks))
+ (setq evil-execute-normal-keys nil))))
(setq evil-insert-count nil
evil--execute-normal-return-state evil-state
evil--execute-normal-eol-pos (when (eolp) (point-marker))
diff --git a/evil-common.el b/evil-common.el
index 7034365ade..3f7ea29d6d 100644
--- a/evil-common.el
+++ b/evil-common.el
@@ -49,30 +49,40 @@
(if (fboundp 'gui-set-selection) 'gui-set-selection 'x-set-selection))
;; macro helper
-(eval-and-compile
- (defun evil-unquote (exp)
- "Return EXP unquoted."
- (while (eq (car-safe exp) 'quote)
- (setq exp (cadr exp)))
- exp))
+(defun evil--with-delay (cond-fun body-fun hook &optional append local name)
+ (if (and cond-fun (funcall cond-fun))
+ (funcall body-fun)
+ (let* ((name (or name (format "evil-delay-in-%s" hook)))
+ (fun (make-symbol name)))
+ (fset fun (lambda (&rest _)
+ (when (or (null cond-fun) (funcall cond-fun))
+ (remove-hook hook fun local)
+ (funcall body-fun))))
+ (put fun 'permanent-local-hook t)
+ (add-hook hook fun append local))))
+
+(defmacro evil-with-delay (condition hook &rest body)
+ "Execute BODY when CONDITION becomes true, checking with HOOK.
+HOOK can be a simple symbol or it can be of the form
+\(HOOK APPEND LOCAL NAME) where:
+NAME specifies the name of the entry added to HOOK.
+If APPEND is non-nil, the entry is appended to the hook.
+If LOCAL is non-nil, the buffer-local value of HOOK is modified."
+ (declare (debug (form sexp body)) (indent 2))
+ (unless (consp hook) (setq hook (list hook)))
+ ;; FIXME: Now the compiler doesn't know that `body' is only run if
`condition'
+ ;; is true, so we get spurious warnings! :-(
+ `(evil--with-delay ,(if condition `(lambda () ,condition))
+ (lambda () ,@body)
+ ,@(mapcar #'macroexp-quote hook)))
(defun evil-delay (condition form hook &optional append local name)
"Execute FORM when CONDITION becomes true, checking with HOOK.
-NAME specifies the name of the entry added to HOOK. If APPEND is
-non-nil, the entry is appended to the hook. If LOCAL is non-nil,
+NAME specifies the name of the entry added to HOOK. If APPEND is
+non-nil, the entry is appended to the hook. If LOCAL is non-nil,
the buffer-local value of HOOK is modified."
- (if (and (not (booleanp condition)) (eval condition))
- (eval form)
- (let* ((name (or name (format "evil-delay-form-in-%s" hook)))
- (fun (make-symbol name))
- (condition (or condition t)))
- (fset fun `(lambda (&rest args)
- (when ,condition
- (remove-hook ',hook #',fun ',local)
- ,form)))
- (put fun 'permanent-local-hook t)
- (add-hook hook fun append local))))
-(put 'evil-delay 'lisp-indent-function 2)
+ (declare (obsolete evil-with-delay "2022") (indent 2))
+ (eval `(evil-with-delay ,condition (,hook ,append ,local ,name) ,form) t))
;;; List functions
diff --git a/evil-core.el b/evil-core.el
index a4f9fa1cc2..2fb6437443 100644
--- a/evil-core.el
+++ b/evil-core.el
@@ -978,16 +978,22 @@ mode, in which case `evil-define-minor-mode-key' is used."
((and (consp keymap) (eq (car keymap) 'quote))
`(evil-define-minor-mode-key ,state ,keymap ,key ,def ,@bindings))
(t
- `(evil-delay ',(if (symbolp keymap)
- `(and (boundp ',keymap) (keymapp ,keymap))
- `(keymapp ,keymap))
- '(condition-case-unless-debug err
- (evil-define-key* ,state ,keymap ,key ,def ,@bindings)
- (error (message "error in evil-define-key: %s"
- (error-message-string err))))
- 'after-load-functions t nil
- (format "evil-define-key-in-%s"
- ',(if (symbolp keymap) keymap 'keymap))))))
+ `(evil-with-delay ,(if (symbolp keymap)
+ ;; BEWARE: Can't work for lexically scoped
vars.
+ `(and (boundp ',keymap) (keymapp ,keymap))
+ `(keymapp ,keymap))
+ (after-load-functions t nil
+ ,(format "evil-define-key-in-%s"
+ (if (symbolp keymap) keymap
+ 'keymap)))
+ ;; Sadly, the compiler doesn't understand `evil-with-delay's code
+ ;; well enough to figure out that the keymap var is necessarily
+ ;; bound since we just tested `boundp'.
+ ,(if (symbolp keymap) `(defvar ,keymap))
+ (condition-case-unless-debug err
+ (evil-define-key* ,state ,keymap ,key ,def ,@bindings)
+ (error (message "error in evil-define-key: %s"
+ (error-message-string err))))))))
(defalias 'evil-declare-key #'evil-define-key)
(defun evil-define-key* (state keymap key def &rest bindings)
@@ -1030,7 +1036,7 @@ The use is nearly identical to `evil-define-key' with the
exception that this is a function and not a macro (and so will
not be expanded when compiled which can have unintended
consequences). `evil-define-key*' also does not defer any
-bindings like `evil-define-key' does using `evil-delay'. This
+bindings like `evil-define-key' does using `evil-with-delay'. This
allows errors in the bindings to be caught immediately, and makes
its behavior more predictable."
(declare (indent defun))
diff --git a/evil-states.el b/evil-states.el
index 9c824ab592..695f8871e2 100644
--- a/evil-states.el
+++ b/evil-states.el
@@ -381,17 +381,16 @@ otherwise exit Visual state."
(defun evil-visual-activate-hook (&optional _command)
"Enable Visual state if the region is activated."
(unless (evil-visual-state-p)
- (evil-delay nil
- ;; the activation may only be momentary, so re-check
- ;; in `post-command-hook' before entering Visual state
- '(unless (or (evil-visual-state-p)
- (evil-insert-state-p)
- (evil-emacs-state-p))
- (when (and (region-active-p)
- (not deactivate-mark))
- (evil-visual-state)))
- 'post-command-hook nil t
- "evil-activate-visual-state")))
+ (evil-with-delay nil
+ (post-command-hook nil t "evil-activate-visual-state")
+ ;; the activation may only be momentary, so re-check
+ ;; in `post-command-hook' before entering Visual state
+ (unless (or (evil-visual-state-p)
+ (evil-insert-state-p)
+ (evil-emacs-state-p))
+ (when (and (region-active-p)
+ (not deactivate-mark))
+ (evil-visual-state))))))
(put 'evil-visual-activate-hook 'permanent-local-hook t)
(defun evil-visual-deactivate-hook (&optional command)
- [nongnu] branch scratch/evil created (now ea1b21d658), Stefan Monnier, 2023/07/03
- [nongnu] scratch/evil b04145a776 7/8: Replace uses of `defadvice` with `advice-add`, Stefan Monnier, 2023/07/03
- [nongnu] scratch/evil 675faf080b 5/8: Use lexical-binding everywhere, Stefan Monnier, 2023/07/03
- [nongnu] scratch/evil 17c92495d8 4/8: (evil-with-delay): New macro, extracted from `evil-delay`,
Stefan Monnier <=
- [nongnu] scratch/evil b59be16833 1/8: evil-pkg.el: Remove file, Stefan Monnier, 2023/07/03
- [nongnu] scratch/evil 1ba1eb9b66 2/8: Better follow conventions for use of ' in docstrings, Stefan Monnier, 2023/07/03
- [nongnu] scratch/evil ea1b21d658 8/8: Misc minor changes, Stefan Monnier, 2023/07/03
- [nongnu] scratch/evil df957ddb68 3/8: Prefer #' to quote function names, Stefan Monnier, 2023/07/03
- [nongnu] scratch/evil f09062ee12 6/8: Remove redundant `:group` args, Stefan Monnier, 2023/07/03