]> code.delx.au - gnu-emacs-elpa/blobdiff - ivy.el
Add the '!' behavior into `ivy--regex-ignore-order'
[gnu-emacs-elpa] / ivy.el
diff --git a/ivy.el b/ivy.el
index af786c033e2aee3987f27d8efc63ae3e3b34291e..6ff1e876bb68f752fac365acb17227e7b5a17a58 100644 (file)
--- a/ivy.el
+++ b/ivy.el
   "Incremental vertical completion."
   :group 'convenience)
 
+(defgroup ivy-faces nil
+  "Font-lock faces for `ivy'."
+  :group 'ivy)
+
 (defface ivy-current-match
   '((((class color) (background light))
      :background "#1a4b77" :foreground "white")
     (((class color) (background dark))
      :background "#65a7e2" :foreground "black"))
-  "Face used by Ivy for highlighting first match.")
+  "Face used by Ivy for highlighting the current match.")
+
+(defface ivy-minibuffer-match-face-1
+  '((((class color) (background light))
+     :background "#d3d3d3")
+    (((class color) (background dark))
+     :background "#555555"))
+  "The background face for `ivy' minibuffer matches.")
+
+(defface ivy-minibuffer-match-face-2
+  '((((class color) (background light))
+     :background "#e99ce8" :weight bold)
+    (((class color) (background dark))
+     :background "#777777" :weight bold))
+  "Face for `ivy' minibuffer matches modulo 1.")
+
+(defface ivy-minibuffer-match-face-3
+  '((((class color) (background light))
+     :background "#bbbbff" :weight bold)
+    (((class color) (background dark))
+     :background "#7777ff" :weight bold))
+  "Face for `ivy' minibuffer matches modulo 2.")
+
+(defface ivy-minibuffer-match-face-4
+  '((((class color) (background light))
+     :background "#ffbbff" :weight bold)
+    (((class color) (background dark))
+     :background "#8a498a" :weight bold))
+  "Face for `ivy' minibuffer matches modulo 3.")
 
 (defface ivy-confirm-face
   '((t :foreground "ForestGreen" :inherit minibuffer-prompt))
-  "Face used by Ivy to issue a confirmation prompt.")
+  "Face used by Ivy for a confirmation prompt.")
 
 (defface ivy-match-required-face
   '((t :foreground "red" :inherit minibuffer-prompt))
-  "Face used by Ivy to issue a match required prompt.")
+  "Face used by Ivy for a match required prompt.")
+
+(setcdr (assoc load-file-name custom-current-group-alist) 'ivy)
 
 (defface ivy-subdir
   '((t (:inherit 'dired-directory)))
   '((t (:foreground "#110099")))
   "Face used by Ivy for highlighting remotes in the alternatives.")
 
