emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[nongnu] scratch/evil 79ef3ad9f5 4/8: (evil-with-delay): New macro, extr


From: Stefan Monnier
Subject: [nongnu] scratch/evil 79ef3ad9f5 4/8: (evil-with-delay): New macro, extracted from `evil-delay`
Date: Sun, 2 Jul 2023 12:34:32 -0400 (EDT)

branch: scratch/evil
commit 79ef3ad9f5e9f8024477929ebd0a023069ae893c
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   | 48 ++++++++++++++++++++++-----------------
 evil-core.el     | 24 +++++++++++---------
 evil-states.el   | 21 +++++++++--------
 4 files changed, 86 insertions(+), 75 deletions(-)

diff --git a/evil-commands.el b/evil-commands.el
index 0b28ceac34..347ba5c939 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 1311ae366d..969d5432a8 100644
--- a/evil-common.el
+++ b/evil-common.el
@@ -49,30 +49,38 @@
   (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)))
+  `(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 8f7eba9002..5db6326952 100644
--- a/evil-core.el
+++ b/evil-core.el
@@ -988,16 +988,18 @@ 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)))
+            (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)
@@ -1040,7 +1042,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 abade4c6df..0f20c62869 100644
--- a/evil-states.el
+++ b/evil-states.el
@@ -390,17 +390,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)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]