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

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

[nongnu] elpa/evil-escape 1271af99ac 064/133: Rewrite of evil-escape (v3


From: ELPA Syncer
Subject: [nongnu] elpa/evil-escape 1271af99ac 064/133: Rewrite of evil-escape (v3.0)
Date: Wed, 3 Jan 2024 21:59:53 -0500 (EST)

branch: elpa/evil-escape
commit 1271af99ac537a3e38d7ce5445e8d12e35e302b0
Author: syl20bnr <sylvain.benner@gmail.com>
Commit: syl20bnr <sylvain.benner@gmail.com>

    Rewrite of evil-escape (v3.0)
---
 evil-escape.el | 489 +++++++++++++++------------------------------------------
 1 file changed, 126 insertions(+), 363 deletions(-)

diff --git a/evil-escape.el b/evil-escape.el
index c98550c465..f6f95fa064 100644
--- a/evil-escape.el
+++ b/evil-escape.el
@@ -5,7 +5,7 @@
 ;; Author: Sylvain Benner <sylvain.benner@gmail.com>
 ;; Keywords: convenience editing evil
 ;; Created: 22 Oct 2014
-;; Version: 2.29
+;; Version: 3.0
 ;; Package-Requires: ((emacs "24") (evil "1.0.9"))
 ;; URL: https://github.com/syl20bnr/evil-escape
 
@@ -50,12 +50,10 @@
 ;; --------------
 
 ;; The key sequence can be customized with the variable
-;; `evil-escape-key-sequence'
-;; It must be set before requiring evil-escape.
+;; `evil-escape-key-sequence'.
 
 ;; The delay between the two key presses can be customized with
 ;; the variable `evil-escape-delay'. Default is `0.1'.
-;; It must be set before requiring evil-escape.
 
 ;; A major mode can be excluded by adding it to the list
 ;; `evil-escape-excluded-major-modes'.
@@ -63,15 +61,6 @@
 ;; More information in the readme of the repository:
 ;; https://github.com/syl20bnr/evil-escape
 
-;; Limitations
-
-;; `fd' cannot be used during macro recording, use regular `ESC'
-;; instead.
-
-;; Due to the current implementation only the key declared in
-;; `evil-motion-state-map' can be used as the first character
-;; of the key sequence:
-
 ;;; Code:
 
 (require 'evil)
@@ -81,56 +70,20 @@
   :prefix "evil-escape-"
   :group 'evil)
 
-(eval-and-compile
-  (defcustom evil-escape-key-sequence (kbd "fd")
-    "Two keys sequence to escape from insert state."
-    :type 'key-sequence
-    :group 'evil-escape)
-
-  (defcustom evil-escape-delay 0.1
-    "Max time delay between the two key press to be considered successful."
-    :type 'number
-    :group 'evil-escape)
-
-  (defcustom evil-escape-excluded-major-modes '()
-    "Excluded major modes where escape sequences has no effect."
-    :type 'sexp
-    :group 'evil-escape)
-)
-
-(defvar evil-escape-motion-state-shadowed-func nil
-  "Original function of `evil-motion-state' shadowed by `evil-espace'.
-This variable is used to restore the original function bound to the
-first key of the escape key sequence when `evil-escape'
-mode is disabled.")
-
-(defvar evil-escape-isearch-shadowed-func nil
-  "Original function of `isearch-mode-map' shadowed by `evil-escape'.
-This variable is used to restore the original function bound to the
-first key of the escape key sequence when `evil-escape'
-mode is disabled.")
-
-(defvar evil-escape-lisp-state-shadowed-func nil
-  "Original function of `evil-lisp-state-map' shadowed by `evil-escape'.
-This variable is used to restore the original function bound to the
-first key of the escape key sequence when `evil-escape'
-mode is disabled.")
-
-(defvar evil-escape-evilified-state-shadowed-func nil
-  "Original function of `evil-evilified-state-map' shadowed by `evil-escape'.
-This variable is used to restore the original function bound to the
-first key of the escape key sequence when `evil-escape'
-mode is disabled.")
-
-(defvar evil-escape-iedit-state-shadowed-func nil
-  "Original function of `evil-iedit-state-map' shadowed by `evil-escape'.
-This variable is used to restore the original function bound to the
-first key of the escape key sequence when `evil-escape'
-mode is disabled.")
-
-(defvar evil-escape-inhibit nil
-  "If non nil then evil-escape does nothing. This variable is used to
-support functions which wrap evil-escape.")
+(defcustom evil-escape-key-sequence (kbd "fd")
+  "Two keys sequence to escape from insert state."
+  :type 'key-sequence
+  :group 'evil-escape)
+
+(defcustom evil-escape-delay 0.1
+  "Max time delemacs-lisp-modeay between the two key press to be considered 
successful."
+  :type 'number
+  :group 'evil-escape)
+
+(defcustom evil-escape-excluded-major-modes '()
+  "Excluded major modes where escape sequences has no effect."
+  :type 'sexp
+  :group 'evil-escape)
 
 ;;;###autoload
 (define-minor-mode evil-escape-mode
@@ -140,318 +93,128 @@ with a key sequence."
   :group 'evil
   :global t
   (if evil-escape-mode
-      (evil-escape--define-keys)
-    (evil-escape--undefine-keys)))
-
-(eval-and-compile
-  (defun evil-escape--first-key ()
-    "Return the first key string in the key sequence."
-    (let* ((first-key (elt evil-escape-key-sequence 0))
-           (fkeystr (char-to-string first-key)))
-      fkeystr)))
-
-(defun evil-escape--escape-function-symbol (from)
-  "Return the function symbol for the passed FROM string."
-  (intern (format "evil-escape-%s" from)))
-
-(defmacro evil-escape-define-escape (from map command &rest properties)
-  "Define a function to escape from FROM in MAP keymap by executing COMMAND.
-
-`:shadowed-func FUNCTION'
-     If non nil specify the shadowed function from the first key of the
-     sequence.
-
-`:insert-func FUNCTION'
-     Specify the insert function to call when inserting the first key.
-
-`:delete-func FUNCTION'
-     Specify the delete function to call when deleting the first key."
-  (let* ((shadowed-func (plist-get properties :shadowed-func))
-         (evil-func-props (when shadowed-func
-                            (evil-get-command-properties shadowed-func)))
-         (insert-func (plist-get properties :insert-func))
-         (delete-func (plist-get properties :delete-func)))
-    `(progn
-       (define-key ,map ,(evil-escape--first-key)
-         (evil-define-motion ,(evil-escape--escape-function-symbol from)
-           (count)
-           ,(format "evil-escape wrapper function for `%s'." command)
-           ,@evil-func-props
-           (if (eq 'operator evil-state)
-               (call-interactively ',shadowed-func)
-             (if (and (called-interactively-p 'interactive)
-                      (not (memq major-mode evil-escape-excluded-major-modes)))
-                 ;; called by the user
-                 (evil-escape--escape ,from
-                                      ',map
-                                      ,evil-escape-key-sequence
-                                      ',command
-                                      ',shadowed-func
-                                      ',insert-func
-                                      ',delete-func)
-               ;; not called by the user (i.e. via a macro)
-               (evil-escape--setup-passthrough ,from ',map 
',shadowed-func))))))))
-
-(defun evil-escape--define-keys ()
-  "Set the key bindings to escape _everything!_"
-  (setq evil-escape-motion-state-shadowed-func
-        (or evil-escape-motion-state-shadowed-func
-            (lookup-key evil-motion-state-map (evil-escape--first-key))))
-  ;; evil states
-  ;; insert state
-  (eval `(evil-escape-define-escape "insert-state" evil-insert-state-map 
evil-normal-state
-                                    :insert-func 
evil-escape--insert-state-insert-func
-                                    :delete-func 
evil-escape--insert-state-delete-func))
-  ;; emacs state
-  (eval `(evil-escape-define-escape "emacs-state" evil-emacs-state-map
-                                    evil-escape--emacs-state-exit-func))
-  ;; visual state
-  (eval `(evil-escape-define-escape "visual-state" evil-visual-state-map 
evil-exit-visual-state
-                                    :shadowed-func 
,evil-escape-motion-state-shadowed-func))
-  ;; motion state
-  (let ((exit-func (lambda () (interactive)
-                     (cond ((or (eq 'apropos-mode major-mode)
-                                (eq 'help-mode major-mode)
-                                (eq 'ert-results-mode major-mode)
-                                (eq 'ert-simple-view-mode major-mode))
-                            (quit-window))
-                           ((eq 'undo-tree-visualizer-mode major-mode)
-                            (undo-tree-visualizer-quit))
-                           ((and (fboundp 'helm-ag--edit-abort)
-                                 (string-equal "*helm-ag-edit*" (buffer-name)))
-                            (call-interactively 'helm-ag--edit-abort))
-                           ((eq 'neotree-mode major-mode) (neotree-hide))
-                           (t (evil-normal-state))))))
-    (eval `(evil-escape-define-escape "motion-state" evil-motion-state-map 
,exit-func
-                                      :shadowed-func 
,evil-escape-motion-state-shadowed-func)))
-  ;; replace state
-  (eval `(evil-escape-define-escape "replace-state" evil-replace-state-map 
evil-normal-state
-                                    :insert-func 
evil-escape--default-insert-func
-                                    :delete-func 
evil-escape--default-delete-func))
-  ;; mini-buffer
-  (eval `(evil-escape-define-escape "minibuffer" minibuffer-local-map 
abort-recursive-edit
-                                    :insert-func 
evil-escape--default-insert-func
-                                    :delete-func 
evil-escape--default-delete-func))
-  ;; evil ex command
-  (eval `(evil-escape-define-escape "ex-command" evil-ex-completion-map 
abort-recursive-edit
-                                    :insert-func 
evil-escape--default-insert-func
-                                    :delete-func 
evil-escape--default-delete-func))
-  ;; isearch
-  (setq evil-escape-isearch-shadowed-func
-        (or evil-escape-isearch-shadowed-func
-            (lookup-key isearch-mode-map (evil-escape--first-key))))
-  (eval `(evil-escape-define-escape "isearch" isearch-mode-map isearch-abort
-                                    :insert t
-                                    :delete t
-                                    :shadowed-func 
,evil-escape-isearch-shadowed-func
-                                    :insert-func 
evil-escape--isearch-insert-func
-                                    :delete-func isearch-delete-char))
-  ;; lisp state if installed
-  (eval-after-load 'evil-lisp-state
-    '(progn
-       (setq evil-escape-lisp-state-shadowed-func
-             (or evil-escape-lisp-state-shadowed-func
-                 (lookup-key evil-lisp-state-map (evil-escape--first-key))))
-       (eval `(evil-escape-define-escape "lisp-state" evil-lisp-state-map
-                                         evil-normal-state
-                                         :shadowed-func 
,evil-escape-lisp-state-shadowed-func))))
-  ;; iedit state if installed
-  (eval-after-load 'evil-iedit-state
-    '(progn
-       (setq evil-escape-iedit-state-shadowed-func
-             (or evil-escape-iedit-state-shadowed-func
-                 (lookup-key evil-iedit-state-map (evil-escape--first-key))))
-       (eval `(evil-escape-define-escape "iedit-state" evil-iedit-state-map
-                                         evil-iedit-state/quit-iedit-mode
-                                         :shadowed-func 
,evil-escape-iedit-state-shadowed-func))
-       (eval '(evil-escape-define-escape "iedit-insert-state" 
evil-iedit-insert-state-map
-                                         evil-iedit-state/quit-iedit-mode
-                                         :insert-func 
evil-escape--default-insert-func
-                                         :delete-func 
evil-escape--default-delete-func))))
-
-  ;; evilified state if installed
-  (eval-after-load 'evil-evilified-state
-    '(progn
-       (setq evil-escape-evilified-state-shadowed-func
-             (or evil-escape-evilified-state-shadowed-func
-                 (lookup-key evil-evilified-state-map 
(evil-escape--first-key))))
-       (eval `(evil-escape-define-escape
-               "evilified-state" evil-evilified-state-map
-               evil-escape--emacs-state-exit-func
-               :shadowed-func ,evil-escape-evilified-state-shadowed-func)))))
-
-(defun evil-escape--undefine-keys ()
-  "Unset the key bindings defined in `evil-escape--define-keys'."
-  (let ((first-key (evil-escape--first-key)))
-    ;; bulk undefine
-    (dolist (map '(evil-insert-state-map
-                   evil-motion-state-map
-                   evil-emacs-state-map
-                   evil-visual-state-map
-                   evil-lisp-state-map
-                   evil-evilified-state-map
-                   evil-iedit-state-map
-                   evil-iedit-insert-state-map
-                   minibuffer-local-map
-                   isearch-mode-map
-                   evil-ex-completion-map))
-      (when (boundp map)
-        (define-key (eval map) first-key nil)))
-    ;; motion state
-    (when evil-escape-motion-state-shadowed-func
-        (define-key evil-motion-state-map
-          (kbd first-key) evil-escape-motion-state-shadowed-func))
-    ;; isearch
-    (when evil-escape-isearch-shadowed-func
-        (define-key isearch-mode-map
-          (kbd first-key) evil-escape-isearch-shadowed-func))
-    ;; list state
-    (when evil-escape-lisp-state-shadowed-func
-        (define-key evil-lisp-state-map
-          (kbd first-key) evil-escape-lisp-state-shadowed-func))
-    ;; evilified state
-    (when evil-escape-evilified-state-shadowed-func
-        (define-key evil-evilified-state-map
-          (kbd first-key) evil-escape-evilified-state-shadowed-func))
-    ;; iedit state
-    (when evil-escape-iedit-state-shadowed-func
-      (define-key evil-iedit-state-map
-        (kbd first-key) evil-escape-iedit-state-shadowed-func)
-      (define-key evil-iedit-insert-state-map (kbd first-key) nil))))
-
-(defun evil-escape--default-insert-func (_)
-  "Insert typed char in current buffer if not read only."
-  (when (not buffer-read-only) (self-insert-command 1)))
-
-(defun evil-escape--insert-state-insert-func (key)
-  "Take care of term-mode."
-  (interactive)
-  (cond ((eq 'term-mode major-mode)
-         (call-interactively 'term-send-raw))
-        (t (evil-escape--default-insert-func key))))
-
-(defun evil-escape--isearch-insert-func (key)
-  "Insert KEY in current buffer if not read only."
-  (isearch-printing-char))
-
-(defun evil-escape--default-delete-func ()
-  "Delete char in current buffer if not read only."
-  (when (not buffer-read-only) (delete-char -1)))
+      (add-hook 'pre-command-hook 'evil-escape-pre-command-hook)
+    (remove-hook 'pre-command-hook 'evil-escape-pre-command-hook)))
+
+(defun evil-escape-pre-command-hook ()
+  ""
+  (when (evil-escape-p)
+    (let ((inserted (evil-escape--insert)))
+      (let ((skey (elt evil-escape-key-sequence 1))
+            (evt (read-event nil nil evil-escape-delay)))
+        (cond
+         ((null evt)
+          (when inserted (evil-escape--delete)))
+         ((and (integerp evt) (char-equal evt skey))
+          (when inserted (evil-escape--delete))
+          (evil-escape--escape)
+          (setq this-command 'ignore))
+         (t
+          (when inserted (evil-escape--delete))
+          (setq unread-command-events
+                (append unread-command-events (list evt)))))))))
 
-(defun evil-escape--insert-state-delete-func ()
-  "Take care of term-mode and other weird modes."
-  (interactive)
-  (cond ((eq 'term-mode major-mode)
-         (call-interactively 'term-send-backspace))
-        ((eq 'deft-mode major-mode)
-         (call-interactively 'deft-filter-increment))
-        (t (evil-escape--default-delete-func))))
-
-(defun evil-escape--emacs-state-exit-func ()
-  "Return the exit function to execute."
-  (interactive)
+(defun evil-escape-p ()
+  "Return non-nil if evil-escape should run."
+  (and (or (window-minibuffer-p)
+           (and (fboundp 'helm-alive-p) (helm-alive-p))
+           (and (not (eq evil-state 'normal))
+                (not (eq evil-state 'motion))))
+       (not (memq major-mode evil-escape-excluded-major-modes))
+       (equal (this-command-keys) (evil-escape--first-key))))
+
+(defun evil-escape--escape ()
+  "Escape from everything... well almost everything."
+  (pcase evil-state
+    (`normal (evil-escape--escape-normal-state))
+    (`motion (evil-escape--escape-motion-state))
+    (`insert (evil-normal-state))
+    (`emacs (evil-escape--escape-emacs-state))
+    (`evilified (evil-escape--escape-emacs-state))
+    (`visual (evil-exit-visual-state))
+    (`replace (evil-normal-state))
+    (`lisp (evil-normal-state))
+    (`iedit (evil-iedit-state/quit-iedit-mode))
+    (`iedit-insert (evil-iedit-state/quit-iedit-mode))
+    (_ (evil-escape--escape-normal-state))))
+
+(defun evil-escape--escape-normal-state ()
+  "Escape from normal state."
+  (cond
+   ((and (fboundp 'helm-alive-p) (helm-alive-p))
+    (abort-recursive-edit))
+   ((eq major-mode 'isearch-mode) (isearch-abort))
+   ((window-minibuffer-p) (abort-recursive-edit))))
+
+(defun evil-escape--escape-motion-state ()
+  "Escape from motion state."
+  (cond
+   ((or (eq 'apropos-mode major-mode)
+        (eq 'help-mode major-mode)
+        (eq 'ert-results-mode major-mode)
+        (eq 'ert-simple-view-mode major-mode))
+    (quit-window)
+    ((eq 'undo-tree-visualizer-mode major-mode)
+     (undo-tree-visualizer-quit)))
+   ((and (fboundp 'helm-ag--edit-abort)
+         (string-equal "*helm-ag-edit*" (buffer-name)))
+    (call-interactively 'helm-ag--edit-abort))
+   ((eq 'neotree-mode major-mode) (neotree-hide))
+   (t (evil-normal-state))))
+
+(defun evil-escape--escape-emacs-state ()
+  "Escape from emacs state."
   (cond ((string-match "magit" (symbol-name major-mode))
          (evil-escape--escape-with-q))
         ((eq 'paradox-menu-mode major-mode)
          (evil-escape--escape-with-q))
         ((eq 'gist-list-menu-mode major-mode)
          (quit-window))
-        (t  (evil-normal-state))))
+        (t (evil-normal-state))))
+
+(defun evil-escape--first-key ()
+  "Return the first key string in the key sequence."
+  (let* ((first-key (elt evil-escape-key-sequence 0))
+         (fkeystr (char-to-string first-key)))
+    fkeystr))
+
+(defun evil-escape--insert-func ()
+  "Default insert function."
+  (when (not buffer-read-only) (self-insert-command 1)))
+
+(defun evil-escape--default-delete-func ()
+  "Delete char in current buffer if not read only."
+  (when (not buffer-read-only) (delete-char -1)))
+
+(defun evil-escape--insert ()
+  "Insert the first key of the sequence."
+  (pcase evil-state
+    (`insert (pcase major-mode
+               (`isearch-mode (isearch-printing-char))
+               (`term-mode (call-interactively 'term-send-raw))
+               (_ (evil-escape--insert-func))) t)
+    (`normal
+     (when (window-minibuffer-p) (evil-escape--insert-func) t))
+    (`replace (evil-escape--insert-func) t)
+    (`iedit-insert (evil-escape--insert-func) t)))
+
+(defun evil-escape--delete ()
+  "Revert the insertion of the first key of the sequence."
+  (pcase evil-state
+    (`insert (pcase major-mode
+               (`isearch-mode (isearch-delete-char))
+               (`term-mode (call-interactively 'term-send-backspace))
+               (`deft-mode (call-interactively 'deft-filter-increment))
+               (_ (evil-escape--default-delete-func))))
+    (`normal
+     (when (minibuffer-window-active-p (evil-escape--default-delete-func))))
+    (`replace (evil-escape--default-delete-func))
+    (`iedit-insert (evil-escape--default-delete-func))))
 
 (defun evil-escape--escape-with-q ()
   "Send `q' key press event to exit from a buffer."
   (setq unread-command-events (listify-key-sequence "q")))
 
-(defun evil-escape--execute-shadowed-func (func)
-  "Execute the passed FUNC if the context allows it."
-  (unless (or (null func)
-              (eq 'insert evil-state)
-              (and (boundp 'isearch-mode) (symbol-value 'isearch-mode))
-              (minibufferp))
-    (call-interactively func)))
-
-(defun evil-escape--passthrough (from key map shadowed passthrough)
-  "Allow the next command KEY to pass through MAP so they can reach
-the underlying major or minor modes map.
-Once the command KEY passed through MAP the function HFUNC is removed
-from the `post-command-hook'."
-  (if evil-escape--first-pass
-      ;; first pass
-      (progn
-        (if shadowed
-            (define-key map key shadowed)
-          (evil-escape--undefine-keys))
-        (setq evil-escape--first-pass nil))
-    ;; second pass
-    (evil-escape--define-keys)
-    (setq evil-escape-inhibit nil)
-    (remove-hook 'post-command-hook passthrough)))
-
-(defun evil-escape--setup-passthrough (from map &optional shadowed-func)
-  "Setup a pass through for the next command"
-  (let ((passthrough (intern (format "evil-escape--%s-passthrough" from))))
-    (eval `(defun ,passthrough ()
-             ,(format "Setup an evil-escape passthrough for wrapper %s" from)
-             (evil-escape--passthrough ,from
-                                       (evil-escape--first-key)
-                                       ,map
-                                       ',shadowed-func
-                                       ',passthrough)))
-    (setq evil-escape--first-pass t
-          evil-escape-inhibit t)
-    (add-hook 'post-command-hook passthrough)
-    (unless (or (bound-and-true-p isearch-mode) (minibufferp))
-      (setq unread-command-events
-            (append unread-command-events (listify-key-sequence
-                                           (evil-escape--first-key)))))))
-
-(defun evil-escape--escape
-    (from map keys callback
-          &optional shadowed-func insert-func delete-func)
-  "Execute the passed CALLBACK using KEYS. KEYS is a cons cell of 2 characters.
-
-If the first key insertion shadowed a function then pass the shadowed function
-in SHADOWED-FUNC and it will be executed if the key sequence was not
- successfull.
-
-If INSERT-FUNC is not nil then the first key pressed is inserted using the
- function INSERT-FUNC.
-
-If DELETE-FUNC is not nil then the first key is deleted using the function
-DELETE-FUNC when calling CALLBACK. "
-  (let* ((modified (buffer-modified-p))
-         (fkey (elt keys 0))
-         (fkeystr (char-to-string fkey))
-         (skey (elt keys 1))
-         (hl-line-mode-before (when (boundp 'hl-line-mode) hl-line-mode)))
-    (unless evil-escape-inhibit
-      (if insert-func (funcall insert-func fkey))
-      ;; global-hl-line-mode seems to be deactivated when `read-event' so we
-      ;; temporarily force line-mode locally to prevent flicker
-      (when (or (bound-and-true-p global-hl-line-mode)
-                (bound-and-true-p hl-line-mode))
-        (hl-line-mode))
-      (let* ((evt (read-event nil nil evil-escape-delay)))
-        (unless hl-line-mode-before (hl-line-mode -1))
-        (cond
-         ((null evt)
-          (unless insert-func
-            (evil-escape--setup-passthrough from map shadowed-func)))
-         ((and (integerp evt)
-               (char-equal evt skey))
-          ;; remove the f character
-          (if delete-func (funcall delete-func))
-          (set-buffer-modified-p modified)
-          ;; disable running transient map
-          (unless (equal "isearch" from)
-            (setq overriding-terminal-local-map nil))
-          (call-interactively callback))
-         (t ; otherwise
-          (unless insert-func
-            (evil-escape--setup-passthrough from map shadowed-func))
-          (setq unread-command-events
-                (append unread-command-events (list evt)))))))))
-
 (provide 'evil-escape)
 
 ;;; evil-escape.el ends here



reply via email to

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