diff --git a/evil-macros.el b/evil-macros.el index 9e7d2f34..ebc188e0 100644 --- a/evil-macros.el +++ b/evil-macros.el @@ -58,7 +58,7 @@ The return value is a list (BEG END TYPE)." (evil-this-type (or type (evil-get-command-property motion :type 'exclusive)))) (condition-case err - (let ((repeat-type (evil-repeat-type motion t))) + (let ((repeat-type (evil--repeat-type motion))) (when (functionp repeat-type) (funcall repeat-type 'pre)) (unless (with-local-quit (setq range (call-interactively motion)) diff --git a/evil-repeat.el b/evil-repeat.el index edc6db1e..b9141fb5 100644 --- a/evil-repeat.el +++ b/evil-repeat.el @@ -122,12 +122,6 @@ (require 'evil-states) -(declare-function evil-visual-state-p "evil-visual") -(declare-function evil-visual-range "evil-visual") -(declare-function evil-visual-char "evil-visual") -(declare-function evil-visual-line "evil-visual") -(declare-function evil-visual-block "evil-visual") - (defmacro evil-without-repeat (&rest body) (declare (indent defun) (debug t)) @@ -173,8 +167,7 @@ Update `evil-repeat-ring' with the accumulated changes in `evil-repeat-info' and clear variables." (unwind-protect (when (evil-repeat-recording-p) - (setq evil-repeat-info - (evil-normalize-repeat-info evil-repeat-info)) + (setq evil-repeat-info (evil-normalize-repeat-info evil-repeat-info)) (when (and evil-repeat-info evil-repeat-ring) (ring-insert evil-repeat-ring evil-repeat-info))) (evil-repeat-reset nil))) @@ -224,43 +217,51 @@ buffer is known and different from the current buffer." (not (minibufferp)) (not (eq (current-buffer) evil-repeat-buffer)))) +(defvar evil-repeat-types + '((t . evil-repeat-keystrokes) + (change . evil-repeat-changes) + (motion . evil-repeat-motion) + (insert-at-point . evil-repeat-insert-at-point) + (ignore . nil)) + "Alist of defined repeat-types.") + +(defun evil--repeat-type (command) + "Return the :repeat property of COMMAND." + (when (functionp command) ; ignore keyboard macros + (let* ((type (evil-get-command-property command :repeat t)) + (repeat-type (assq type evil-repeat-types))) + (if repeat-type (cdr repeat-type) type)))) + (defun evil-repeat-type (command &optional default) "Return the :repeat property of COMMAND. If COMMAND doesn't have this property, return DEFAULT." + (declare (obsolete evil--repeat-type "1.15.0")) (when (functionp command) ; ignore keyboard macros (let* ((type (evil-get-command-property command :repeat default)) (repeat-type (assq type evil-repeat-types))) (if repeat-type (cdr repeat-type) type)))) (defun evil-repeat-force-abort-p (repeat-type) - "Return non-nil iff the current command should abort the recording of repeat information." - (or (evil-repeat-different-buffer-p) ; ... buffer changed - (eq repeat-type 'abort) ; ... explicitely forced - (eq evil-recording-repeat 'abort) ; ... already aborted - (evil-emacs-state-p) ; ... in Emacs state - (and (evil-mouse-events-p (this-command-keys)) ; ... mouse events + "Return non-nil if the current command should abort the recording of repeat info." + (or (evil-repeat-different-buffer-p) ; ... buffer changed + (eq repeat-type 'abort) ; ... explicitely forced + (eq evil-recording-repeat 'abort) ; ... already aborted + (evil-emacs-state-p) ; ... in Emacs state + (and (evil-mouse-events-p ; ... mouse events + (this-command-keys-vector)) (eq repeat-type nil)) - (minibufferp))) ; ... minibuffer activated + (minibufferp))) ; ... minibuffer activated (defun evil-repeat-record (info) - "Add INFO to the end of `evil-repeat-info'." + "Append INFO to `evil-repeat-info'." (when (evil-repeat-recording-p) (setq evil-repeat-info (nconc evil-repeat-info (list info))))) -;; called from `evil-normal-state-exit-hook' -(defun evil-repeat-start-hook () - "Record a new repeat when exiting Normal state. -Does not record in Emacs state or if the current command -has :repeat nil." - (when (and (eq (evil-repeat-type this-command t) t) - (not (evil-emacs-state-p))) - (evil-repeat-start))) - ;; called from `pre-command-hook' (defun evil-repeat-pre-hook () "Prepare the current command for recording the repeation." (when evil-local-mode - (let ((repeat-type (evil-repeat-type this-command t))) + (let ((repeat-type (evil--repeat-type this-command))) (cond ;; abort the repeat ((evil-repeat-force-abort-p repeat-type) @@ -270,7 +271,7 @@ has :repeat nil." (evil-repeat-abort)) ;; ignore those commands completely ((or (null repeat-type) - (evil-mouse-events-p (this-command-keys)))) + (evil-mouse-events-p (this-command-keys-vector)))) ;; record command (t ;; In normal-state or visual state, each command is a single @@ -286,7 +287,7 @@ has :repeat nil." (defun evil-repeat-post-hook () "Finish recording of repeat-information for the current-command." (when (and evil-local-mode evil-recording-repeat) - (let ((repeat-type (evil-repeat-type this-command t))) + (let ((repeat-type (evil--repeat-type this-command))) (cond ;; abort the repeat ((evil-repeat-force-abort-p repeat-type) @@ -358,7 +359,7 @@ Motions are recorded by keystroke but only in Insert state." ;; called from the `after-change-functions' hook (defun evil-repeat-change-hook (beg end length) "Record change information for current command." - (let ((repeat-type (evil-repeat-type this-command t))) + (let ((repeat-type (evil--repeat-type this-command))) (when (and (evil-repeat-recording-p) (eq repeat-type 'evil-repeat-changes) (not (evil-emacs-state-p)) @@ -375,8 +376,7 @@ Motions are recorded by keystroke but only in Insert state." "Record the current buffer changes during a repeat. If CHANGE is specified, it is added to `evil-repeat-changes'." (when (evil-repeat-recording-p) - (setq evil-repeat-changes - (nconc evil-repeat-changes (list (list relpos ins ndel)))))) + (push (list relpos ins ndel) evil-repeat-changes))) (defun evil-repeat-start-record-changes () "Start the recording of a new set of buffer changes." @@ -387,7 +387,7 @@ If CHANGE is specified, it is added to `evil-repeat-changes'." "Finish the recording of buffer changes and record them as repeat." (when (evil-repeat-recording-p) (evil-repeat-record `(evil-execute-change - ,evil-repeat-changes + ,(nreverse evil-repeat-changes) ,(- (point) evil-repeat-pos))) (setq evil-repeat-changes nil))) @@ -402,7 +402,7 @@ inserts some text in a buffer between (point) and (mark)." (remove-hook 'after-change-functions #'evil-repeat-insert-at-point-hook t)))) (defun evil-repeat-insert-at-point-hook (beg end _length) - (let ((repeat-type (evil-repeat-type this-command t))) + (let ((repeat-type (evil--repeat-type this-command))) (when (and (evil-repeat-recording-p) (eq repeat-type 'evil-repeat-insert-at-point) (not (evil-emacs-state-p)) @@ -628,7 +628,7 @@ If COUNT is negative, this is a more recent kill." "Record `this-command-keys' before it is overwritten." (when (and (evil-repeat-recording-p) evil-recording-current-command) - (let ((repeat-type (evil-repeat-type this-command t))) + (let ((repeat-type (evil--repeat-type this-command))) (when (functionp repeat-type) (funcall repeat-type 'pre-read-key-sequence))))) diff --git a/evil-states.el b/evil-states.el index abade4c6..9c824ab5 100644 --- a/evil-states.el +++ b/evil-states.el @@ -25,10 +25,10 @@ ;; You should have received a copy of the GNU General Public License ;; along with Evil. If not, see . -(require 'evil-core) - ;;; Code: +(require 'evil-core) + ;;; Normal state (evil-define-state normal @@ -36,7 +36,6 @@ AKA \"Command\" state." :tag " " :enable (motion) - :exit-hook (evil-repeat-start-hook) (cond ((evil-normal-state-p) (overwrite-mode -1) @@ -139,6 +138,7 @@ commands opening a new line." (remove-hook 'pre-command-hook #'evil-insert-repeat-hook)) (put 'evil-insert-repeat-hook 'permanent-local-hook t) +(declare-function evil-execute-repeat-info "evil-repeat") (defun evil-cleanup-insert-state () "Called when Insert or Replace state is about to be exited. Handles the repeat-count of the insertion command." @@ -148,22 +148,15 @@ Handles the repeat-count of the insertion command." (evil-insert-newline-below) (when evil-auto-indent (indent-according-to-mode))) - (when (fboundp 'evil-execute-repeat-info) - (evil-execute-repeat-info - (cdr evil-insert-repeat-info))))) + (evil-execute-repeat-info (cdr evil-insert-repeat-info)))) (when evil-insert-vcount (let ((buffer-invisibility-spec buffer-invisibility-spec)) ;; make all lines hidden by hideshow temporarily visible (when (listp buffer-invisibility-spec) (setq buffer-invisibility-spec - (evil-filter-list - #'(lambda (x) - (or (eq x 'hs) - (eq (car-safe x) 'hs))) - buffer-invisibility-spec))) - (let ((line (nth 0 evil-insert-vcount)) - (col (nth 1 evil-insert-vcount)) - (vcount (nth 2 evil-insert-vcount))) + (cl-remove-if (lambda (x) (eq (or (car-safe x) x) 'hs)) + buffer-invisibility-spec))) + (cl-destructuring-bind (line col vcount) evil-insert-vcount (save-excursion (dotimes (v (1- vcount)) (goto-char (point-min)) @@ -177,9 +170,7 @@ Handles the repeat-count of the insertion command." (move-to-column col t) (funcall col)) (dotimes (_ (or evil-insert-count 1)) - (when (fboundp 'evil-execute-repeat-info) - (evil-execute-repeat-info - (cdr evil-insert-repeat-info))))))))))) + (evil-execute-repeat-info (cdr evil-insert-repeat-info)))))))))) ;;; Visual state diff --git a/evil-tests.el b/evil-tests.el index 9e8f8589..ad0df818 100644 --- a/evil-tests.el +++ b/evil-tests.el @@ -8286,14 +8286,13 @@ maybe we need one line more with some text\n" "alpha bravo alpha charlie [a]lpha"))))) (ert-deftest evil-test-ex-search-motion () + "Test that Ex forward search, as a motion, can be repeated." :tags '(evil ex search) (evil-without-display (evil-select-search-module 'evil-search-module 'evil-search) - (ert-info ("Ex forward search, as a motion, can be repeated") - (evil-test-buffer - "alpha [b]ravo charlie delta golf hotel charlie india" - ("c/charlie" [return] "replacement " [escape] "4w.") - "alpha replacement charlie delta golf replacement[ ]charlie india")))) + (evil-test-buffer "alpha [b]ravo charlie delta golf hotel charlie india" + ("c/charlie" [return] "replacement " [escape] "4w.") + "alpha replacement charlie delta golf replacement[ ]charlie india"))) (ert-deftest evil-test-ex-search-next+previous-match () :tags '(evil ex search) diff --git a/evil-vars.el b/evil-vars.el index 87442465..2d8532a1 100644 --- a/evil-vars.el +++ b/evil-vars.el @@ -1570,14 +1570,6 @@ character argument for some commands, e.g. `evil-replace'.") (defvar evil-repeat-ring (make-ring 10) "A ring of repeat-informations to repeat the last command.") -(defvar evil-repeat-types - '((t . evil-repeat-keystrokes) - (change . evil-repeat-changes) - (motion . evil-repeat-motion) - (insert-at-point . evil-repeat-insert-at-point) - (ignore . nil)) - "An alist of defined repeat-types.") - (defvar evil-recording-repeat nil "Whether we are recording a repeat.") @@ -1585,7 +1577,7 @@ character argument for some commands, e.g. `evil-replace'.") "Whether we are recording the current command for repeat.") (defvar evil-repeat-changes nil - "Accumulated buffer changes for changed-based commands.") + "Accumulated buffer changes in reverse order for change-tracking commands.") (defvar evil-repeat-info nil "Information accumulated during current repeat.") @@ -1595,8 +1587,7 @@ character argument for some commands, e.g. `evil-replace'.") If the buffer is changed, the repeat is cancelled.") (defvar evil-repeat-pos nil - "The position of point at the beginning of an change-tracking - editing command.") + "The point position at the start of a change-tracking command.") (defvar evil-repeat-keys nil "The keys that invoked the current command.")