branch: elpa/evil
commit bb7e4bf95f4f9e97af70b270712a7ceb92a29907
Author: Axel Forsman <axels...@gmail.com>
Commit: Axel Forsman <axels...@gmail.com>
    Make Ex hooks not be permanent
---
 evil-common.el |  14 +--
 evil-ex.el     | 264 +++++++++++++++++++++++++--------------------------------
 evil-search.el |   2 +-
 3 files changed, 123 insertions(+), 157 deletions(-)

diff --git a/evil-common.el b/evil-common.el
index f0f3b4d216..8db8d3c8bf 100644
--- a/evil-common.el
+++ b/evil-common.el
@@ -2022,18 +2022,17 @@ sometimes moving point, so `C-a' `C-w' etc. would miss 
their intended target.")
 
 (defun evil-ex-remove-default ()
   "Remove the default text shown in the ex minibuffer.
-When ex starts, the previous command is shown enclosed in
+When Ex starts, the previous command is shown enclosed in
 parenthesis. This function removes this text when the first key
 is pressed."
   (when (and (not (eq this-command 'exit-minibuffer))
              (/= (minibuffer-prompt-end) (point-max)))
-    (if (eq this-command 'evil-ex-delete-backward-char)
-        (setq this-command 'ignore))
+    (when (eq this-command 'evil-ex-delete-backward-char)
+      (setq this-command 'ignore))
     (if (eq this-original-command 'evil-paste-from-register)
         (setq evil-paste-clear-minibuffer-first t)
       (delete-minibuffer-contents)))
-  (remove-hook 'pre-command-hook #'evil-ex-remove-default))
-(put 'evil-ex-remove-default 'permanent-local-hook t)
+  (remove-hook 'pre-command-hook #'evil-ex-remove-default t))
 
 (defun evil-get-register (register &optional noerror)
   "Return contents of REGISTER.
@@ -2137,8 +2136,9 @@ The following special registers are supported.
               (let ((enable-recursive-minibuffers t))
                 (setq evil-last-=-register-input
                       (minibuffer-with-setup-hook
-                          (lambda () (when evil-last-=-register-input
-                                       (add-hook 'pre-command-hook 
#'evil-ex-remove-default)))
+                          (lambda ()
+                            (when evil-last-=-register-input
+                              (add-hook 'pre-command-hook 
#'evil-ex-remove-default nil t)))
                         (read-from-minibuffer
                          "="
                          (and evil-last-=-register-input
diff --git a/evil-ex.el b/evil-ex.el
index 7606b6065e..2abefb57ec 100644
--- a/evil-ex.el
+++ b/evil-ex.el
@@ -136,11 +136,11 @@ left recursion.  See `evil-parser' for a detailed 
explanation
 of the syntax.")
 
 (defvar evil-ex-echo-overlay nil
-  "Overlay used for displaying info messages during ex.")
+  "Overlay used for displaying info messages during Ex.")
 
 (defun evil-ex-p ()
   "Whether Ex is currently active."
-  (and evil-ex-current-buffer t))
+  (when evil-ex-current-buffer t))
 
 (evil-define-command evil-ex (&optional initial-input)
   "Enter an Ex command.
@@ -156,31 +156,29 @@ is appended to the line."
   :keep-visual t
   :repeat abort
   (interactive
-   (list
-    (let ((s (concat
-              (cond
-               ((and (evil-visual-state-p)
-                     evil-ex-visual-char-range
-                     (memq (evil-visual-type) '(inclusive exclusive)))
-                "`<,`>")
-               ((evil-visual-state-p)
-                "'<,'>")
-               (current-prefix-arg
-                (let ((arg (prefix-numeric-value current-prefix-arg)))
-                  (cond ((< arg 0) (setq arg (1+ arg)))
-                        ((> arg 0) (setq arg (1- arg))))
-                  (if (= arg 0) "."
-                    (format ".,.%+d" arg)))))
-              evil-ex-initial-input)))
-      (and (> (length s) 0) s))))
+   (let ((s (concat
+             (cond
+              ((and (evil-visual-state-p)
+                    evil-ex-visual-char-range
+                    (memq (evil-visual-type) '(inclusive exclusive)))
+               "`<,`>")
+              ((evil-visual-state-p) "'<,'>")
+              (current-prefix-arg
+               (let ((arg (prefix-numeric-value current-prefix-arg)))
+                 (cond ((< arg 0) (setq arg (1+ arg)))
+                       ((> arg 0) (setq arg (1- arg))))
+                 (if (= arg 0) "."
+                   (format ".,.%+d" arg)))))
+             evil-ex-initial-input)))
+     (list (when (> (length s) 0) s))))
   (let ((evil-ex-current-buffer (current-buffer))
         (evil-ex-previous-command (unless initial-input
-                                    (car-safe evil-ex-history)))
-        evil-ex-argument-handler
-        evil-ex-info-string
-        result)
+                                    (car evil-ex-history)))
+        evil-ex-argument-handler result)
     (minibuffer-with-setup-hook
-        (if initial-input #'evil-ex-setup-and-update #'evil-ex-setup)
+        (lambda ()
+          (evil-ex-setup)
+          (when initial-input (evil-ex-update)))
       (setq result
             (read-from-minibuffer
              ":"
@@ -191,8 +189,7 @@ is appended to the line."
              evil-ex-completion-map
              nil
              'evil-ex-history
-             (when evil-want-empty-ex-last-command
-               evil-ex-previous-command)
+             (when evil-want-empty-ex-last-command evil-ex-previous-command)
              t)))
     (evil-ex-execute result)))
 
@@ -206,21 +203,19 @@ is appended to the line."
   (evil-ex-update nil nil nil result)
   ;; execute command
   (unless (zerop (length result))
-    (if evil-ex-expression
-        (eval evil-ex-expression)
-      (user-error "Ex: syntax error"))))
+    (eval (or evil-ex-expression (user-error "Ex: syntax error")))))
 
 (defun evil-ex-delete-backward-char ()
   "Close the minibuffer if it is empty.
 Otherwise behaves like `delete-backward-char'."
   (interactive)
   (call-interactively
-   (if (zerop (length (minibuffer-contents)))
+   (if (zerop (length (minibuffer-contents-no-properties)))
        #'abort-recursive-edit
      #'delete-backward-char)))
 
 (defun evil-ex-abort ()
-  "Cancel ex state when another buffer is selected."
+  "Cancel Ex state when another buffer is selected."
   (unless (or (minibufferp)
               (memq this-command '(mouse-drag-region choose-completion)))
     (abort-recursive-edit)))
@@ -232,41 +227,34 @@ Otherwise behaves like `delete-backward-char'."
   (insert result)
   (exit-minibuffer))
 
+(defun evil--ex-elisp-p ()
+  "Return whether an Elisp expression is being entered on the Ex command line."
+  (string-prefix-p "(" (minibuffer-contents-no-properties)))
+
 (defun evil-ex-elisp-completion-at-point ()
   "Complete an `evil-ex' Elisp expression."
-  (when (and (fboundp 'elisp-completion-at-point)
-             (string-prefix-p "(" (minibuffer-contents-no-properties)))
-    (elisp-completion-at-point)))
+  (and (evil--ex-elisp-p)
+       (fboundp 'elisp-completion-at-point)
+       (elisp-completion-at-point)))
 
 (defun evil-ex-setup ()
   "Initialize Ex minibuffer.
-This function registers several hooks that are used for the
-interactive actions during ex state."
+This function registers hooks that are used for the interactive
+actions during Ex state."
   (add-hook 'post-command-hook #'evil-ex-abort)
   (add-hook 'after-change-functions #'evil-ex-update nil t)
   (add-hook 'minibuffer-exit-hook #'evil-ex-teardown nil t)
   (when evil-ex-previous-command
-    (add-hook 'pre-command-hook #'evil-ex-remove-default))
-  (remove-hook 'minibuffer-setup-hook #'evil-ex-setup)
-  (with-no-warnings
-    (make-variable-buffer-local 'completion-at-point-functions))
-  (setq completion-at-point-functions
-        '(evil-ex-elisp-completion-at-point
-          evil-ex-command-completion-at-point
-          evil-ex-argument-completion-at-point)))
-(put 'evil-ex-setup 'permanent-local-hook t)
-
-(defun evil-ex-setup-and-update ()
-  "Initialize Ex minibuffer with `evil-ex-setup', then call `evil-ex-update'."
-  (evil-ex-setup)
-  (evil-ex-update))
+    (add-hook 'pre-command-hook #'evil-ex-remove-default nil t))
+  (set (make-local-variable 'completion-at-point-functions)
+       '(evil-ex-elisp-completion-at-point
+         evil-ex-command-completion-at-point
+         evil-ex-argument-completion-at-point)))
 
 (defun evil-ex-teardown ()
   "Deinitialize Ex minibuffer.
 Clean up everything set up by `evil-ex-setup'."
   (remove-hook 'post-command-hook #'evil-ex-abort)
-  (remove-hook 'minibuffer-exit-hook #'evil-ex-teardown t)
-  (remove-hook 'after-change-functions #'evil-ex-update t)
   (when evil-ex-argument-handler
     (let ((runner (evil-ex-argument-handler-runner
                    evil-ex-argument-handler)))
@@ -274,27 +262,25 @@ Clean up everything set up by `evil-ex-setup'."
         (funcall runner 'stop)))))
 (put 'evil-ex-teardown 'permanent-local-hook t)
 
-(defun evil-ex-update (&optional beg end len string)
+(defun evil-ex-update (&optional beg _end _len string)
   "Update Ex variables when the minibuffer changes.
 This function is usually called from `after-change-functions'
 hook. If BEG is non-nil (which is the case when called from
 `after-change-functions'), then an error description is shown
 in case of incomplete or unknown commands."
   (let* ((prompt (minibuffer-prompt-end))
-         (string (or string (buffer-substring prompt (point-max))))
+         (string (or string (minibuffer-contents-no-properties)))
          arg bang cmd count expr func handler range tree type)
     (if (and (eq this-command #'self-insert-command)
              (commandp (setq cmd (lookup-key evil-ex-map string))))
         (progn
           (setq evil-ex-expression `(call-interactively #',cmd))
-          (when (minibufferp)
-            (exit-minibuffer)))
+          (when (minibufferp) (exit-minibuffer)))
       (setq cmd nil)
       ;; store the buffer position of each character
       ;; as the `ex-index' text property
       (dotimes (i (length string))
-        (add-text-properties
-         i (1+ i) (list 'ex-index (+ i prompt)) string))
+        (put-text-property i (1+ i) 'ex-index (+ i prompt) string))
       (with-current-buffer evil-ex-current-buffer
         (setq tree (evil-ex-parse string t)
               expr (evil-ex-parse string))
@@ -320,8 +306,7 @@ in case of incomplete or unknown commands."
         (cond
          ;; update argument-handler
          (func
-          (when (setq type (evil-get-command-property
-                            func :ex-arg))
+          (when (setq type (evil-get-command-property func :ex-arg))
             (setq handler (cdr-safe
                            (assoc type
                                   evil-ex-argument-types))))
@@ -339,47 +324,45 @@ in case of incomplete or unknown commands."
                              (evil-ex-argument-handler-runner
                               evil-ex-argument-handler))))
             (when runner (funcall runner 'update evil-ex-argument))))
+         ;; show error message only when called from `after-change-functions'
          (beg
-          ;; show error message only when called from `after-change-functions'
-          (let ((n (length (all-completions cmd (evil-ex-completion-table)))))
+          (let ((prefix (try-completion cmd (evil-ex-completion-table))))
             (cond
-             ((> n 1) (evil-ex-echo "Incomplete command"))
-             ((= n 0) (evil-ex-echo "Unknown command"))))))))))
-(put 'evil-ex-update 'permanent-local-hook t)
+             ((stringp prefix) (evil-ex-echo "Incomplete command"))
+             ((null prefix) (evil-ex-echo "Unknown command"))))))))))
 
 (defun evil-ex-echo (string &rest args)
   "Display a message after the current Ex command."
   (with-selected-window (minibuffer-window)
-    (with-current-buffer (window-buffer (minibuffer-window))
-      (unless (or evil-no-display
-                  (zerop (length string)))
-        (let ((string (format " [%s]" (apply #'format string args)))
-              (ov (or evil-ex-echo-overlay
-                      (setq evil-ex-echo-overlay (make-overlay (point-min) 
(point-max) nil t t))))
-              after-change-functions before-change-functions)
-          (put-text-property 0 (length string) 'face 'evil-ex-info string)
-          ;; The following 'trick' causes point to be shown before the
-          ;; message instead behind. It is shamelessly stolen from the
-          ;; implementation of `minibuffer-message`.
-          (put-text-property 0 1 'cursor t string)
-          (move-overlay ov (point-max) (point-max))
-          (overlay-put ov 'after-string string)
-          (add-hook 'pre-command-hook #'evil--ex-remove-echo-overlay nil 
t))))))
+    (unless (or evil-no-display (zerop (length string)))
+      (let ((string (format " [%s]" (apply #'format string args)))
+            (ov (or evil-ex-echo-overlay
+                    (setq evil-ex-echo-overlay (make-overlay (point-min) 
(point-max) nil t t))))
+            after-change-functions before-change-functions)
+        (put-text-property 0 (length string) 'face 'evil-ex-info string)
+        ;; The following "trick" causes point to be shown before the
+        ;; message instead of behind. It is shamelessly stolen from
+        ;; the implementation of `minibuffer-message'.
+        (put-text-property 0 1 'cursor t string)
+        (move-overlay ov (point-max) (point-max))
+        (overlay-put ov 'after-string string)
+        (add-hook 'pre-command-hook #'evil--ex-remove-echo-overlay nil t)))))
 
 (defun evil--ex-remove-echo-overlay ()
-  "Remove echo overlay from ex minibuffer."
+  "Remove echo overlay from Ex minibuffer."
   (when evil-ex-echo-overlay
     (delete-overlay evil-ex-echo-overlay)
     (setq evil-ex-echo-overlay nil))
-  (remove-hook 'pre-command-hook 'evil--ex-remove-echo-overlay t))
+  (remove-hook 'pre-command-hook #'evil--ex-remove-echo-overlay t))
 
 (defun evil-ex-completion ()
-  "Complete the current ex command or argument."
+  "Complete the current Ex command or argument."
   (interactive)
   (let (after-change-functions)
     (evil-ex-update)
     (completion-at-point)
-    (remove-text-properties (minibuffer-prompt-end) (point-max) '(face nil 
evil))))
+    (remove-list-of-text-properties
+     (minibuffer-prompt-end) (point-max) '(face evil))))
 
 (defun evil-ex-command-completion-at-point ()
   (let ((beg (if evil-ex-cmd
@@ -474,15 +457,14 @@ in case of incomplete or unknown commands."
                       (point)))
              (end (1+ (or (and evil-ex-argument
                                (get-text-property (1- (length 
evil-ex-argument))
-                                                  'ex-index
-                                                  evil-ex-argument))
+                                                  'ex-index evil-ex-argument))
                           (1- (point)))))
              (binding (evil-ex-completed-binding evil-ex-cmd))
              (arg-type (evil-get-command-property binding :ex-arg))
              (arg-handler (assoc arg-type evil-ex-argument-types))
-             (completer (and arg-handler
-                             (evil-ex-argument-handler-completer
-                              (cdr arg-handler)))))
+             (completer (when arg-handler
+                          (evil-ex-argument-handler-completer
+                           (cdr arg-handler)))))
         (when completer
           (if (eq (car completer) 'collection)
               (list beg end (cdr completer))
@@ -492,13 +474,12 @@ in case of incomplete or unknown commands."
 
 (defun evil-ex-define-cmd (cmd function)
   "Bind the function FUNCTION to the command CMD."
-  (save-match-data
-    (if (string-match "^[^][]*\\(\\[\\(.*\\)\\]\\)[^][]*$" cmd)
-        (let ((abbrev (replace-match "" nil t cmd 1))
-              (full (replace-match "\\2" nil nil cmd 1)))
-          (evil--add-to-alist 'evil-ex-commands full function)
-          (evil--add-to-alist 'evil-ex-commands abbrev full))
-      (evil--add-to-alist 'evil-ex-commands cmd function))))
+  (if (string-match "^[^][]*\\(\\[\\(.*\\)\\]\\)[^][]*$" cmd)
+      (let ((abbrev (replace-match "" nil t cmd 1))
+            (full (replace-match "\\2" nil nil cmd 1)))
+        (evil--add-to-alist 'evil-ex-commands full function)
+        (evil--add-to-alist 'evil-ex-commands abbrev full))
+    (evil--add-to-alist 'evil-ex-commands cmd function)))
 
 (defun evil-ex-make-argument-handler (runner completer)
   (list runner completer))
@@ -612,16 +593,13 @@ works accordingly."
 
 (defun evil-ex-binding (command &optional noerror)
   "Return the final binding of COMMAND."
-  (let ((binding (save-match-data
-                   (string-match "^\\(.+?\\)\\!?$" command)
-                   (match-string 1 command))))
-    (while (progn
-             (setq binding (cdr (assoc binding evil-ex-commands)))
-             (stringp binding)))
+  (string-match "^\\(.+?\\)\\!?$" command)
+  (let ((binding (match-string 1 command)))
+    (while (stringp
+            (setq binding (cdr (assoc binding evil-ex-commands)))))
     (unless binding
-      (setq binding (intern command)))
+      (setq binding (intern-soft command)))
     (if (commandp binding)
-        ;; check for remaps
         (or (command-remapping binding) binding)
       (unless noerror
         (user-error "Unknown command: `%s'" command)))))
@@ -684,15 +662,14 @@ This function interprets special file names like # and %."
           (let ((binding (evil-ex-binding evil-ex-cmd)))
             (unless (eq binding #'evil-ex-repeat)
               (setq hist nil)
-              (if evil-ex-expression
-                  (eval evil-ex-expression)
-                (user-error "Ex: syntax error")))))))))
+              (eval (or evil-ex-expression
+                        (user-error "Ex: syntax error"))))))))))
 
 (defun evil-ex-call-command (range command argument)
   "Execute the given command COMMAND."
   (let* ((count (when (numberp range) range))
          (range (when (evil-range-p range) range))
-         (bang (and (save-match-data (string-match ".!$" command)) t))
+         (bang (when (string-match-p ".!$" command) t))
          (evil-ex-point (point))
          (evil-ex-range
           (or range (and count (evil-ex-range count count))))
@@ -701,7 +678,7 @@ This function interprets special file names like # and %."
                           (if (evil-visual-state-p)
                               (min (point) (or (mark) most-positive-fixnum))
                             (point))))
-         (evil-ex-bang (and bang t))
+         (evil-ex-bang bang)
          (evil-ex-argument (copy-sequence argument))
          (evil-this-type (evil-type evil-ex-range))
          (current-prefix-arg count)
@@ -709,11 +686,11 @@ This function interprets special file names like # and %."
     (when (stringp evil-ex-argument)
       (set-text-properties
        0 (length evil-ex-argument) nil evil-ex-argument))
+    (when evil-ex-reverse-range
+      (setq evil-ex-reverse-range nil)
+      (unless (y-or-n-p "Backward range given, OK to swap? ")
+        (user-error "")))
     (let ((buf (current-buffer)))
-      (when evil-ex-reverse-range
-        (setq evil-ex-reverse-range nil)
-        (unless (y-or-n-p "Backward range given, OK to swap? ")
-          (user-error "")))
       (unwind-protect
           (cond
            ((not evil-ex-range)
@@ -725,12 +702,8 @@ This function interprets special file names like # and %."
            (t
             ;; set visual selection to match the region if an explicit
             ;; range has been specified
-            (let ((ex-range (evil-copy-range evil-ex-range))
-                  beg end)
-              (evil-expand-range ex-range)
-              (setq beg (evil-range-beginning ex-range)
-                    end (evil-range-end ex-range))
-              (evil-sort beg end)
+            (cl-destructuring-bind (beg end &rest)
+                (evil-expand-range evil-ex-range t)
               (setq this-command evil-ex-command)
               (run-hooks 'pre-command-hook)
               (set-mark end)
@@ -754,7 +727,7 @@ This function interprets special file names like # and %."
 
 (defun evil-ex-current-line ()
   "Return the line number of the current line."
-  (line-number-at-pos (point)))
+  (line-number-at-pos))
 
 (defun evil-ex-last-line ()
   "Return the line number of the last line."
@@ -768,9 +741,7 @@ This function interprets special file names like # and %."
   "Return the first and last position of the current range."
   (when (and end-line (< end-line beg-line))
     (setq evil-ex-reverse-range t)
-    (let ((beg-line* beg-line))
-      (setq beg-line end-line
-            end-line beg-line*)))
+    (evil-swap beg-line end-line))
   (evil-range
    (evil-line-position beg-line)
    (evil-line-position (or end-line beg-line) -1)
@@ -779,7 +750,7 @@ This function interprets special file names like # and %."
 
 (defun evil-ex-full-range ()
   "Return a range encompassing the whole buffer."
-  (evil-range (point-min) (point-max) 'line))
+  (evil-range (point-min) (point-max) 'line :expanded t))
 
 (defun evil-ex-last-visual-range ()
   "Return a linewise range of the last visual selection."
@@ -788,18 +759,15 @@ This function interprets special file names like # and %."
 (defun evil-ex-marker (marker)
   "Return MARKER's line number in the current buffer.
 Signal an error if MARKER is in a different buffer."
-  (when (stringp marker)
-    (setq marker (aref marker 0)))
-  (setq marker (evil-get-marker marker))
+  (setq marker (evil-get-marker
+                (if (stringp marker) (aref marker 0) marker)))
   (if (numberp marker)
       (line-number-at-pos marker)
     (user-error "Ex does not support markers in other files")))
 
 (defun evil-ex-char-marker-range (beg end)
-  (when (stringp beg) (setq beg (aref beg 0)))
-  (when (stringp end) (setq end (aref end 0)))
-  (setq beg (evil-get-marker beg)
-        end (evil-get-marker end))
+  (setq beg (evil-get-marker (if (stringp beg) (aref beg 0) beg))
+        end (evil-get-marker (if (stringp end) (aref end 0) end)))
   (if (and (numberp beg) (numberp end))
       (evil-expand-range
        (evil-range beg end
@@ -818,15 +786,14 @@ Return the line number of the match."
   (setq evil-ex-search-pattern (evil-ex-make-search-pattern pattern)
         evil-ex-search-direction 'forward)
   (condition-case err
-      (save-match-data
-        (save-excursion
-          (set-text-properties 0 (length pattern) nil pattern)
-          (evil-move-end-of-line)
-          (if (re-search-forward pattern nil t)
-              (line-number-at-pos (1- (match-end 0)))
-            (goto-char (point-min))
-            (and (re-search-forward pattern nil t)
-                 (line-number-at-pos (1- (match-end 0)))))))
+      (save-excursion
+        (set-text-properties 0 (length pattern) nil pattern)
+        (evil-move-end-of-line)
+        (when (or (re-search-forward pattern nil t)
+                  (progn
+                    (goto-char (point-min))
+                    (re-search-forward pattern nil t)))
+          (line-number-at-pos (1- (match-end 0)))))
     (invalid-regexp
      (evil-ex-echo (cadr err))
      nil)))
@@ -839,15 +806,14 @@ Return the line number of the match."
   (setq evil-ex-search-pattern (evil-ex-make-search-pattern pattern)
         evil-ex-search-direction 'backward)
   (condition-case err
-      (save-match-data
-        (save-excursion
-          (set-text-properties 0 (length pattern) nil pattern)
-          (evil-move-beginning-of-line)
-          (if (re-search-backward pattern nil t)
-              (line-number-at-pos (match-beginning 0))
-            (goto-char (point-max))
-            (and (re-search-backward pattern nil t)
-                 (line-number-at-pos (match-beginning 0))))))
+      (save-excursion
+        (set-text-properties 0 (length pattern) nil pattern)
+        (evil-move-beginning-of-line)
+        (when (or (re-search-backward pattern nil t)
+                  (progn
+                    (goto-char (point-max))
+                    (re-search-backward pattern nil t)))
+          (line-number-at-pos (match-beginning 0))))
     (invalid-regexp
      (evil-ex-echo (cadr err))
      nil)))
diff --git a/evil-search.el b/evil-search.el
index 2a79a9d8d3..a662a730dc 100644
--- a/evil-search.el
+++ b/evil-search.el
@@ -1094,7 +1094,7 @@ current search result."
 
 (defun evil-ex-search-setup ()
   "Hook to initialize the minibuffer for ex search."
-  (add-hook 'pre-command-hook #'evil-ex-remove-default))
+  (add-hook 'pre-command-hook #'evil-ex-remove-default nil t))
 
 (defun evil-ex-start-search (direction count)
   "Start a new search in a certain DIRECTION."

Reply via email to