+(defface ivy-virtual
+  '((t :inherit font-lock-builtin-face))
+  "Face used by Ivy for matching virtual buffer names.")
+
 (defcustom ivy-height 10
   "Number of lines for the minibuffer window."
   :type 'integer)
 
 (defcustom ivy-count-format "%-4d "
-  "The style of showing the current candidate count for `ivy-read'.
-Set this to \"\" if you don't want the count.  You can also set
-it to e.g. \"(%d/%d) \" if you want to see both the candidate
-index and the candidate count."
+  "The style to use for displaying the current candidate count for `ivy-read'.
+Set this to \"\" to suppress the count visibility.
+Set this to \"(%d/%d) \" to display both the index and the count."
   :type '(choice
           (const :tag "Count disabled" "")
           (const :tag "Count matches" "%-4d ")
@@ -87,27 +124,27 @@ index and the candidate count."
           string))
 
 (defcustom ivy-wrap nil
-  "Whether to wrap around after the first and last candidate."
+  "When non-nil, wrap around after the first and the last candidate."
   :type 'boolean)
 
 (defcustom ivy-display-style (unless (version< emacs-version "24.5") 'fancy)
   "The style for formatting the minibuffer.
 
-By default, the matched strings will be copied as they are.
+By default, the matched strings are copied as is.
 
-With the fancy method, the matching parts of the regexp will be
-additionally highlighted, just like `swiper' does it.
+The fancy display style highlights matching parts of the regexp,
+a behavior similar to `swiper'.
 
 This setting depends on `add-face-text-property' - a C function
-available as of 24.5. It will behave poorly in earlier Emacs
-versions."
+available as of Emacs 24.5. Fancy style will render poorly in
+earlier versions of Emacs."
   :type '(choice
           (const :tag "Plain" nil)
           (const :tag "Fancy" fancy)))
 
 (defcustom ivy-on-del-error-function 'minibuffer-keyboard-quit
   "The handler for when `ivy-backward-delete-char' throws.
-This is usually meant as a quick exit out of the minibuffer."
+Usually a quick exit out of the minibuffer."
   :type 'function)
 
 (defcustom ivy-extra-directories '("../" "./")
@@ -214,7 +251,7 @@ This should eventually become a stack so that you could use
   "History list of candidates entered in the minibuffer.
 
 Maximum length of the history list is determined by the value
-of `history-length', which see.")
+of `history-length'.")
 
 (defvar ivy--directory nil
   "Current directory when completing file names.")
@@ -243,7 +280,7 @@ Otherwise, store nil.")
 
 (defvar ivy--prompt nil
   "Store the format-style prompt.
-When non-nil, it should contain one %d.")
+When non-nil, it should contain at least one %d.")
 
 (defvar ivy--prompt-extra ""
   "Temporary modifications to the prompt.")
@@ -463,7 +500,7 @@ When ARG is t, exit with current text, ignoring the candidates."
          (setq res (cl-delete-duplicates res :test #'equal))
          (let* ((old-ivy-last ivy-last)
                 (enable-recursive-minibuffers t)
-                (host (ivy-read "Find File: "
+                (host (ivy-read "user@host: "
                                 (mapcar #'ivy-build-tramp-name res)
                                 :initial-input rest)))
            (setq ivy-last old-ivy-last)
@@ -662,12 +699,14 @@ If the input is empty, select the previous history element instead."
 
 (defun ivy--get-window (state)
   "Get the window from STATE."
-  (let ((window (ivy-state-window state)))
-    (if (window-live-p window)
-        window
-      (if (= (length (window-list)) 1)
-          (selected-window)
-        (next-window)))))
+  (if (ivy-state-p state)
+      (let ((window (ivy-state-window state)))
+        (if (window-live-p window)
+            window
+          (if (= (length (window-list)) 1)
+              (selected-window)
+            (next-window))))
+    (selected-window)))
 
 (defun ivy--actionp (x)
   "Return non-nil when X is a list of actions."
@@ -925,11 +964,11 @@ Prioritize directories."
   "An alist of sorting functions for each collection function.
 Interactive functions that call completion fit in here as well.
 
-For each entry, nil means no sorting.  It's very useful to turn
-off the sorting for functions that have candidates in the natural
-buffer order, like `org-refile' or `Man-goto-section'.
+Nil means no sorting, which is useful to turn off the sorting for
+functions that have candidates in the natural buffer order, like
+`org-refile' or `Man-goto-section'.
 
-The entry associated to t is used for all fall-through cases.
+The entry associated with t is used for all fall-through cases.
 
 See also `ivy-sort-max-size'."
   :type
@@ -947,22 +986,30 @@ See also `ivy-sort-max-size'."
   '((swiper . ivy-recompute-index-swiper)
     (swiper-multi . ivy-recompute-index-swiper)
     (counsel-git-grep . ivy-recompute-index-swiper)
+    (counsel-grep . ivy-recompute-index-swiper-async)
     (t . ivy-recompute-index-zero))
   "An alist of index recomputing functions for each collection function.
-When the input changes, calling the appropriate function will
-return an integer - the index of the matched candidate that
-should be selected.")
+When the input changes, the appropriate function returns an
+integer - the index of the matched candidate that should be
+selected.")
 
 (defvar ivy-re-builders-alist
   '((t . ivy--regex-plus))
   "An alist of regex building functions for each collection function.
-Each function should take a string and return a valid regex or a
-regex sequence (see below).
 
-The entry associated to t is used for all fall-through cases.
-Possible choices: `ivy--regex', `regexp-quote', `ivy--regex-plus'.
+Each key is (in order of priority):
+1. The actual collection function, e.g. `read-file-name-internal'.
+2. The symbol passed by :caller into `ivy-read'.
+3. `this-command'.
+4. t.
+
+Each value is a function that should take a string and return a
+valid regex or a regex sequence (see below).
 
-In case a function returns a list, it should look like this:
+Possible choices: `ivy--regex', `regexp-quote',
+`ivy--regex-plus', `ivy--regex-fuzzy'.
+
+If a function returns a list, it should format like this:
 '((\"matching-regexp\" . t) (\"non-matching-regexp\") ...).
 
 The matches will be filtered in a sequence, you can mix the
@@ -1005,50 +1052,56 @@ Directories come first."
         (push dir seq))
       seq)))
 
+(defvar ivy-recursive-restore t
+  "When non-nil, restore the above state when exiting the minibuffer.
+This variable is let-bound to nil by functions that take care of
+the restoring themselves.")
+
 ;;** Entry Point
 (cl-defun ivy-read (prompt collection
-                    &key predicate require-match initial-input
-                      history preselect keymap update-fn sort
-                      action unwind re-builder matcher dynamic-collection caller)
+                           &key predicate require-match initial-input
+                           history preselect keymap update-fn sort
+                           action unwind re-builder matcher dynamic-collection caller)
   "Read a string in the minibuffer, with completion.
 
-PROMPT is a string to prompt with; normally it ends in a colon
-and a space.  When PROMPT contains %d, it will be updated with
-the current number of matching candidates.  If % appears elsewhere
-in the PROMPT it should be quoted as %%.
-See also `ivy-count-format'.
+PROMPT is a format string, normally ending in a colon and a
+space; %d anywhere in the string is replaced by the current
+number of matching candidates. For the literal % character,
+escape it with %%. See also `ivy-count-format'.
 
-COLLECTION is a list of strings, or a function, or an alist, or a
-hash table.
+COLLECTION is either a list of strings, a function, an alist, or
+hash table.
 
-If INITIAL-INPUT is non-nil, insert it in the minibuffer initially.
+If INITIAL-INPUT is not nil, then insert that input in the
+minibuffer initially.
 
-KEYMAP is composed together with `ivy-minibuffer-map'.
+KEYMAP is composed with `ivy-minibuffer-map'.
 
-If PRESELECT is non-nil select the corresponding candidate out of
-the ones that match INITIAL-INPUT.
+If PRESELECT is not nil, then select the corresponding candidate
+out of the ones that match the INITIAL-INPUT.
 
 UPDATE-FN is called each time the current candidate(s) is changed.
 
-When SORT is t, refer to `ivy-sort-functions-alist' for sorting.
+When SORT is t, use `ivy-sort-functions-alist' for sorting.
 
-ACTION is a lambda to call after a result was selected. It should
-take a single argument, usually a string.
+ACTION is a lambda function to call after selecting a result. It
+takes a single string argument.
 
-UNWIND is a lambda to call before exiting.
+UNWIND is a lambda function to call before exiting.
 
-RE-BUILDER is a lambda that transforms text into a regex.
+RE-BUILDER is a lambda function to call to transform text into a
+regex pattern.
 
-MATCHER can completely override matching.
+MATCHER is to override matching.
 
-DYNAMIC-COLLECTION is a boolean that determines whether to update
-the list of candidates with each input by calling COLLECTION for
-the current input.
+DYNAMIC-COLLECTION is a boolean to specify if the list of
+candidates is updated after each input by calling COLLECTION.
 
 CALLER is a symbol to uniquely identify the caller to `ivy-read'.
-It's used in conjunction with COLLECTION to indentify which
-customizations should apply to the current completion session."
-  (let ((extra-actions (plist-get ivy--actions-list this-command)))
+It is used, along with COLLECTION, to determine which
+customizations apply to the current completion session."
+  (let ((extra-actions (append (plist-get ivy--actions-list t)
+                               (plist-get ivy--actions-list this-command))))
     (when extra-actions
       (setq action
             (if (functionp action)
@@ -1056,7 +1109,7 @@ customizations should apply to the current completion session."
                   ("o" ,action "default")
                   ,@extra-actions)
               (delete-dups (append action extra-actions))))))
-  (let ((recursive-ivy-last (and (window-minibuffer-p) ivy-last)))
+  (let ((recursive-ivy-last (and (active-minibuffer-window) ivy-last)))
     (setq ivy-last
           (make-ivy-state
            :prompt prompt
@@ -1080,41 +1133,45 @@ customizations should apply to the current completion session."
     (ivy--reset-state ivy-last)
     (prog1
         (unwind-protect
-             (minibuffer-with-setup-hook
-                 #'ivy--minibuffer-setup
-               (let* ((hist (or history 'ivy-history))
-                      (minibuffer-completion-table collection)
-                      (minibuffer-completion-predicate predicate)
-                      (resize-mini-windows (cond
-                                             ((display-graphic-p) nil)
-                                             ((null resize-mini-windows) 'grow-only)
-                                             (t resize-mini-windows)))
-                      (res (read-from-minibuffer
-                            prompt
-                            (ivy-state-initial-input ivy-last)
-                            (make-composed-keymap keymap ivy-minibuffer-map)
-                            nil
-                            hist)))
-                 (when (eq ivy-exit 'done)
-                   (let ((item (if ivy--directory
-                                   ivy--current
-                                 ivy-text)))
-                     (unless (equal item "")
-                       (set hist (cons (propertize item 'ivy-index ivy--index)
-                                       (delete item
-                                               (cdr (symbol-value hist)))))))
-                   res)))
+            (minibuffer-with-setup-hook
+                #'ivy--minibuffer-setup
+              (let* ((hist (or history 'ivy-history))
+                     (minibuffer-completion-table collection)
+                     (minibuffer-completion-predicate predicate)
+                     (resize-mini-windows (cond
+                                           ((display-graphic-p) nil)
+                                           ((null resize-mini-windows) 'grow-only)
+                                           (t resize-mini-windows))))
+                (read-from-minibuffer
+                 prompt
+                 (ivy-state-initial-input ivy-last)
+                 (make-composed-keymap keymap ivy-minibuffer-map)
+                 nil
+                 hist)
+                (when (eq ivy-exit 'done)
+                  (let ((item (if ivy--directory
+                                  ivy--current
+                                ivy-text)))
+                    (unless (equal item "")
+                      (set hist (cons (propertize item 'ivy-index ivy--index)
+                                      (delete item
+                                              (cdr (symbol-value hist))))))))
+                ivy--current))
           (remove-hook 'post-command-hook #'ivy--exhibit)
           (when (setq unwind (ivy-state-unwind ivy-last))
-            (funcall unwind)))
+            (funcall unwind))
+          (unless (eq ivy-exit 'done)
+            (when recursive-ivy-last
+              (ivy--reset-state (setq ivy-last recursive-ivy-last)))))
       (ivy-call)
-      (when recursive-ivy-last
+      (when (and recursive-ivy-last
+                 ivy-recursive-restore)
         (ivy--reset-state (setq ivy-last recursive-ivy-last))))))
 
 (defun ivy--reset-state (state)
   "Reset the ivy to STATE.
 This is useful for recursive `ivy-read'."
-  (let ((prompt (ivy-state-prompt state))
+  (let ((prompt (or (ivy-state-prompt state) ""))
         (collection (ivy-state-collection state))
         (predicate (ivy-state-predicate state))
         (history (ivy-state-history state))
@@ -1123,7 +1180,8 @@ This is useful for recursive `ivy-read'."
         (re-builder (ivy-state-re-builder state))
         (dynamic-collection (ivy-state-dynamic-collection state))
         (initial-input (ivy-state-initial-input state))
-        (require-match (ivy-state-require-match state)))
+        (require-match (ivy-state-require-match state))
+        (caller (ivy-state-caller state)))
     (unless initial-input
       (setq initial-input (cdr (assoc this-command
                                       ivy-initial-inputs-alist))))
@@ -1133,6 +1191,9 @@ This is useful for recursive `ivy-read'."
           (or re-builder
               (and (functionp collection)
                    (cdr (assoc collection ivy-re-builders-alist)))
+              (and caller
+                   (cdr (assoc caller ivy-re-builders-alist)))
+              (cdr (assoc this-command ivy-re-builders-alist))
               (cdr (assoc t ivy-re-builders-alist))
               'ivy--regex))
     (setq ivy--subexps 0)
@@ -1168,7 +1229,8 @@ This is useful for recursive `ivy-read'."
                            (equal initial-input default-directory)
                            (equal initial-input ""))
                  (setq coll (cons initial-input coll)))
-               (setq initial-input nil)))
+               (unless (ivy-state-action ivy-last)
+                 (setq initial-input nil))))
             ((eq collection 'internal-complete-buffer)
              (setq coll (ivy--buffer-list "" ivy-use-virtual-buffers)))
             ((or (functionp collection)
@@ -1192,27 +1254,32 @@ This is useful for recursive `ivy-read'."
       (when preselect
         (unless (or (and require-match
                          (not (eq collection 'internal-complete-buffer)))
+                    dynamic-collection
                     (let ((re (regexp-quote preselect)))
                       (cl-find-if (lambda (x) (string-match re x))
                                   coll)))
           (setq coll (cons preselect coll))))
       (setq ivy--old-re nil)
       (setq ivy--old-cands nil)
+      (when (integerp preselect)
+        (setq ivy--old-re "")
+        (setq ivy--index preselect))
       (when initial-input
         ;; Needed for anchor to work
         (setq ivy--old-cands coll)
         (setq ivy--old-cands (ivy--filter initial-input coll)))
       (setq ivy--all-candidates coll)
-      (setq ivy--index (or
-                        (and dynamic-collection
-                             ivy--index)
-                        (and preselect
-                             (ivy--preselect-index
-                              preselect
-                              (if initial-input
-                                  ivy--old-cands
-                                coll)))
-                        0)))
+      (unless (integerp preselect)
+        (setq ivy--index (or
+                          (and dynamic-collection
+                               ivy--index)
+                          (and preselect
+                               (ivy--preselect-index
+                                preselect
+                                (if initial-input
+                                    ivy--old-cands
+                                  coll)))
+                          0))))
     (setq ivy-exit nil)
     (setq ivy--default (or
                         (thing-at-point 'url)
@@ -1246,53 +1313,119 @@ This is useful for recursive `ivy-read'."
 ;;;###autoload
 (defun ivy-completing-read (prompt collection
                             &optional predicate require-match initial-input
-                              history def _inherit-input-method)
+                              history def inherit-input-method)
   "Read a string in the minibuffer, with completion.
 
-This is an interface that conforms to `completing-read', so that
-it can be used for `completing-read-function'.
+This interface conforms to `completing-read' and can be used for
+`completing-read-function'.
 
 PROMPT is a string to prompt with; normally it ends in a colon and a space.
 COLLECTION can be a list of strings, an alist, an obarray or a hash table.
 PREDICATE limits completion to a subset of COLLECTION.
-REQUIRE-MATCH is considered boolean.  See `completing-read'.
+REQUIRE-MATCH is specified with a boolean value.  See `completing-read'.
 INITIAL-INPUT is a string that can be inserted into the minibuffer initially.
-_HISTORY is ignored for now.
+HISTORY is a list of previously selected inputs.
 DEF is the default value.
-_INHERIT-INPUT-METHOD is ignored for now.
-
-The history, defaults and input-method arguments are ignored for now."
-  ;; See the doc of `completing-read'.
-  (when (consp history)
-    (when (numberp (cdr history))
-      (setq initial-input (nth (1- (cdr history))
-                               (symbol-value (car history)))))
-    (setq history (car history)))
-  (ivy-read (replace-regexp-in-string "%" "%%" prompt)
-            collection
-            :predicate predicate
-            :require-match require-match
-            :initial-input (if (consp initial-input)
-                               (car initial-input)
-                             (if (and (stringp initial-input)
-                                      (string-match "\\+" initial-input))
-                                 (replace-regexp-in-string
-                                  "\\+" "\\\\+" initial-input)
-                               initial-input))
-            :preselect (if (listp def) (car def) def)
-            :history history
-            :keymap nil
-            :sort
-            (let ((sort (assoc this-command ivy-sort-functions-alist)))
-              (if sort
-                  (cdr sort)
-                t))))
+INHERIT-INPUT-METHOD is currently ignored."
+  (if (memq this-command '(tmm-menubar tmm-shortcut))
+      (completing-read-default prompt collection
+                               predicate require-match
+                               initial-input history
+                               def inherit-input-method)
+    ;; See the doc of `completing-read'.
+    (when (consp history)
+      (when (numberp (cdr history))
+        (setq initial-input (nth (1- (cdr history))
+                                 (symbol-value (car history)))))
+      (setq history (car history)))
+    (ivy-read (replace-regexp-in-string "%" "%%" prompt)
+              collection
+              :predicate predicate
+              :require-match require-match
+              :initial-input (if (consp initial-input)
+                                 (car initial-input)
+                               (if (and (stringp initial-input)
+                                        (string-match "\\+" initial-input))
+                                   (replace-regexp-in-string
+                                    "\\+" "\\\\+" initial-input)
+                                 initial-input))
+              :preselect (if (listp def) (car def) def)
+              :history history
+              :keymap nil
+              :sort
+              (let ((sort (assoc this-command ivy-sort-functions-alist)))
+                (if sort
+                    (cdr sort)
+                  t)))))
+
+(defvar ivy-completion-beg nil
+  "Completion bounds start.")
+
+(defvar ivy-completion-end nil
+  "Completion bounds end.")
+
+(defun ivy-completion-in-region-action (str)
+  "Insert STR, erasing the previous one.
+The previous string is between `ivy-completion-beg' and `ivy-completion-end'."
+  (when (stringp str)
+    (with-ivy-window
+      (when ivy-completion-beg
+        (delete-region
+         ivy-completion-beg
+         ivy-completion-end))
+      (setq ivy-completion-beg
+            (move-marker (make-marker) (point)))
+      (insert str)
+      (setq ivy-completion-end
+            (move-marker (make-marker) (point))))))
+
+(defun ivy-completion-common-length (str)
+  "Return the length of the first 'completions-common-part face in STR."
+  (let ((pos 0)
+        (len (length str)))
+    (while (and (<= pos len)
+                (let ((prop (get-text-property pos 'face str)))
+                  (not (eq 'completions-common-part
+                           (if (listp prop) (car prop) prop)))))
+      (setq pos (1+ pos)))
+    (if (< pos len)
+        (or (next-single-property-change pos 'face str) len)
+      0)))
+
+(defun ivy-completion-in-region (start end collection &optional predicate)
+  "An Ivy function suitable for `completion-in-region-function'."
+  (let* ((enable-recursive-minibuffers t)
+         (str (buffer-substring-no-properties start end))
+         (comps
+          (completion-all-completions str collection predicate (- end start))))
+    (if (null comps)
+        (message "No matches")
+      (nconc comps nil)
+      (setq ivy-completion-beg (- end (ivy-completion-common-length (car comps))))
+      (setq ivy-completion-end end)
+      (if (null (cdr comps))
+          (progn
+            (setf (ivy-state-window ivy-last) (selected-window))
+            (ivy-completion-in-region-action
+             (substring-no-properties
+              (car comps))))
+        (let* ((w (1+ (floor (log (length comps) 10))))
+               (ivy-count-format (and ivy-count-format
+                                      (format "%%-%dd " w))))
+          (and
+           (ivy-read (format "(%s): " str)
+                     ;; remove 'completions-first-difference face
+                     (mapcar #'substring-no-properties comps)
+                     :predicate predicate
+                     :action #'ivy-completion-in-region-action
+                     :require-match t)
+           t))))))
 
 ;;;###autoload
 (define-minor-mode ivy-mode
   "Toggle Ivy mode on or off.
-With ARG, turn Ivy mode on if arg is positive, off otherwise.
-Turning on Ivy mode will set `completing-read-function' to
+Turn Ivy mode on if ARG is positive, off otherwise.
+Turning on Ivy mode sets `completing-read-function' to
 `ivy-completing-read'.
 
 Global bindings:
@@ -1305,8 +1438,11 @@ Minibuffer bindings:
   :keymap ivy-mode-map
   :lighter " ivy"
   (if ivy-mode
-      (setq completing-read-function 'ivy-completing-read)
-    (setq completing-read-function 'completing-read-default)))
+      (progn
+        (setq completing-read-function 'ivy-completing-read)
+        (setq completion-in-region-function 'ivy-completion-in-region))
+    (setq completing-read-function 'completing-read-default)
+    (setq completion-in-region-function 'completion--in-region)))
 
 (defun ivy--preselect-index (preselect candidates)
   "Return the index of PRESELECT in CANDIDATES."
@@ -1358,7 +1494,7 @@ This allows to \"quote\" N spaces by inputting N+1 spaces."
     (nreverse res)))
 
 (defun ivy--regex (str &optional greedy)
-  "Re-build regex from STR in case it has a space.
+  "Re-build regex pattern from STR in case it has a space.
 When GREEDY is non-nil, join words in a greedy way."
   (let ((hashed (unless greedy
                   (gethash str ivy--regex-hash))))
@@ -1386,51 +1522,54 @@ When GREEDY is non-nil, join words in a greedy way."
                             ".*?")))))
                     ivy--regex-hash)))))
 
-(defun ivy--regex-ignore-order (str)
-  "Re-build regex from STR by splitting it on spaces.
-Ignore the order of each group.
-
-ATTENTION: This is a proof of concept and may not work as you
-expect. It will match as many groups as there are in the STR, but
-won't make sure that the matches are distinct. For instance, if
-you type 'foo bar', anything that contains 'foo' and 'bar', 'bar'
-and 'foo' will be matched, but also anything that contains 'foo'
-twice or 'bar' twice. If you want to find all candidates containing 'foo' and
-'bar' in any order, consider using `ivy-restrict-to-matches' instead.
-"
+(defun ivy--regex-ignore-order--part (str &optional discard)
+  "Re-build regex from STR by splitting at spaces.
+Ignore the order of each group."
   (let* ((subs (split-string str " +" t))
          (len (length subs)))
     (cl-case len
-      (1
-       (setq ivy--subexps 0)
-       (car subs))
+      (0
+       "")
       (t
-       (setq ivy--subexps len)
-       (let ((all (mapconcat #'identity subs "\\|")))
-         (mapconcat
-          (lambda (x)
-            (if (string-match "\\`\\\\(.*\\\\)\\'" x)
-                x
-              (format "\\(%s\\)" x)))
-          (make-list len all)
-          ".*?"))))))
+       (mapcar (lambda (x) (cons x (not discard)))
+               subs)))))
+
+(defun ivy--regex-ignore-order (str)
+  "Re-build regex from STR by splitting at spaces.
+Ignore the order of each group. Everything before \"!\" should
+match. Everything after \"!\" should not match."
+  (let ((parts (split-string str "!" t)))
+    (cl-case (length parts)
+      (0
+       "")
+      (1
+       (if (string= (substring str 0 1) "!")
+           (list (cons "" t)
+                 (ivy--regex-ignore-order--part (car parts) t))
+         (ivy--regex-ignore-order--part (car parts))))
+      (2
+       (append
+        (ivy--regex-ignore-order--part (car parts))
+        (ivy--regex-ignore-order--part (cadr parts) t)))
+      (t (error "Unexpected: use only one !")))))
 
 (defun ivy--regex-plus (str)
   "Build a regex sequence from STR.
-Spaces are wild, everything before \"!\" should match.
-Everything after \"!\" should not match."
+Spaces are wild card characters, everything before \"!\" should
+match. Everything after \"!\" should not match."
   (let ((parts (split-string str "!" t)))
     (cl-case (length parts)
       (0
        "")
       (1
-       (ivy--regex (car parts)))
+       (if (string= (substring str 0 1) "!")
+           (list (cons "" t)
+                 (list (ivy--regex (car parts))))
+         (ivy--regex (car parts))))
       (2
-       (let ((res
-              (mapcar #'list
-                      (split-string (cadr parts) " " t))))
-         (cons (cons (ivy--regex (car parts)) t)
-               res)))
+       (cons
+        (cons (ivy--regex (car parts)) t)
+        (mapcar #'list (split-string (cadr parts) " " t))))
       (t (error "Unexpected: use only one !")))))
 
 (defun ivy--regex-fuzzy (str)
@@ -1478,7 +1617,7 @@ Insert .* between each char."
   "Update the prompt according to `ivy--prompt'."
   (when ivy--prompt
     (unless (memq this-command '(ivy-done ivy-alt-done ivy-partial-or-done
-                                 counsel-find-symbol))
+                                          counsel-find-symbol))
       (setq ivy--prompt-extra ""))
     (let (head tail)
       (if (string-match "\\(.*\\): \\'" ivy--prompt)
@@ -1534,7 +1673,7 @@ Insert .* between each char."
         (constrain-to-field nil (point-max))))))
 
 (defun ivy--set-match-props (str match props)
-  "Set STR text proprties that match MATCH to PROPS."
+  "Set STR text properties that match MATCH to PROPS."
   (when (string-match match str)
     (set-text-properties
      (match-beginning 0)
@@ -1633,18 +1772,20 @@ Should be run via minibuffer `post-command-hook'."
       (ivy--resize-minibuffer-to-fit))))
 
 (defun ivy--resize-minibuffer-to-fit ()
-  "Resize the minibuffer window so it has enough space to display
-all of the text contained in the minibuffer."
+  "Resize the minibuffer window size to fit the text in the minibuffer."
   (with-selected-window (minibuffer-window)
     (if (fboundp 'window-text-pixel-size)
         (let ((text-height (cdr (window-text-pixel-size)))
               (body-height (window-body-height nil t)))
           (when (> text-height body-height)
-            (window-resize nil (- text-height body-height) nil t t)))
-        (let ((text-height (count-screen-lines))
-              (body-height (window-body-height)))
-          (when (> text-height body-height)
-            (window-resize nil (- text-height body-height) nil t))))))
+            ;; Note: the size increment needs to be at least frame-char-height,
+            ;; otherwise resizing won't do anything.
+            (let ((delta (max (- text-height body-height) (frame-char-height))))
+              (window-resize nil delta nil t t))))
+      (let ((text-height (count-screen-lines))
+            (body-height (window-body-height)))
+        (when (> text-height body-height)
+          (window-resize nil (- text-height body-height) nil t))))))
 
 (declare-function colir-blend-face-background "ext:colir")
 
@@ -1681,7 +1822,7 @@ all of the text contained in the minibuffer."
 In any completion session, the case folding starts in auto:
 
 - when the input is all lower case, `case-fold-search' is t
-- otherwise it's nil.
+- otherwise nil.
 
 You can toggle this to make `case-fold-search' nil regardless of input."
   (interactive)
@@ -1692,6 +1833,25 @@ You can toggle this to make `case-fold-search' nil regardless of input."
   ;; reset cache so that the candidate list updates
   (setq ivy--old-re nil))
 
+(defun ivy--re-filter (re candidates)
+  "Return all RE matching CANDIDATES.
+RE is a list of cons cells, with a regexp car and a boolean cdr.
+When the cdr is t, the car must match.
+Otherwise, the car must not match."
+  (let ((re-list (if (stringp re) (list (cons re t)) re))
+        (res candidates))
+    (dolist (re re-list)
+      (setq res
+            (ignore-errors
+              (funcall
+               (if (cdr re)
+                   #'cl-remove-if-not
+                 #'cl-remove-if)
+               (let ((re-str (car re)))
+                 (lambda (x) (string-match re-str x)))
+               res))))
+    res))
+
 (defun ivy--filter (name candidates)
   "Return all items that match NAME in CANDIDATES.
 CANDIDATES are assumed to be static."
@@ -1724,21 +1884,14 @@ CANDIDATES are assumed to be static."
                           (lambda (x) (string-match re x))
                           ivy--old-cands)))
                       (t
-                       (let ((re-list (if (stringp re) (list (cons re t)) re))
-                             (res candidates))
-                         (dolist (re re-list)
-                           (setq res
-                                 (ignore-errors
-                                   (funcall
-                                    (if (cdr re)
-                                        #'cl-remove-if-not
-                                      #'cl-remove-if)
-                                    (let ((re-str (car re)))
-                                      (lambda (x) (string-match re-str x)))
-                                    res))))
-                         res)))))
+                       (ivy--re-filter re candidates)))))
         (ivy--recompute-index name re-str cands)
-        (setq ivy--old-re (if cands re-str ""))
+        (setq ivy--old-re
+              (if (eq ivy--regex-function 'ivy--regex-ignore-order)
+                  re
+                (if cands
+                    re-str
+                  "")))
         (setq ivy--old-cands (ivy--sort name cands))))))
 
 (defcustom ivy-sort-matches-functions-alist '((t . nil))
@@ -1765,7 +1918,7 @@ The alist VAL is a sorting function with the signature of
                 (nth 5 (file-attributes f1)))))))
 
 (defun ivy--sort (name candidates)
-  "Re-sort CANDIDATES according to NAME.
+  "Re-sort CANDIDATES by NAME.
 All CANDIDATES are assumed to match NAME."
   (let ((key (or (ivy-state-caller ivy-last)
                  (when (functionp (ivy-state-collection ivy-last))
@@ -1851,9 +2004,28 @@ Prefix matches to NAME are put ahead of the list."
             (cl-incf i))
           res)))))
 
+(defun ivy-recompute-index-swiper-async (_re-str cands)
+  (let ((tail (nthcdr ivy--index ivy--old-cands))
+        idx)
+    (if (and tail ivy--old-cands (not (equal "^" ivy--old-re)))
+        (progn
+          (while (and tail (null idx))
+            ;; Compare with `equal', since the collection is re-created
+            ;; each time with `split-string'
+            (setq idx (cl-position (pop tail) cands :test #'equal)))
+          (or idx 0))
+      ivy--index)))
+
 (defun ivy-recompute-index-zero (_re-str _cands)
   0)
 
+(defcustom ivy-minibuffer-faces
+  '(ivy-minibuffer-match-face-1
+    ivy-minibuffer-match-face-2
+    ivy-minibuffer-match-face-3
+    ivy-minibuffer-match-face-4)
+  "List of `ivy' faces for minibuffer group matches.")
+
 (defun ivy--flx-sort (name cands)
   "Sort according to closeness to string NAME the string list CANDS."
   (condition-case nil
@@ -1866,23 +2038,40 @@ Prefix matches to NAME are put ahead of the list."
                   (delq nil
                         (mapcar
                          (lambda (x)
-                           (let ((score (car (flx-score x flx-name ivy--flx-cache))))
+                           (let ((score (flx-score x flx-name ivy--flx-cache)))
                              (and score
                                   (cons score x))))
                          cands))))
             (if cands-with-score
-                (mapcar #'cdr
+                (mapcar (lambda (x)
+                          (let ((str (copy-sequence (cdr x)))
+                                (i 0)
+                                (last-j -2))
+                            (dolist (j (cdar x))
+                              (unless (eq j (1+ last-j))
+                                (cl-incf i))
+                              (setq last-j j)
+                              (ivy-add-face-text-property
+                               j (1+ j)
+                               (nth (1+ (mod (+ i 2) (1- (length ivy-minibuffer-faces))))
+                                    ivy-minibuffer-faces)
+                               str))
+                            str))
                         (sort cands-with-score
                               (lambda (x y)
-                                (> (car x) (car y)))))
+                                (> (caar x) (caar y)))))
               cands))
         cands)
     (error
      cands)))
 
-(defvar ivy-format-function 'ivy-format-function-default
+(defcustom ivy-format-function 'ivy-format-function-default
   "Function to transform the list of candidates into a string.
-This string will be inserted into the minibuffer.")
+This string is inserted into the minibuffer."
+  :type '(choice
+          (const :tag "Default" ivy-format-function-default)
+          (const :tag "Arrow prefix" ivy-format-function-arrow)
+          (const :tag "Full line" ivy-format-function-line)))
 
 (defun ivy--truncate-string (str width)
   "Truncate STR to WIDTH."
@@ -1891,98 +2080,93 @@ This string will be inserted into the minibuffer.")
                                     (- (length str) 3))) "...")
     str))
 
-(defun ivy-format-function-default (cands)
-  "Transform CANDS into a string for minibuffer."
-  (if (bound-and-true-p truncate-lines)
-      (mapconcat #'identity cands "\n")
-    (let ((ww (- (window-width)
-                 (if (and (boundp 'fringe-mode) (eq fringe-mode 0)) 1 0))))
-      (mapconcat
-       (if truncate-lines
-           (lambda (s)
-             (ivy--truncate-string s ww))
-         #'identity)
-       cands "\n"))))
-
-(defun ivy-format-function-arrow (cands)
-  "Transform CANDS into a string for minibuffer."
+(defun ivy--format-function-generic (selected-fn other-fn cand-pairs separator)
+  "Transform CAND-PAIRS into a string for minibuffer.
+SELECTED-FN and OTHER-FN each take two string arguments.
+SEPARATOR is used to join the candidates."
   (let ((i -1))
     (mapconcat
-     (lambda (s)
-       (concat (if (eq (cl-incf i) ivy--index)
-                   "> "
-                 "  ")
-               s))
-     cands "\n")))
-
-(defface ivy-minibuffer-match-face-1
-  '((((class color) (background light))
-     :background "#d3d3d3")
-    (((class color) (background dark))
-     :background "#555555"))
-  "The background face for `ivy' minibuffer matches.")
-
-(defface ivy-minibuffer-match-face-2
-  '((((class color) (background light))
-     :background "#e99ce8" :weight bold)
-    (((class color) (background dark))
-     :background "#777777" :weight bold))
-  "Face for `ivy' minibuffer matches modulo 1.")
-
-(defface ivy-minibuffer-match-face-3
-  '((((class color) (background light))
-     :background "#bbbbff" :weight bold)
-    (((class color) (background dark))
-     :background "#7777ff" :weight bold))
-  "Face for `ivy' minibuffer matches modulo 2.")
-
-(defface ivy-minibuffer-match-face-4
-  '((((class color) (background light))
-     :background "#ffbbff" :weight bold)
-    (((class color) (background dark))
-     :background "#8a498a" :weight bold))
-  "Face for `ivy' minibuffer matches modulo 3.")
-
-(defcustom ivy-minibuffer-faces
-  '(ivy-minibuffer-match-face-1
-    ivy-minibuffer-match-face-2
-    ivy-minibuffer-match-face-3
-    ivy-minibuffer-match-face-4)
-  "List of `ivy' faces for minibuffer group matches.")
+     (lambda (pair)
+       (let ((str (car pair))
+             (extra (cdr pair))
+             (curr (eq (cl-incf i) ivy--index)))
+         (if curr
+             (funcall selected-fn str extra)
+           (funcall other-fn str extra))))
+     cand-pairs
+     separator)))
+
+(defun ivy-format-function-default (cand-pairs)
+  "Transform CAND-PAIRS into a string for minibuffer."
+  (ivy--format-function-generic
+   (lambda (str extra)
+     (concat (ivy--add-face str 'ivy-current-match) extra))
+   #'concat
+   cand-pairs
+   "\n"))
+
+(defun ivy-format-function-arrow (cand-pairs)
+  "Transform CAND-PAIRS into a string for minibuffer."
+  (ivy--format-function-generic
+   (lambda (str extra)
+     (concat "> " (ivy--add-face str 'ivy-current-match) extra))
+   (lambda (str extra)
+     (concat "  " str extra))
+   cand-pairs
+   "\n"))
+
+(defun ivy-format-function-line (cand-pairs)
+  "Transform CAND-PAIRS into a string for minibuffer."
+  (ivy--format-function-generic
+   (lambda (str extra)
+     (ivy--add-face (concat str extra "\n") 'ivy-current-match))
+   (lambda (str extra)
+     (concat str extra "\n"))
+   cand-pairs
+   ""))
+
+(defun ivy-add-face-text-property (start end face str)
+  (if (fboundp 'add-face-text-property)
+      (add-face-text-property
+       start end face nil str)
+    (font-lock-append-text-property
+     start end 'face face str)))
 
 (defun ivy--format-minibuffer-line (str)
   (let ((start 0)
         (str (copy-sequence str)))
-    (when (eq ivy-display-style 'fancy)
-      (unless ivy--old-re
-        (setq ivy--old-re (funcall ivy--regex-function ivy-text)))
-      (while (and (string-match ivy--old-re str start)
-                  (> (- (match-end 0) (match-beginning 0)) 0))
-        (setq start (match-end 0))
-        (let ((i 0))
-          (while (<= i ivy--subexps)
-            (let ((face
-                   (cond ((zerop ivy--subexps)
-                          (cadr ivy-minibuffer-faces))
-                         ((zerop i)
-                          (car ivy-minibuffer-faces))
-                         (t
-                          (nth (1+ (mod (+ i 2) (1- (length ivy-minibuffer-faces))))
-                               ivy-minibuffer-faces)))))
-              (if (fboundp 'add-face-text-property)
-                  (add-face-text-property
-                   (match-beginning i)
-                   (match-end i)
-                   face
-                   nil
-                   str)
-                (font-lock-append-text-property
-                 (match-beginning i)
-                 (match-end i)
-                 'face
-                 face
-                 str)))
-            (cl-incf i)))))
+    (cond ((eq ivy--regex-function 'ivy--regex-ignore-order)
+           (when (consp ivy--old-re)
+             (let ((i 1))
+               (dolist (re ivy--old-re)
+                 (when (string-match (car re) str)
+                   (ivy-add-face-text-property
+                    (match-beginning 0) (match-end 0)
+                    (nth (1+ (mod (+ i 2) (1- (length ivy-minibuffer-faces))))
+                         ivy-minibuffer-faces)
+                    str))
+                 (cl-incf i)))))
+          ((and (eq ivy-display-style 'fancy)
+                (not (eq ivy--regex-function 'ivy--regex-fuzzy)))
+           (unless ivy--old-re
+             (setq ivy--old-re (funcall ivy--regex-function ivy-text)))
+           (while (and (string-match ivy--old-re str start)
+                       (> (- (match-end 0) (match-beginning 0)) 0))
+             (setq start (match-end 0))
+             (let ((i 0))
+               (while (<= i ivy--subexps)
+                 (let ((face
+                        (cond ((zerop ivy--subexps)
+                               (cadr ivy-minibuffer-faces))
+                              ((zerop i)
+                               (car ivy-minibuffer-faces))
+                              (t
+                               (nth (1+ (mod (+ i 2) (1- (length ivy-minibuffer-faces))))
+                                    ivy-minibuffer-faces)))))
+                   (ivy-add-face-text-property
+                    (match-beginning i) (match-end i)
+                    face str))
+                 (cl-incf i))))))
     str))
 
 (defun ivy--format (cands)
@@ -2015,13 +2199,11 @@ CANDS is a list of strings."
                                        x)))
                                  cands))))
       (setq ivy--current (copy-sequence (nth index cands)))
-      (setq cands (mapcar
-                   #'ivy--format-minibuffer-line
-                   cands))
-      (setf (nth index cands)
-            (ivy--add-face (nth index cands) 'ivy-current-match))
       (let* ((ivy--index index)
-             (res (concat "\n" (funcall ivy-format-function cands))))
+             (cand-pairs (mapcar
+                          (lambda (cand)
+                            (cons (ivy--format-minibuffer-line cand) nil)) cands))
+             (res (concat "\n" (funcall ivy-format-function cand-pairs))))
         (put-text-property 0 (length res) 'read-only nil res)
         res))))
 
@@ -2030,9 +2212,6 @@ CANDS is a list of strings."
 
 (defvar recentf-list)
 
-(defface ivy-virtual '((t :inherit font-lock-builtin-face))
-  "Face used by Ivy for matching virtual buffer names.")
-
 (defcustom ivy-virtual-abbreviate 'name
   "The mode of abbreviation for virtual buffer names."
   :type '(choice
@@ -2205,11 +2384,12 @@ Don't finish completion."
 
 (defun ivy-reverse-i-search ()
   "Enter a recursive `ivy-read' session using the current history.
-The selected history element will be inserted into the minibufer."
+The selected history element will be inserted into the minibuffer."
   (interactive)
   (let ((enable-recursive-minibuffers t)
         (history (symbol-value (ivy-state-history ivy-last)))
-        (old-last ivy-last))
+        (old-last ivy-last)
+        (ivy-recursive-restore nil))
     (ivy-read "Reverse-i-search: "
               history
               :action (lambda (x)
@@ -2268,12 +2448,12 @@ buffer would modify `ivy-last'.")
 (defun ivy-occur ()
   "Stop completion and put the current matches into a new buffer.
 
-The new buffer will also remember the current action(s).
+The new buffer remembers current action(s).
 
-While in the *ivy-occur* buffer, selecting a cadidate with RET or
+While in the *ivy-occur* buffer, selecting a candidate with RET or
 a mouse click will call the appropriate action for that candidate.
 
-It's possible to have an unlimited amount of *ivy-occur* buffers."
+There is no limit on the number of *ivy-occur* buffers."
   (interactive)
   (let ((buffer
          (generate-new-buffer
@@ -2290,7 +2470,10 @@ It's possible to have an unlimited amount of *ivy-occur* buffers."
             (setq ivy--old-cands
                   (split-string
                    (shell-command-to-string
-                    (format counsel-git-grep-cmd ivy--old-re))
+                    (format counsel-git-grep-cmd
+                            (if (stringp ivy--old-re)
+                                ivy--old-re
+                              (caar ivy--old-re))))
                    "\n"
                    t))
             (ivy-occur-grep-mode))
@@ -2357,6 +2540,9 @@ EVENT gives the mouse position."
       (goto-char pos)
       (ivy-occur-press))))
 
+(declare-function swiper--cleanup "swiper")
+(declare-function swiper--add-overlays "swiper")
+
 (defun ivy-occur-press ()
   "Execute action for the current candidate."
   (interactive)