]> code.delx.au - gnu-emacs-elpa/blobdiff - ivy.el
counsel.el (counsel-grep-or-swiper): New command
[gnu-emacs-elpa] / ivy.el
diff --git a/ivy.el b/ivy.el
index aacdcf48a388e897deb616c5b9612e5325ba0774..18f9dca681977b0388a3d7adba3192eaf3d9e726 100644 (file)
--- a/ivy.el
+++ b/ivy.el
   "Incremental vertical completion."
   :group 'convenience)
 
+(defgroup ivy-faces nil
+  "Font-lock faces for `ivy'."
+  :group 'ivy
+  :group 'faces)
+
 (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 numbered 1 modulo 3.")
+
+(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 numbered 2 modulo 3.")
+
+(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 numbered 3 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.")
 
 (defface ivy-subdir
-  '((t (:inherit 'dired-directory)))
+  '((t :inherit dired-directory))
   "Face used by Ivy for highlighting subdirs in the alternatives.")
 
 (defface ivy-modified-buffer
-  '((t :inherit 'default))
+  '((t :inherit default))
   "Face used by Ivy for highlighting modified file visiting buffers.")
 
 (defface ivy-remote
-  '((t (:foreground "#110099")))
+  '((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.")
+
+(defface ivy-action
+  '((t :inherit font-lock-builtin-face))
+  "Face used by Ivy for displaying keys in `ivy-read-action'.")
+
+(setcdr (assoc load-file-name custom-current-group-alist) 'ivy)
+
 (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 ")
           (const :tag "Count matches and show current match" "(%d/%d) ")
           string))
 
+(defcustom ivy-add-newline-after-prompt nil
+  "When non-nil, add a newline after the `ivy-read' prompt."
+  :type 'boolean)
+
 (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 '("../" "./")
@@ -130,6 +176,48 @@ Only \"./\" and \"../\" apply here. They appear in reverse order."
   (setq ivy--actions-list
         (plist-put ivy--actions-list cmd actions)))
 
+(defvar ivy--display-transformers-list nil
+  "A list of str->str transformers per command.")
+
+(defun ivy-set-display-transformer (cmd transformer)
+  "Set CMD a displayed candidate TRANSFORMER.
+
+It's a lambda that takes a string one of the candidates in the
+collection and returns a string for display, the same candidate
+plus some extra information.
+
+This lambda is called only on the `ivy-height' candidates that
+are about to be displayed, not on the whole collection."
+  (setq ivy--display-transformers-list
+        (plist-put ivy--display-transformers-list cmd transformer)))
+
+(defvar ivy--sources-list nil
+  "A list of extra sources per command.")
+
+(defun ivy-set-sources (cmd sources)
+  "Attach to CMD a list of extra SOURCES.
+
+Each static source is a function that takes no argument and
+returns a list of strings.
+
+The '(original-source) determines the position of the original
+dynamic source.
+
+Extra dynamic sources aren't supported yet.
+
+Example:
+
+    (defun small-recentf ()
+      (cl-subseq recentf-list 0 20))
+
+    (ivy-set-sources
+     'counsel-locate
+     '((small-recentf)
+       (original-source)))
+"
+  (setq ivy--sources-list
+        (plist-put ivy--sources-list cmd sources)))
+
 ;;* Keymap
 (require 'delsel)
 (defvar ivy-minibuffer-map
@@ -139,25 +227,23 @@ Only \"./\" and \"../\" apply here. They appear in reverse order."
     (define-key map (kbd "C-j") 'ivy-alt-done)
     (define-key map (kbd "C-M-j") 'ivy-immediate-done)
     (define-key map (kbd "TAB") 'ivy-partial-or-done)
-    (define-key map (kbd "C-n") 'ivy-next-line)
-    (define-key map (kbd "C-p") 'ivy-previous-line)
-    (define-key map (kbd "<down>") 'ivy-next-line)
-    (define-key map (kbd "<up>") 'ivy-previous-line)
+    (define-key map [remap next-line] 'ivy-next-line)
+    (define-key map [remap previous-line] 'ivy-previous-line)
     (define-key map (kbd "C-s") 'ivy-next-line-or-history)
     (define-key map (kbd "C-r") 'ivy-reverse-i-search)
     (define-key map (kbd "SPC") 'self-insert-command)
-    (define-key map (kbd "DEL") 'ivy-backward-delete-char)
-    (define-key map (kbd "M-DEL") 'ivy-backward-kill-word)
-    (define-key map (kbd "C-d") 'ivy-delete-char)
-    (define-key map (kbd "C-f") 'ivy-forward-char)
-    (define-key map (kbd "M-d") 'ivy-kill-word)
-    (define-key map (kbd "M-<") 'ivy-beginning-of-buffer)
-    (define-key map (kbd "M->") 'ivy-end-of-buffer)
+    (define-key map [remap delete-backward-char] 'ivy-backward-delete-char)
+    (define-key map [remap backward-kill-word] 'ivy-backward-kill-word)
+    (define-key map [remap delete-char] 'ivy-delete-char)
+    (define-key map [remap forward-char] 'ivy-forward-char)
+    (define-key map [remap kill-word] 'ivy-kill-word)
+    (define-key map [remap beginning-of-buffer] 'ivy-beginning-of-buffer)
+    (define-key map [remap end-of-buffer] 'ivy-end-of-buffer)
     (define-key map (kbd "M-n") 'ivy-next-history-element)
     (define-key map (kbd "M-p") 'ivy-previous-history-element)
     (define-key map (kbd "C-g") 'minibuffer-keyboard-quit)
-    (define-key map (kbd "C-v") 'ivy-scroll-up-command)
-    (define-key map (kbd "M-v") 'ivy-scroll-down-command)
+    (define-key map [remap scroll-up-command] 'ivy-scroll-up-command)
+    (define-key map [remap scroll-down-command] 'ivy-scroll-down-command)
     (define-key map (kbd "C-M-n") 'ivy-next-line-and-call)
     (define-key map (kbd "C-M-p") 'ivy-previous-line-and-call)
     (define-key map (kbd "M-q") 'ivy-toggle-regexp-quote)
@@ -166,18 +252,24 @@ Only \"./\" and \"../\" apply here. They appear in reverse order."
     (define-key map (kbd "C-o") 'hydra-ivy/body)
     (define-key map (kbd "M-o") 'ivy-dispatching-done)
     (define-key map (kbd "C-M-o") 'ivy-dispatching-call)
-    (define-key map (kbd "C-k") 'ivy-kill-line)
+    (define-key map [remap kill-line] 'ivy-kill-line)
     (define-key map (kbd "S-SPC") 'ivy-restrict-to-matches)
-    (define-key map (kbd "M-w") 'ivy-kill-ring-save)
+    (define-key map [remap kill-ring-save] 'ivy-kill-ring-save)
     (define-key map (kbd "C-'") 'ivy-avy)
-    (define-key map (kbd "C-c o") 'ivy-occur)
+    (define-key map (kbd "C-M-a") 'ivy-read-action)
+    (define-key map (kbd "C-c C-o") 'ivy-occur)
+    (define-key map (kbd "C-c C-a") 'ivy-toggle-ignore)
+    (define-key map [remap describe-mode] 'ivy-help)
     map)
   "Keymap used in the minibuffer.")
 (autoload 'hydra-ivy/body "ivy-hydra" "" t)
 
 (defvar ivy-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map [remap switch-to-buffer] 'ivy-switch-buffer)
+    (define-key map [remap switch-to-buffer]
+      'ivy-switch-buffer)
+    (define-key map [remap switch-to-buffer-other-window]
+      'ivy-switch-buffer-other-window)
     map)
   "Keymap for `ivy-mode'.")
 
@@ -190,15 +282,19 @@ Only \"./\" and \"../\" apply here. They appear in reverse order."
   window
   ;; The buffer in which `ivy-read' was called
   buffer
+  ;; The value of `ivy-text' to be used by `ivy-occur'
+  text
   action
   unwind
   re-builder
   matcher
   ;; When this is non-nil, call it for each input change to get new candidates
   dynamic-collection
+  ;; A lambda that transforms candidates only for display
+  display-transformer-fn
   caller)
 
-(defvar ivy-last nil
+(defvar ivy-last (make-ivy-state)
   "The last parameters passed to `ivy-read'.
 
 This should eventually become a stack so that you could use
@@ -207,11 +303,27 @@ This should eventually become a stack so that you could use
 (defsubst ivy-set-action (action)
   (setf (ivy-state-action ivy-last) action))
 
+(defun ivy-thing-at-point ()
+  "Return a string that corresponds to the current thing at point."
+  (or
+   (thing-at-point 'url)
+   (and (eq (ivy-state-collection ivy-last) 'read-file-name-internal)
+        (ffap-file-at-point))
+   (let (s)
+     (cond ((stringp (setq s (thing-at-point 'symbol)))
+            (if (string-match "\\`[`']?\\(.*?\\)'?\\'" s)
+                (match-string 1 s)
+              s))
+           ((looking-at "(+\\(\\(?:\\sw\\|\\s_\\)+\\)\\_>")
+            (match-string-no-properties 1))
+           (t
+            "")))))
+
 (defvar ivy-history nil
   "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.")
@@ -235,12 +347,27 @@ Otherwise, store nil.")
 (defvar ivy--all-candidates nil
   "Store the candidates passed to `ivy-read'.")
 
+(defvar ivy--extra-candidates '((original-source))
+  "Store candidates added by the extra sources.
+
+This is an internal-use alist. Each key is a function name, or
+original-source (which represents where the current dynamic
+candidates should go).
+
+Each value is an evaluation of the function, in case of static
+sources. These values will subsequently be filtered on `ivy-text'.
+
+This variable is set by `ivy-read' and used by `ivy--set-candidates'.")
+
+(defvar ivy-use-ignore t
+  "Store policy for user-configured candidate filtering.")
+
 (defvar ivy--default nil
   "Default initial input.")
 
 (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.")
@@ -268,6 +395,18 @@ When non-nil, it should contain one %d.")
 
 (defvar Info-current-file)
 
+(eval-and-compile
+  (unless (fboundp 'defvar-local)
+    (defmacro defvar-local (var val &optional docstring)
+      "Define VAR as a buffer-local variable with default value VAL."
+      (declare (debug defvar) (doc-string 3))
+      (list 'progn (list 'defvar var val docstring)
+            (list 'make-variable-buffer-local (list 'quote var)))))
+  (unless (fboundp 'setq-local)
+    (defmacro setq-local (var val)
+      "Set variable VAR to value VAL in current buffer."
+      (list 'set (list 'make-local-variable (list 'quote var)) val))))
+
 (defmacro ivy-quit-and-run (&rest body)
   "Quit the minibuffer and run BODY afterwards."
   `(progn
@@ -278,6 +417,15 @@ When non-nil, it should contain one %d.")
                     ,@body))
      (minibuffer-keyboard-quit)))
 
+(defun ivy-exit-with-action (action)
+  "Quit the minibuffer and call ACTION afterwards."
+  (ivy-set-action
+   `(lambda (x)
+      (funcall ',action x)
+      (ivy-set-action ',(ivy-state-action ivy-last))))
+  (setq ivy-exit 'done)
+  (exit-minibuffer))
+
 (defmacro with-ivy-window (&rest body)
   "Execute BODY in the window from which `ivy-read' was called."
   (declare (indent 0)
@@ -318,30 +466,48 @@ When non-nil, it should contain one %d.")
          (insert ivy-text)
          (ivy--exhibit))))
 
+(defvar ivy-read-action-format-function 'ivy-read-action-format-default
+  "Function used to transform the actions list into a docstring.")
+
+(defun ivy-read-action-format-default (actions)
+  "Create a docstring from ACTIONS.
+
+ACTIONS is a list. Each list item is a list of 3 items:
+key (a string), cmd and doc (a string)."
+  (format "%s\n%s\n"
+          (if (eq this-command 'ivy-read-action)
+              "Select action: "
+            ivy--current)
+          (mapconcat
+           (lambda (x)
+             (format "%s: %s"
+                     (propertize
+                      (car x)
+                      'face 'ivy-action)
+                     (nth 2 x)))
+           actions
+           "\n")))
+
 (defun ivy-read-action ()
-  "Change the action to one of the available ones."
+  "Change the action to one of the available ones.
+
+Return nil for `minibuffer-keyboard-quit' or wrong key during the
+selection, non-nil otherwise."
   (interactive)
   (let ((actions (ivy-state-action ivy-last)))
-    (unless (null (ivy--actionp actions))
-      (let* ((hint (concat ivy--current
-                           "\n"
-                           (mapconcat
-                            (lambda (x)
-                              (format "%s: %s"
-                                      (propertize
-                                       (car x)
-                                       'face 'font-lock-builtin-face)
-                                      (nth 2 x)))
-                            (cdr actions)
-                            "\n")
-                           "\n"))
+    (if (null (ivy--actionp actions))
+        t
+      (let* ((hint (funcall ivy-read-action-format-function (cdr actions)))
+             (resize-mini-windows 'grow-only)
              (key (string (read-key hint)))
              (action-idx (cl-position-if
                           (lambda (x) (equal (car x) key))
                           (cdr actions))))
-        (cond ((string= key "\a"))
+        (cond ((string= key "\a")
+               nil)
               ((null action-idx)
-               (error "%s is not bound" key))
+               (message "%s is not bound" key)
+               nil)
               (t
                (message "")
                (setcar actions (1+ action-idx))
@@ -350,16 +516,17 @@ When non-nil, it should contain one %d.")
 (defun ivy-dispatching-done ()
   "Select one of the available actions and call `ivy-done'."
   (interactive)
-  (ivy-read-action)
-  (ivy-done))
+  (when (ivy-read-action)
+    (ivy-done)))
 
 (defun ivy-dispatching-call ()
   "Select one of the available actions and call `ivy-call'."
   (interactive)
   (let ((actions (copy-sequence (ivy-state-action ivy-last))))
-    (ivy-read-action)
-    (ivy-call)
-    (ivy-set-action actions)))
+    (unwind-protect
+         (when (ivy-read-action)
+           (ivy-call))
+      (ivy-set-action actions))))
 
 (defun ivy-build-tramp-name (x)
   "Reconstruct X into a path.
@@ -377,64 +544,86 @@ Is is a cons cell, related to `tramp-get-completion-function'."
   "Exit the minibuffer with the selected candidate.
 When ARG is t, exit with current text, ignoring the candidates."
   (interactive "P")
+  (cond (arg
+         (ivy-immediate-done))
+        (ivy--directory
+         (ivy--directory-done))
+        ((eq (ivy-state-collection ivy-last) 'Info-read-node-name-1)
+         (if (member ivy--current '("(./)" "(../)"))
+             (ivy-quit-and-run
+              (ivy-read "Go to file: " 'read-file-name-internal
+                        :action (lambda (x)
+                                  (Info-find-node
+                                   (expand-file-name x ivy--directory)
+                                   "Top"))))
+           (ivy-done)))
+        (t
+         (ivy-done))))
+
+(defun ivy--directory-done ()
+  "Handle exit from the minibuffer when completing file names."
   (let (dir)
-    (cond (arg
-           (ivy-immediate-done))
-          ((and ivy--directory
-                (or
-                 (and
-                  (not (equal ivy-text ""))
-                  (file-directory-p ivy-text)
-                  (setq dir (expand-file-name
-                             ivy-text ivy--directory)))
-                 (and
-                  (not (string= ivy--current "./"))
-                  (cl-plusp ivy--length)
-                  (file-directory-p
-                   (setq dir (expand-file-name
-                              ivy--current ivy--directory))))))
-           (ivy--cd dir)
-           (ivy--exhibit))
-          ((eq (ivy-state-collection ivy-last) 'Info-read-node-name-1)
-           (if (or (equal ivy--current "(./)")
-                   (equal ivy--current "(../)"))
-               (ivy-quit-and-run
-                (ivy-read "Go to file: " 'read-file-name-internal
-                          :action (lambda (x)
-                                    (Info-find-node
-                                     (expand-file-name x ivy--directory)
-                                     "Top"))))
-             (ivy-done)))
-          ((and ivy--directory
-                (string-match "\\`/[^/]+:.*:.*\\'" ivy-text))
-           (ivy-done))
-          ((and ivy--directory
-                (string-match
-                 "\\`/\\([^/]+?\\):\\(?:\\(.*\\)@\\)?\\(.*\\)\\'"
-                 ivy-text))
-           (let ((method (match-string 1 ivy-text))
-                 (user (match-string 2 ivy-text))
-                 (rest (match-string 3 ivy-text))
-                 res)
-             (require 'tramp)
-             (dolist (x (tramp-get-completion-function method))
-               (setq res (append res (funcall (car x) (cadr x)))))
-             (setq res (delq nil res))
-             (when user
-               (dolist (x res)
-                 (setcar x user)))
-             (setq res (cl-delete-duplicates res :test #'equal))
-             (let* ((old-ivy-last ivy-last)
-                    (enable-recursive-minibuffers t)
-                    (host (ivy-read "Find File: "
-                                    (mapcar #'ivy-build-tramp-name res)
-                                    :initial-input rest)))
-               (setq ivy-last old-ivy-last)
-               (when host
-                 (setq ivy--directory "/")
-                 (ivy--cd (concat "/" method ":" host ":"))))))
-          (t
-           (ivy-done)))))
+    (cond
+      ((equal ivy-text "/sudo::")
+       (setq dir (concat ivy-text ivy--directory))
+       (ivy--cd dir)
+       (ivy--exhibit))
+      ((and
+        (> ivy--length 0)
+        (not (string= ivy--current "./"))
+        (setq dir (ivy-expand-file-if-directory ivy--current)))
+       (ivy--cd dir)
+       (ivy--exhibit))
+      ((or (and (equal ivy--directory "/")
+                (string-match "\\`[^/]+:.*:.*\\'" ivy-text))
+           (string-match "\\`/[^/]+:.*:.*\\'" ivy-text))
+       (ivy-done))
+      ((or (and (equal ivy--directory "/")
+                (cond ((string-match
+                        "\\`\\([^/]+?\\):\\(?:\\(.*\\)@\\)?\\(.*\\)\\'"
+                        ivy-text))
+                      ((string-match
+                        "\\`\\([^/]+?\\):\\(?:\\(.*\\)@\\)?\\(.*\\)\\'"
+                        ivy--current)
+                       (setq ivy-text ivy--current))))
+           (string-match
+            "\\`/\\([^/]+?\\):\\(?:\\(.*\\)@\\)?\\(.*\\)\\'"
+            ivy-text))
+       (let ((method (match-string 1 ivy-text))
+             (user (match-string 2 ivy-text))
+             (rest (match-string 3 ivy-text))
+             res)
+         (require 'tramp)
+         (dolist (x (tramp-get-completion-function method))
+           (setq res (append res (funcall (car x) (cadr x)))))
+         (setq res (delq nil res))
+         (when user
+           (dolist (x res)
+             (setcar x user)))
+         (setq res (cl-delete-duplicates res :test #'equal))
+         (let* ((old-ivy-last ivy-last)
+                (enable-recursive-minibuffers t)
+                (host (ivy-read "user@host: "
+                                (mapcar #'ivy-build-tramp-name res)
+                                :initial-input rest)))
+           (setq ivy-last old-ivy-last)
+           (when host
+             (setq ivy--directory "/")
+             (ivy--cd (concat "/" method ":" host ":"))))))
+      (t
+       (ivy-done)))))
+
+(defun ivy-expand-file-if-directory (file-name)
+  "Expand FILE-NAME as directory.
+When this directory doesn't exist, return nil."
+  (when (stringp file-name)
+    (let ((full-name
+           ;; Ignore host name must not match method "ssh"
+           (ignore-errors
+             (file-name-as-directory
+              (expand-file-name file-name ivy--directory)))))
+      (when (and full-name (file-directory-p full-name))
+        full-name))))
 
 (defcustom ivy-tab-space nil
   "When non-nil, `ivy-partial-or-done' should insert a space."
@@ -445,13 +634,15 @@ When ARG is t, exit with current text, ignoring the candidates."
 If the text hasn't changed as a result, forward to `ivy-alt-done'."
   (interactive)
   (if (and (eq (ivy-state-collection ivy-last) #'read-file-name-internal)
-           (string-match "\\`/" ivy-text))
-      (let ((default-directory ivy--directory))
+           (or (and (equal ivy--directory "/")
+                    (string-match "\\`[^/]+:.*\\'" ivy-text))
+               (string-match "\\`/" ivy-text)))
+      (let ((default-directory ivy--directory)
+            dir)
         (minibuffer-complete)
         (setq ivy-text (ivy--input))
-        (when (and (file-directory-p ivy-text)
-                   (= ivy--length 1))
-          (ivy--cd (expand-file-name ivy-text))))
+        (when (setq dir (ivy-expand-file-if-directory ivy-text))
+          (ivy--cd dir)))
     (or (ivy-partial)
         (when (or (eq this-command last-command)
                   (eq ivy--length 1))
@@ -499,28 +690,32 @@ If the text hasn't changed as a result, forward to `ivy-alt-done'."
 (defun ivy-resume ()
   "Resume the last completion session."
   (interactive)
-  (with-current-buffer (ivy-state-buffer ivy-last)
-    (ivy-read
-     (ivy-state-prompt ivy-last)
-     (ivy-state-collection ivy-last)
-     :predicate (ivy-state-predicate ivy-last)
-     :require-match (ivy-state-require-match ivy-last)
-     :initial-input ivy-text
-     :history (ivy-state-history ivy-last)
-     :preselect (unless (eq (ivy-state-collection ivy-last)
-                            'read-file-name-internal)
-                  ivy--current)
-     :keymap (ivy-state-keymap ivy-last)
-     :update-fn (ivy-state-update-fn ivy-last)
-     :sort (ivy-state-sort ivy-last)
-     :action (ivy-state-action ivy-last)
-     :unwind (ivy-state-unwind ivy-last)
-     :re-builder (ivy-state-re-builder ivy-last)
-     :matcher (ivy-state-matcher ivy-last)
-     :dynamic-collection (ivy-state-dynamic-collection ivy-last)
-     :caller (ivy-state-caller ivy-last))))
-
-(defvar ivy-calling nil
+  (if (null (ivy-state-action ivy-last))
+      (user-error "The last session isn't compatible with `ivy-resume'")
+    (when (eq (ivy-state-caller ivy-last) 'swiper)
+      (switch-to-buffer (ivy-state-buffer ivy-last)))
+    (with-current-buffer (ivy-state-buffer ivy-last)
+      (ivy-read
+       (ivy-state-prompt ivy-last)
+       (ivy-state-collection ivy-last)
+       :predicate (ivy-state-predicate ivy-last)
+       :require-match (ivy-state-require-match ivy-last)
+       :initial-input ivy-text
+       :history (ivy-state-history ivy-last)
+       :preselect (unless (eq (ivy-state-collection ivy-last)
+                              'read-file-name-internal)
+                    ivy--current)
+       :keymap (ivy-state-keymap ivy-last)
+       :update-fn (ivy-state-update-fn ivy-last)
+       :sort (ivy-state-sort ivy-last)
+       :action (ivy-state-action ivy-last)
+       :unwind (ivy-state-unwind ivy-last)
+       :re-builder (ivy-state-re-builder ivy-last)
+       :matcher (ivy-state-matcher ivy-last)
+       :dynamic-collection (ivy-state-dynamic-collection ivy-last)
+       :caller (ivy-state-caller ivy-last)))))
+
+(defvar-local ivy-calling nil
   "When non-nil, call the current action when `ivy--index' changes.")
 
 (defun ivy-set-index (index)
@@ -543,13 +738,13 @@ If the text hasn't changed as a result, forward to `ivy-alt-done'."
 (defun ivy-scroll-up-command ()
   "Scroll the candidates upward by the minibuffer height."
   (interactive)
-  (ivy-set-index (min (+ ivy--index ivy-height)
+  (ivy-set-index (min (1- (+ ivy--index ivy-height))
                       (1- ivy--length))))
 
 (defun ivy-scroll-down-command ()
   "Scroll the candidates downward by the minibuffer height."
   (interactive)
-  (ivy-set-index (max (- ivy--index ivy-height)
+  (ivy-set-index (max (1+ (- ivy--index ivy-height))
                       0)))
 
 (defun ivy-minibuffer-grow ()
@@ -581,9 +776,9 @@ If the text hasn't changed as a result, forward to `ivy-alt-done'."
   "Move cursor vertically down ARG candidates.
 If the input is empty, select the previous history element instead."
   (interactive "p")
-  (when (string= ivy-text "")
-    (ivy-previous-history-element 1))
-  (ivy-next-line arg))
+  (if (string= ivy-text "")
+      (ivy-previous-history-element 1)
+    (ivy-next-line arg)))
 
 (defun ivy-previous-line (&optional arg)
   "Move cursor vertically up ARG candidates."
@@ -610,6 +805,13 @@ If the input is empty, select the previous history element instead."
   (when (setq ivy-calling (not ivy-calling))
     (ivy-call)))
 
+(defun ivy-toggle-ignore ()
+  "Toggle user-configured candidate filtering."
+  (interactive)
+  (setq ivy-use-ignore (null ivy-use-ignore))
+  ;; invalidate cache
+  (setq ivy--old-cands nil))
+
 (defun ivy--get-action (state)
   "Get the action function from STATE."
   (let ((action (ivy-state-action state)))
@@ -620,12 +822,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."
@@ -657,24 +861,35 @@ If the input is empty, select the previous history element instead."
                 (nth 2 (nth (car action) action)))
       "[1/1] default")))
 
+(defvar ivy-inhibit-action nil
+  "When non-nil, `ivy-call' does nothing.
+
+Example use:
+
+    (let* ((ivy-inhibit-action t)
+          (str (counsel-locate \"lispy.el\")))
+     ;; do whatever with str - the corresponding file will not be opened
+     )")
+
 (defun ivy-call ()
   "Call the current action without exiting completion."
   (interactive)
-  (let ((action (ivy--get-action ivy-last)))
-    (when action
-      (let* ((collection (ivy-state-collection ivy-last))
-             (x (if (and (consp collection)
-                         (consp (car collection)))
-                    (cdr (assoc ivy--current collection))
-                  (if (equal ivy--current "")
-                      ivy-text
-                    ivy--current))))
-        (prog1 (funcall action x)
-          (unless (or (eq ivy-exit 'done)
-                      (equal (selected-window)
-                             (active-minibuffer-window))
-                      (null (active-minibuffer-window)))
-            (select-window (active-minibuffer-window))))))))
+  (unless ivy-inhibit-action
+    (let ((action (ivy--get-action ivy-last)))
+      (when action
+        (let* ((collection (ivy-state-collection ivy-last))
+               (x (if (and (consp collection)
+                           (consp (car collection)))
+                      (cdr (assoc ivy--current collection))
+                    (if (equal ivy--current "")
+                        ivy-text
+                      ivy--current))))
+          (prog1 (funcall action x)
+            (unless (or (eq ivy-exit 'done)
+                        (equal (selected-window)
+                               (active-minibuffer-window))
+                        (null (active-minibuffer-window)))
+              (select-window (active-minibuffer-window)))))))))
 
 (defun ivy-next-line-and-call (&optional arg)
   "Move cursor vertically down ARG candidates.
@@ -703,24 +918,45 @@ Call the permanent action if possible."
 (defun ivy-next-history-element (arg)
   "Forward to `next-history-element' with ARG."
   (interactive "p")
-  (next-history-element arg)
+  (if (and (= minibuffer-history-position 0)
+           (equal ivy-text ""))
+      (progn
+        (insert ivy--default)
+        (when (and (with-ivy-window (derived-mode-p 'prog-mode))
+                   (eq (ivy-state-caller ivy-last) 'swiper)
+                   (not (file-exists-p ivy--default))
+                   (not (ffap-url-p ivy--default))
+                   (not (ivy-state-dynamic-collection ivy-last))
+                   (> (point) (minibuffer-prompt-end)))
+          (undo-boundary)
+          (insert "\\_>")
+          (goto-char (minibuffer-prompt-end))
+          (insert "\\_<")
+          (forward-char (+ 2 (length ivy--default)))))
+    (next-history-element arg))
   (ivy--cd-maybe)
   (move-end-of-line 1)
   (ivy--maybe-scroll-history))
 
+(defvar ivy-ffap-url-functions nil
+  "List of functions that check if the point is on a URL.")
+
 (defun ivy--cd-maybe ()
   "Check if the current input points to a different directory.
 If so, move to that directory, while keeping only the file name."
   (when ivy--directory
     (let ((input (ivy--input))
           url)
-      (if (setq url (ffap-url-p input))
-          (progn
-            (ivy-set-action
-             (lambda (_)
-               (funcall ffap-url-fetcher url)))
-            (setq ivy-exit 'done)
-            (exit-minibuffer))
+      (if (setq url (or (ffap-url-p input)
+                        (with-ivy-window
+                          (cl-reduce
+                           (lambda (a b)
+                             (or a (funcall b)))
+                           ivy-ffap-url-functions
+                           :initial-value nil))))
+          (ivy-exit-with-action
+           (lambda (_)
+             (funcall ffap-url-fetcher url)))
         (setq input (expand-file-name input))
         (let ((file (file-name-nondirectory input))
               (dir (expand-file-name (file-name-directory input))))
@@ -861,9 +1097,10 @@ On error (read-only), call `ivy-on-del-error-function'."
             (avy--process
              (nreverse candidates)
              (avy--style-fn avy-style)))))
-    (ivy-set-index (- (line-number-at-pos candidate) 2))
-    (ivy--exhibit)
-    (ivy-done)))
+    (when (numberp candidate)
+      (ivy-set-index (- (line-number-at-pos candidate) 2))
+      (ivy--exhibit)
+      (ivy-done))))
 
 (defun ivy-sort-file-function-default (x y)
   "Compare two files X and Y.
@@ -886,42 +1123,53 @@ 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
   '(alist
     :key-type (choice
-               (const :tag "All other functions" t)
-               (symbol :tag "Function"))
+               (const :tag "Fall-through" t)
+               (symbol :tag "Collection"))
     :value-type (choice
-                 (const :tag "plain sort" string-lessp)
-                 (const :tag "file sort" ivy-sort-file-function-default)
-                 (const :tag "no sort" nil)))
+                 (const :tag "Plain sort" string-lessp)
+                 (const :tag "File sort" ivy-sort-file-function-default)
+                 (const :tag "No sort" nil)
+                 (function :tag "Custom function")))
   :group 'ivy)
 
 (defvar ivy-index-functions-alist
   '((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
@@ -964,112 +1212,153 @@ 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
+                    &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 function to call to update the list of
-candidates with each 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 (delete-dups
+                        (append (plist-get ivy--actions-list t)
+                                (plist-get ivy--actions-list this-command)
+                                (plist-get ivy--actions-list caller)))))
     (when extra-actions
       (setq action
-            (if (functionp action)
-                `(1
-                  ("o" ,action "default")
-                  ,@extra-actions)
-              (delete-dups (append action extra-actions))))))
-  (setq ivy-last
-        (make-ivy-state
-         :prompt prompt
-         :collection collection
-         :predicate predicate
-         :require-match require-match
-         :initial-input initial-input
-         :history history
-         :preselect preselect
-         :keymap keymap
-         :update-fn update-fn
-         :sort sort
-         :action action
-         :window (selected-window)
-         :buffer (current-buffer)
-         :unwind unwind
-         :re-builder re-builder
-         :matcher matcher
-         :dynamic-collection dynamic-collection
-         :caller caller))
-  (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)))
-        (remove-hook 'post-command-hook #'ivy--exhibit)
-        (when (setq unwind (ivy-state-unwind ivy-last))
-          (funcall unwind)))
-    (ivy-call)))
+            (cond ((functionp action)
+                   `(1
+                     ("o" ,action "default")
+                     ,@extra-actions))
+                  ((null action)
+                   `(1
+                     ("o" identity "default")
+                     ,@extra-actions))
+                  (t
+                   (delete-dups (append action extra-actions)))))))
+  (let ((extra-sources (plist-get ivy--sources-list caller)))
+    (if extra-sources
+        (progn
+          (setq ivy--extra-candidates nil)
+          (dolist (source extra-sources)
+            (cond ((equal source '(original-source))
+                   (setq ivy--extra-candidates
+                         (cons source ivy--extra-candidates)))
+                  ((null (cdr source))
+                   (setq ivy--extra-candidates
+                         (cons
+                          (list (car source) (funcall (car source)))
+                          ivy--extra-candidates))))))
+      (setq ivy--extra-candidates '((original-source)))))
+  (let ((recursive-ivy-last (and (active-minibuffer-window) ivy-last))
+        (transformer-fn
+         (plist-get ivy--display-transformers-list
+                    (or caller (and (functionp collection)
+                                    collection)))))
+    (setq ivy-last
+          (make-ivy-state
+           :prompt prompt
+           :collection collection
+           :predicate predicate
+           :require-match require-match
+           :initial-input initial-input
+           :history history
+           :preselect preselect
+           :keymap keymap
+           :update-fn update-fn
+           :sort sort
+           :action action
+           :window (selected-window)
+           :buffer (current-buffer)
+           :unwind unwind
+           :re-builder re-builder
+           :matcher matcher
+           :dynamic-collection dynamic-collection
+           :display-transformer-fn transformer-fn
+           :caller caller))
+    (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))))
+                 (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))
+          (unless (eq ivy-exit 'done)
+            (when recursive-ivy-last
+              (ivy--reset-state (setq ivy-last recursive-ivy-last)))))
+      (ivy-call)
+      (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))
@@ -1079,7 +1368,7 @@ This is useful for recursive `ivy-read'."
         (dynamic-collection (ivy-state-dynamic-collection state))
         (initial-input (ivy-state-initial-input state))
         (require-match (ivy-state-require-match state))
-        (matcher (ivy-state-matcher state)))
+        (caller (ivy-state-caller state)))
     (unless initial-input
       (setq initial-input (cdr (assoc this-command
                                       ivy-initial-inputs-alist))))
@@ -1089,6 +1378,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)
@@ -1097,6 +1389,7 @@ This is useful for recursive `ivy-read'."
     (setq ivy--full-length nil)
     (setq ivy-text "")
     (setq ivy-calling nil)
+    (setq ivy-use-ignore t)
     (let (coll sort-fn)
       (cond ((eq collection 'Info-read-node-name-1)
              (if (equal Info-current-file "dir")
@@ -1124,14 +1417,19 @@ 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 (and (ivy-state-action ivy-last)
+                            (not (equal (ivy--get-action ivy-last) 'identity)))
+                 (setq initial-input nil))))
             ((eq collection 'internal-complete-buffer)
-             (setq coll (ivy--buffer-list "" ivy-use-virtual-buffers)))
+             (setq coll (ivy--buffer-list "" ivy-use-virtual-buffers predicate)))
+            (dynamic-collection
+             (setq coll (funcall collection ivy-text)))
             ((or (functionp collection)
                  (byte-code-function-p collection)
                  (vectorp collection)
                  (and (consp collection) (listp (car collection)))
-                 (hash-table-p collection))
+                 (hash-table-p collection)
+                 (and (listp collection) (symbolp (car collection))))
              (setq coll (all-completions "" collection predicate)))
             (t
              (setq coll collection)))
@@ -1145,28 +1443,43 @@ This is useful for recursive `ivy-read'."
             (if (and (setq sort-fn (cdr (assoc t ivy-sort-functions-alist)))
                      (<= (length coll) ivy-sort-max-size))
                 (setq coll (cl-sort (copy-sequence coll) sort-fn))))))
+      (setq coll (ivy--set-candidates coll))
       (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--index (or
-                        (and dynamic-collection
-                             ivy--index)
-                        (and preselect
-                             (ivy--preselect-index
-                              coll initial-input preselect matcher))
-                        0))
       (setq ivy--old-re nil)
       (setq ivy--old-cands nil)
-      (setq ivy--all-candidates coll))
+      (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)
+      (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)
-                        (thing-at-point 'symbol)
-                        ""))
+    (setq ivy--default
+          (if (region-active-p)
+              (buffer-substring
+               (region-beginning)
+               (region-end))
+            (ivy-thing-at-point)))
     (setq ivy--prompt
           (cond ((string-match "%.*d" prompt)
                  prompt)
@@ -1189,53 +1502,136 @@ This is useful for recursive `ivy-read'."
                 (ivy--directory
                  prompt)
                 (t
-                 nil)))
+                 prompt)))
     (setf (ivy-state-initial-input ivy-last) initial-input)))
 
 ;;;###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.
+PROMPT is a string that normally ends in a colon and a space.
+COLLECTION is either 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'.
-INITIAL-INPUT is a string that can be inserted into the minibuffer initially.
-_HISTORY is ignored for now.
+REQUIRE-MATCH is a boolean value.  See `completing-read'.
+INITIAL-INPUT is a string inserted into the minibuffer initially.
+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."
-  (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 (or (assoc this-command ivy-sort-functions-alist)
+                              (assoc t 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))
+         (completion-ignore-case case-fold-search)
+         (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))
+          (if (string= str (car comps))
+              (message "Sole match")
+            (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 (if (string= ivy-count-format "")
+                                     ivy-count-format
+                                   (format "%%-%dd " w)))
+               (prompt (format "(%s): " str)))
+          (and
+           (ivy-read (if (string= ivy-count-format "")
+                         prompt
+                       (replace-regexp-in-string "%" "%%" prompt))
+                     ;; remove 'completions-first-difference face
+                     (mapcar #'substring-no-properties comps)
+                     :predicate predicate
+                     :action #'ivy-completion-in-region-action
+                     :require-match t)
+           t))))))
+
+(defcustom ivy-do-completion-in-region t
+  "When non-nil `ivy-mode' will set `completion-in-region-function'."
+  :type 'boolean)
 
 ;;;###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:
@@ -1248,31 +1644,24 @@ 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)))
-
-(defun ivy--preselect-index (candidates initial-input preselect matcher)
-  "Return the index in CANDIDATES filtered by INITIAL-INPUT for PRESELECT.
-When MATCHER is non-nil it's used instead of `cl-remove-if-not'."
-  (if initial-input
       (progn
-        (setq initial-input (ivy--regex-plus initial-input))
-        (setq candidates
-              (if matcher
-                  (funcall matcher initial-input candidates)
-                (cl-remove-if-not
-                 (lambda (x)
-                   (string-match initial-input x))
-                 candidates))))
-    (when matcher
-      (setq candidates (funcall matcher "" candidates))))
-  (or (cl-position preselect candidates :test #'equal)
-      (and (stringp preselect)
-           (let ((re (regexp-quote preselect)))
-             (cl-position-if
-              (lambda (x)
-                (string-match re x))
-              candidates)))))
+        (setq completing-read-function 'ivy-completing-read)
+        (when ivy-do-completion-in-region
+          (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."
+  (cond ((integerp preselect)
+         preselect)
+        ((cl-position preselect candidates :test #'equal))
+        ((stringp preselect)
+         (let ((re preselect))
+           (cl-position-if
+            (lambda (x)
+              (string-match re x))
+            candidates)))))
 
 ;;* Implementation
 ;;** Regex
@@ -1291,19 +1680,27 @@ This allows to \"quote\" N spaces by inputting N+1 spaces."
         match-len)
     (while (and (string-match " +" str start1)
                 (< start1 len))
-      (setq match-len (- (match-end 0) (match-beginning 0)))
-      (if (= match-len 1)
+      (if (and (> (match-beginning 0) 2)
+               (string= "[^" (substring
+                              str
+                              (- (match-beginning 0) 2)
+                              (match-beginning 0))))
           (progn
-            (when start0
-              (setq start1 start0)
-              (setq start0 nil))
-            (push (substring str start1 (match-beginning 0)) res)
-            (setq start1 (match-end 0)))
-        (setq str (replace-match
-                   (make-string (1- match-len) ?\ )
-                   nil nil str))
-        (setq start0 (or start0 start1))
-        (setq start1 (1- (match-end 0)))))
+            (setq start1 (match-end 0))
+            (setq start0 0))
+        (setq match-len (- (match-end 0) (match-beginning 0)))
+        (if (= match-len 1)
+            (progn
+              (when start0
+                (setq start1 start0)
+                (setq start0 nil))
+              (push (substring str start1 (match-beginning 0)) res)
+              (setq start1 (match-end 0)))
+          (setq str (replace-match
+                     (make-string (1- match-len) ?\ )
+                     nil nil str))
+          (setq start0 (or start0 start1))
+          (setq start1 (1- (match-end 0))))))
     (if start0
         (push (substring str start0) res)
       (setq s (substring str start1))
@@ -1312,7 +1709,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))))
@@ -1331,7 +1728,7 @@ When GREEDY is non-nil, join words in a greedy way."
                          (setq ivy--subexps (length subs))
                          (mapconcat
                           (lambda (x)
-                            (if (string-match "\\`\\\\(.*\\\\)\\'" x)
+                            (if (string-match "\\`\\\\([^?].*\\\\)\\'" x)
                                 x
                               (format "\\(%s\\)" x)))
                           subs
@@ -1340,42 +1737,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.
+(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)
@@ -1392,6 +1801,14 @@ Insert .* between each char."
         (setq ivy--subexps (length (match-string 2 str))))
     str))
 
+(defcustom ivy-fixed-height-minibuffer nil
+  "When non nil, fix the height of the minibuffer during ivy
+completion at `ivy-height'. This effectively sets the minimum
+height at this level and tries to ensure that it does not change
+depending on the number of candidates."
+  :group 'ivy
+  :type 'boolean)
+
 ;;** Rest
 (defun ivy--minibuffer-setup ()
   "Setup ivy completion in the minibuffer."
@@ -1399,9 +1816,12 @@ Insert .* between each char."
   (set (make-local-variable 'minibuffer-default-add-function)
        (lambda ()
          (list ivy--default)))
+  (set (make-local-variable 'inhibit-field-text-motion) nil)
   (when (display-graphic-p)
     (setq truncate-lines t))
   (setq-local max-mini-window-height ivy-height)
+  (when ivy-fixed-height-minibuffer
+    (set-window-text-height (selected-window) ivy-height))
   (add-hook 'post-command-hook #'ivy--exhibit nil t)
   ;; show completions with empty input
   (ivy--exhibit))
@@ -1464,6 +1884,8 @@ Insert .* between each char."
                  (window-width))
               (setq n-str (concat n-str "\n" d-str))
             (setq n-str (concat n-str d-str)))
+          (when ivy-add-newline-after-prompt
+            (setq n-str (concat n-str "\n")))
           (let ((regex (format "\\([^\n]\\{%d\\}\\)[^\n]" (window-width))))
             (while (string-match regex n-str)
               (setq n-str (replace-match (concat (match-string 1 n-str) "\n") nil t n-str 1))))
@@ -1479,7 +1901,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)
@@ -1554,8 +1976,9 @@ Should be run via minibuffer `post-command-hook'."
                        (ivy--buffer-list "" ivy-use-virtual-buffers)))
                (setq ivy--old-re nil))))
       (ivy--insert-minibuffer
-       (ivy--format
-        (ivy--filter ivy-text ivy--all-candidates)))
+       (with-current-buffer (ivy-state-buffer ivy-last)
+         (ivy--format
+          (ivy--filter ivy-text ivy--all-candidates))))
       (setq ivy--old-text ivy-text))))
 
 (defun ivy--insert-minibuffer (text)
@@ -1577,18 +2000,21 @@ 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."
-  (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)))
+  "Resize the minibuffer window size to fit the text in the minibuffer."
+  (unless (frame-root-window-p (minibuffer-window))
+    (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)
+              ;; 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))))))
+            (window-resize nil (- text-height body-height) nil t)))))))
 
 (declare-function colir-blend-face-background "ext:colir")
 
@@ -1625,7 +2051,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)
@@ -1636,6 +2062,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."
@@ -1668,25 +2113,92 @@ 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 ""))
-        (when (and (require 'flx nil 'noerror)
-                   (eq ivy--regex-function 'ivy--regex-fuzzy))
-          (setq cands (ivy--flx-sort name cands)))
-        (setq ivy--old-cands cands)))))
+        (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))))))
+
+(defun ivy--set-candidates (x)
+  "Update `ivy--all-candidates' with X."
+  (let (res)
+    (dolist (source ivy--extra-candidates)
+      (if (equal source '(original-source))
+          (if (null res)
+              (setq res x)
+            (setq res (append x res)))
+        (setq ivy--old-re nil)
+        (setq res (append
+                   (ivy--filter ivy-text (cadr source))
+                   res))))
+    (setq ivy--all-candidates res)))
+
+(defcustom ivy-sort-matches-functions-alist '((t . nil))
+  "An alist of functions for sorting matching candidates.
+
+Unlike `ivy-sort-functions-alist', which is used to sort the
+whole collection only once, this alist of functions are used to
+sort only matching candidates after each change in input.
+
+The alist KEY is either a collection function or t to match
+previously unmatched collection functions.
+
+The alist VAL is a sorting function with the signature of
+`ivy--prefix-sort'."
+  :type '(alist
+          :key-type (choice
+                     (const :tag "Fall-through" t)
+                     (symbol :tag "Collection"))
+          :value-type
+          (choice
+           (const :tag "Don't sort" nil)
+           (const :tag "Put prefix matches ahead" 'ivy--prefix-sort)
+           (function :tag "Custom sort function"))))
+
+(defun ivy--sort-files-by-date (_name candidates)
+  "Re-soft CANDIDATES according to file modification date."
+  (let ((default-directory ivy--directory))
+    (cl-sort (copy-sequence candidates)
+             (lambda (f1 f2)
+               (time-less-p
+                (nth 5 (file-attributes f2))
+                (nth 5 (file-attributes f1)))))))
+
+(defun ivy--sort (name candidates)
+  "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))
+                   (ivy-state-collection ivy-last))))
+        fun)
+    (cond ((and (require 'flx nil 'noerror)
+                (eq ivy--regex-function 'ivy--regex-fuzzy))
+           (ivy--flx-sort name candidates))
+          ((setq fun (cdr (or (assoc key ivy-sort-matches-functions-alist)
+                              (assoc t ivy-sort-matches-functions-alist))))
+           (funcall fun name candidates))
+          (t
+           candidates))))
+
+(defun ivy--prefix-sort (name candidates)
+  "Re-sort CANDIDATES.
+Prefix matches to NAME are put ahead of the list."
+  (if (or (string-match "^\\^" name) (string= name ""))
+      candidates
+    (let ((re-prefix (concat "^" (funcall ivy--regex-function name)))
+          res-prefix
+          res-noprefix)
+      (dolist (s candidates)
+        (if (string-match re-prefix s)
+            (push s res-prefix)
+          (push s res-noprefix)))
+      (nconc
+       (nreverse res-prefix)
+       (nreverse res-noprefix)))))
 
 (defun ivy--recompute-index (name re-str cands)
   (let* ((caller (ivy-state-caller ivy-last))
@@ -1696,10 +2208,10 @@ CANDIDATES are assumed to be static."
     (unless (eq this-command 'ivy-resume)
       (setq ivy--index
             (or
-             (cl-position (if (and (> (length re-str) 0)
-                                   (eq ?^ (aref re-str 0)))
-                              (substring re-str 1)
-                            re-str) cands
+             (cl-position (if (and (> (length name) 0)
+                                   (eq ?^ (aref name 0)))
+                              (substring name 1)
+                            name) cands
                             :test #'equal)
              (and ivy--directory
                   (cl-position
@@ -1709,7 +2221,7 @@ CANDIDATES are assumed to be static."
                   (not (and (require 'flx nil 'noerror)
                             (eq ivy--regex-function 'ivy--regex-fuzzy)
                             (< (length cands) 200)))
-
+                  ivy--old-cands
                   (cl-position (nth ivy--index ivy--old-cands)
                                cands))
              (funcall func re-str cands))))
@@ -1718,10 +2230,8 @@ CANDIDATES are assumed to be static."
                (not (equal ivy--old-re "")))
       (setq ivy--index
             (or (ivy--preselect-index
-                 cands
-                 nil
                  (ivy-state-preselect ivy-last)
-                 nil)
+                 cands)
                 ivy--index)))))
 
 (defun ivy-recompute-index-swiper (_re-str cands)
@@ -1732,17 +2242,71 @@ CANDIDATES are assumed to be static."
           (while (and tail (null idx))
             ;; Compare with eq to handle equal duplicates in cands
             (setq idx (cl-position (pop tail) cands)))
-          (or idx 0))
-      ivy--index)))
+          (or
+           idx
+           (1- (length cands))))
+      (if ivy--old-cands
+          ivy--index
+        ;; already in ivy-state-buffer
+        (let ((n (line-number-at-pos))
+              (res 0)
+              (i 0))
+          (dolist (c cands)
+            (when (eq n (read (get-text-property 0 'display c)))
+              (setq res i))
+            (cl-incf i))
+          res)))))
+
+(defun ivy-recompute-index-swiper-async (_re-str cands)
+  (if (null ivy--old-cands)
+      (let ((ln (with-ivy-window
+                  (line-number-at-pos))))
+        (or
+         ;; closest to current line going forwards
+         (cl-position-if (lambda (x)
+                           (>= (string-to-number x) ln))
+                         cands)
+         ;; closest to current line going backwards
+         (1- (length 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."
+  :type '(repeat :tag "Faces"
+          (choice
+           (const ivy-minibuffer-match-face-1)
+           (const ivy-minibuffer-match-face-2)
+           (const ivy-minibuffer-match-face-3)
+           (const ivy-minibuffer-match-face-4)
+           (face :tag "Other face"))))
+
+(defvar ivy-flx-limit 200
+  "Used to conditionally turn off flx sorting.
+
+When the amount of matching candidates exceeds this limit, then
+no sorting is done.")
+
 (defun ivy--flx-sort (name cands)
   "Sort according to closeness to string NAME the string list CANDS."
   (condition-case nil
       (if (and cands
-               (< (length cands) 200))
+               (< (length cands) ivy-flx-limit))
           (let* ((flx-name (if (string-match "^\\^" name)
                                (substring name 1)
                              name))
@@ -1750,118 +2314,144 @@ CANDIDATES are assumed to be static."
                   (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.")
-
-(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)
-             (if (> (length s) ww)
-                 (concat (substring s 0 (- ww 3)) "...")
-               s))
-         #'identity)
-       cands "\n"))))
+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."
+  (if (> (string-width str) width)
+      (concat (substring str 0 (min (- width 3)
+                                    (- (length str) 3))) "...")
+    str))
 
-(defun ivy-format-function-arrow (cands)
-  "Transform CANDS into a string for minibuffer."
+(defun ivy--format-function-generic (selected-fn other-fn strs separator)
+  "Transform CAND-PAIRS into a string for minibuffer.
+SELECTED-FN and OTHER-FN each take one string argument.
+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.")
+     (lambda (str)
+       (let ((curr (eq (cl-incf i) ivy--index)))
+         (if curr
+             (funcall selected-fn str)
+           (funcall other-fn str))))
+     strs
+     separator)))
 
-(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.")
+(defun ivy-format-function-default (cands)
+  "Transform CAND-PAIRS into a string for minibuffer."
+  (ivy--format-function-generic
+   (lambda (str)
+     (ivy--add-face str 'ivy-current-match))
+   #'identity
+   cands
+   "\n"))
 
-(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-format-function-arrow (cands)
+  "Transform CAND-PAIRS into a string for minibuffer."
+  (ivy--format-function-generic
+   (lambda (str)
+     (concat "> " (ivy--add-face str 'ivy-current-match)))
+   (lambda (str)
+     (concat "  " str))
+   cands
+   "\n"))
+
+(defun ivy-format-function-line (cands)
+  "Transform CAND-PAIRS into a string for minibuffer."
+  (ivy--format-function-generic
+   (lambda (str)
+     (ivy--add-face (concat str "\n") 'ivy-current-match))
+   (lambda (str)
+     (concat str "\n"))
+   cands
+   ""))
+
+(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)))
+           (ignore-errors
+             (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))
+
+(ivy-set-display-transformer
+ 'counsel-find-file 'ivy-read-file-transformer)
+(ivy-set-display-transformer
+ 'read-file-name-internal 'ivy-read-file-transformer)
+
+(defun ivy-read-file-transformer (str)
+  (if (string-match-p "/\\'" str)
+      (propertize str 'face 'ivy-subdir)
     str))
 
 (defun ivy--format (cands)
@@ -1877,29 +2467,16 @@ CANDS is a list of strings."
            (end (min (+ start (1- ivy-height)) ivy--length))
            (start (max 0 (min start (- end (1- ivy-height)))))
            (cands (cl-subseq cands start end))
-           (index (- ivy--index start)))
-      (cond (ivy--directory
-             (setq cands (mapcar (lambda (x)
-                                   (if (string-match-p "/\\'" x)
-                                       (propertize x 'face 'ivy-subdir)
-                                     x))
-                                 cands)))
-            ((eq (ivy-state-collection ivy-last) 'internal-complete-buffer)
-             (setq cands (mapcar (lambda (x)
-                                   (let ((b (get-buffer x)))
-                                     (if (and b
-                                              (buffer-file-name b)
-                                              (buffer-modified-p b))
-                                         (propertize x 'face 'ivy-modified-buffer)
-                                       x)))
-                                 cands))))
+           (index (- ivy--index start))
+           transformer-fn)
       (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))
+      (when (setq transformer-fn (ivy-state-display-transformer-fn ivy-last))
+        (with-ivy-window
+          (setq cands (mapcar transformer-fn cands))))
       (let* ((ivy--index index)
+             (cands (mapcar
+                     #'ivy--format-minibuffer-line
+                     cands))
              (res (concat "\n" (funcall ivy-format-function cands))))
         (put-text-property 0 (length res) 'read-only nil res)
         res))))
@@ -1909,9 +2486,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
@@ -1953,7 +2527,11 @@ CANDS is a list of strings."
       (setq ivy--virtual-buffers (nreverse virtual-buffers))
       (mapcar #'car ivy--virtual-buffers))))
 
-(defun ivy--buffer-list (str &optional virtual)
+(defcustom ivy-ignore-buffers '("\\` ")
+  "List of regexps or functions matching buffer names to ignore."
+  :type '(repeat (choice regexp function)))
+
+(defun ivy--buffer-list (str &optional virtual predicate)
   "Return the buffers that match STR.
 When VIRTUAL is non-nil, add virtual buffers."
   (delete-dups
@@ -1965,10 +2543,73 @@ When VIRTUAL is non-nil, add virtual buffers."
               (abbreviate-file-name default-directory)))
            (propertize x 'face 'ivy-remote)
          x))
-     (all-completions str 'internal-complete-buffer))
+     (all-completions str 'internal-complete-buffer predicate))
     (and virtual
          (ivy--virtual-buffers)))))
 
+(defvar ivy-views (and nil
+                       `(("ivy + *scratch* {}"
+                          (vert
+                           (file ,(expand-file-name "ivy.el"))
+                           (buffer "*scratch*")))
+                         ("swiper + *scratch* {}"
+                          (horz
+                           (file ,(expand-file-name "swiper.el"))
+                           (buffer "*scratch*")))))
+  "Store window configurations selectable by `ivy-switch-buffer'.
+
+The default value is given as an example.
+
+Each element is a list of (NAME TREE). NAME is a string, it's
+recommended to end it with a distinctive snippet e.g. \"{}\" so
+that it's easy to distinguish the window configurations.
+
+TREE is a nested list with the following valid cars:
+- vert: split the window vertically
+- horz: split the window horizontally
+- file: open the specified file
+- buffer: open the specified buffer
+
+TREE can be nested multiple times to have mulitple window splits.")
+
+(defun ivy-source-views ()
+  (mapcar #'car ivy-views))
+
+(ivy-set-sources
+ 'ivy-switch-buffer
+ '((original-source)
+   (ivy-source-views)))
+
+(defun ivy-set-view-recur (view)
+  (cond ((eq (car view) 'vert)
+         (let ((wnd1 (selected-window))
+               (wnd2 (split-window-vertically)))
+           (with-selected-window wnd1
+             (ivy-set-view-recur (nth 1 view)))
+           (with-selected-window wnd2
+             (ivy-set-view-recur (nth 2 view)))))
+        ((eq (car view) 'horz)
+         (let ((wnd1 (selected-window))
+               (wnd2 (split-window-horizontally)))
+           (with-selected-window wnd1
+             (ivy-set-view-recur (nth 1 view)))
+           (with-selected-window wnd2
+             (ivy-set-view-recur (nth 2 view)))))
+        ((eq (car view) 'file)
+         (let* ((name (cadr view))
+                (virtual (assoc name ivy--virtual-buffers))
+                buffer)
+           (cond ((setq buffer (get-buffer name))
+                  (switch-to-buffer buffer nil 'force-same-window))
+                 (virtual
+                  (find-file (cdr virtual)))
+                 ((file-exists-p name)
+                  (find-file name)))))
+        ((eq (car view) 'buffer)
+         (switch-to-buffer (cadr view)))
+        ((eq (car view) 'sexp)
+         (eval (cadr view)))))
+
 (defun ivy--switch-buffer-action (buffer)
   "Switch to BUFFER.
 BUFFER may be a string or nil."
@@ -1976,12 +2617,17 @@ BUFFER may be a string or nil."
     (if (zerop (length buffer))
         (switch-to-buffer
          ivy-text nil 'force-same-window)
-      (let ((virtual (assoc buffer ivy--virtual-buffers)))
-        (if (and virtual
-                 (not (get-buffer buffer)))
-            (find-file (cdr virtual))
-          (switch-to-buffer
-           buffer nil 'force-same-window))))))
+      (let ((virtual (assoc buffer ivy--virtual-buffers))
+            (view (assoc buffer ivy-views)))
+        (cond ((and virtual
+                    (not (get-buffer buffer)))
+               (find-file (cdr virtual)))
+              (view
+               (delete-other-windows)
+               (ivy-set-view-recur (cadr view)))
+              (t
+               (switch-to-buffer
+                buffer nil 'force-same-window)))))))
 
 (defun ivy--switch-buffer-other-window-action (buffer)
   "Switch to BUFFER in other window.
@@ -2016,17 +2662,65 @@ BUFFER may be a string or nil."
     ivy--rename-buffer-action
     "rename")))
 
+(defun ivy--switch-buffer-matcher (regexp candidates)
+  "Return REGEXP-matching CANDIDATES.
+Skip buffers that match `ivy-ignore-buffers'."
+  (let ((res (ivy--re-filter regexp candidates)))
+    (if (or (null ivy-use-ignore)
+            (null ivy-ignore-buffers))
+        res
+      (or (cl-remove-if
+           (lambda (buf)
+             (cl-find-if
+              (lambda (f-or-r)
+                (if (functionp f-or-r)
+                    (funcall f-or-r buf)
+                  (string-match-p f-or-r buf)))
+              ivy-ignore-buffers))
+           res)
+          res))))
+
+(ivy-set-display-transformer
+ 'ivy-switch-buffer 'ivy-switch-buffer-transformer)
+(ivy-set-display-transformer
+ 'internal-complete-buffer 'ivy-switch-buffer-transformer)
+
+(defun ivy-switch-buffer-transformer (str)
+  (let ((b (get-buffer str)))
+    (if (and b
+             (buffer-file-name b)
+             (buffer-modified-p b))
+        (propertize str 'face 'ivy-modified-buffer)
+      str)))
+
+(defun ivy-switch-buffer-occur ()
+  "Occur function for `ivy-switch-buffer' that uses `ibuffer'."
+  (let* ((cand-regexp
+          (concat "\\(" (mapconcat #'regexp-quote ivy--old-cands "\\|") "\\)"))
+         (new-qualifier `((name . ,cand-regexp))))
+    (ibuffer nil (buffer-name) new-qualifier)))
+
 ;;;###autoload
 (defun ivy-switch-buffer ()
   "Switch to another buffer."
   (interactive)
-  (if (not ivy-mode)
-      (call-interactively 'switch-to-buffer)
-    (let ((this-command 'ivy-switch-buffer))
-      (ivy-read "Switch to buffer: " 'internal-complete-buffer
-                :preselect (buffer-name (other-buffer (current-buffer)))
-                :action #'ivy--switch-buffer-action
-                :keymap ivy-switch-buffer-map))))
+  (let ((this-command 'ivy-switch-buffer))
+    (ivy-read "Switch to buffer: " 'internal-complete-buffer
+              :matcher #'ivy--switch-buffer-matcher
+              :preselect (buffer-name (other-buffer (current-buffer)))
+              :action #'ivy--switch-buffer-action
+              :keymap ivy-switch-buffer-map
+              :caller 'ivy-switch-buffer)))
+
+;;;###autoload
+(defun ivy-switch-buffer-other-window ()
+  "Switch to another buffer in another window."
+  (interactive)
+  (ivy-read "Switch to buffer in other window: " 'internal-complete-buffer
+            :preselect (buffer-name (other-buffer (current-buffer)))
+            :action #'ivy--switch-buffer-other-window-action
+            :keymap ivy-switch-buffer-map
+            :caller 'ivy-switch-buffer-other-window))
 
 ;;;###autoload
 (defun ivy-recentf ()
@@ -2036,7 +2730,8 @@ BUFFER may be a string or nil."
             :action
             (lambda (f)
               (with-ivy-window
-                (find-file f)))))
+                (find-file f)))
+            :caller 'ivy-recentf))
 
 (defun ivy-yank-word ()
   "Pull next word from buffer into search string."
@@ -2064,74 +2759,6 @@ If the region is active, forward to `kill-ring-save' instead."
       ivy--old-cands
       "\n"))))
 
-(defvar-local ivy-occur-action nil
-  "Function to call for each line in *ivy-occur* buffer.")
-
-(defvar-local ivy-occur-last nil
-  "Buffer-local value of `ivy-last'.")
-
-(defvar ivy-occur-map
-  (let ((map (make-sparse-keymap)))
-    (define-key map [mouse-1] 'ivy-occur-click)
-    (define-key map (kbd "RET") 'ivy-occur-press)
-    map)
-  "Keymap used in *ivy-occur* buffers.")
-
-(defun ivy-occur ()
-  "Stop completion and put the current matches into a new buffer.
-
-The new buffer will also remember the current action.
-
-While in the *ivy-occur* buffer, selecting a cadidate with RET or
-a mouse click will call the action for that candidate.
-
-It's possible to have an unlimited amount of *ivy-occur* buffers."
-  (interactive)
-  (ivy-quit-and-run
-   (let (caller)
-     (pop-to-buffer
-      (generate-new-buffer
-       (format "*ivy-occur%s*"
-               (if (setq caller (ivy-state-caller ivy-last))
-                   (concat " " (prin1-to-string caller))
-                 ""))))
-     (read-only-mode)
-     (setq ivy-occur-action (ivy--get-action ivy-last))
-     (setq-local ivy--directory ivy--directory)
-     (setq ivy-occur-last ivy-last)
-     (let ((inhibit-read-only t))
-       (erase-buffer)
-       (insert (format "%d candidates:\n" (length ivy--old-cands)))
-       (dolist (cand ivy--old-cands)
-         (let ((str (concat "    " cand)))
-           (add-text-properties
-            0 (length str)
-            `(mouse-face
-              highlight
-              help-echo "mouse-1: call ivy-action"
-              keymap ,ivy-occur-map)
-            str)
-           (insert str "\n")))))))
-
-(defun ivy-occur-click (event)
-  "Execute action for the current candidate.
-EVENT gives the mouse position."
-  (interactive "e")
-  (let ((window (posn-window (event-end event)))
-        (pos (posn-point (event-end event))))
-    (with-current-buffer (window-buffer window)
-      (goto-char pos)
-      (ivy-occur-press))))
-
-(defun ivy-occur-press ()
-  "Execute action for the current candidate."
-  (interactive)
-  (let ((ivy-last ivy-occur-last))
-    (funcall ivy-occur-action
-             (buffer-substring
-              (+ 4 (line-beginning-position))
-              (line-end-position)))))
-
 (defun ivy-insert-current ()
   "Make the current candidate into current input.
 Don't finish completion."
@@ -2152,11 +2779,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)
@@ -2173,6 +2801,267 @@ The selected history element will be inserted into the minibufer."
   (setq ivy--all-candidates
         (ivy--filter ivy-text ivy--all-candidates)))
 
+;;* Occur
+(defvar-local ivy-occur-last nil
+  "Buffer-local value of `ivy-last'.
+Can't re-use `ivy-last' because using e.g. `swiper' in the same
+buffer would modify `ivy-last'.")
+
+(defvar ivy-occur-mode-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map [mouse-1] 'ivy-occur-click)
+    (define-key map (kbd "RET") 'ivy-occur-press)
+    (define-key map (kbd "j") 'ivy-occur-next-line)
+    (define-key map (kbd "k") 'ivy-occur-previous-line)
+    (define-key map (kbd "h") 'backward-char)
+    (define-key map (kbd "l") 'forward-char)
+    (define-key map (kbd "f") 'ivy-occur-press)
+    (define-key map (kbd "g") 'ivy-occur-revert-buffer)
+    (define-key map (kbd "a") 'ivy-occur-read-action)
+    (define-key map (kbd "o") 'ivy-occur-dispatch)
+    (define-key map (kbd "c") 'ivy-occur-toggle-calling)
+    (define-key map (kbd "q") 'quit-window)
+    map)
+  "Keymap for Ivy Occur mode.")
+
+(defun ivy-occur-toggle-calling ()
+  "Toggle `ivy-calling'."
+  (interactive)
+  (if (setq ivy-calling (not ivy-calling))
+      (progn
+        (setq mode-name "Ivy-Occur [calling]")
+        (ivy-occur-press))
+    (setq mode-name "Ivy-Occur"))
+  (force-mode-line-update))
+
+(defun ivy-occur-next-line (&optional arg)
+  "Move the cursor down ARG lines.
+When `ivy-calling' isn't nil, call `ivy-occur-press'."
+  (interactive "p")
+  (forward-line arg)
+  (when ivy-calling
+    (ivy-occur-press)))
+
+(defun ivy-occur-previous-line (&optional arg)
+  "Move the cursor up ARG lines.
+When `ivy-calling' isn't nil, call `ivy-occur-press'."
+  (interactive "p")
+  (forward-line (- arg))
+  (when ivy-calling
+    (ivy-occur-press)))
+
+(define-derived-mode ivy-occur-mode fundamental-mode "Ivy-Occur"
+  "Major mode for output from \\[ivy-occur].
+
+\\{ivy-occur-mode-map}")
+
+(defvar ivy-occur-grep-mode-map
+  (let ((map (copy-keymap ivy-occur-mode-map)))
+    (define-key map (kbd "C-x C-q") 'ivy-wgrep-change-to-wgrep-mode)
+    map)
+  "Keymap for Ivy Occur Grep mode.")
+
+(define-derived-mode ivy-occur-grep-mode grep-mode "Ivy-Occur"
+  "Major mode for output from \\[ivy-occur].
+
+\\{ivy-occur-grep-mode-map}")
+
+(defvar ivy--occurs-list nil
+  "A list of custom occur generators per command.")
+
+(defun ivy-set-occur (cmd occur)
+  "Assign CMD a custom OCCUR function."
+  (setq ivy--occurs-list
+        (plist-put ivy--occurs-list cmd occur)))
+
+(ivy-set-occur 'ivy-switch-buffer 'ivy-switch-buffer-occur)
+(ivy-set-occur 'ivy-switch-buffer-other-window 'ivy-switch-buffer-occur)
+
+(defun ivy--occur-insert-lines (cands)
+  (dolist (str cands)
+    (add-text-properties
+     0 (length str)
+     `(mouse-face
+       highlight
+       help-echo "mouse-1: call ivy-action")
+     str)
+    (insert str "\n")))
+
+(defun ivy-occur ()
+  "Stop completion and put the current matches into a new buffer.
+
+The new buffer remembers current action(s).
+
+While in the *ivy-occur* buffer, selecting a candidate with RET or
+a mouse click will call the appropriate action for that candidate.
+
+There is no limit on the number of *ivy-occur* buffers."
+  (interactive)
+  (if (not (window-minibuffer-p))
+      (user-error "No completion session is active")
+    (let* ((caller (ivy-state-caller ivy-last))
+           (occur-fn (plist-get ivy--occurs-list caller))
+           (buffer
+            (generate-new-buffer
+             (format "*ivy-occur%s \"%s\"*"
+                     (if caller
+                         (concat " " (prin1-to-string caller))
+                       "")
+                     ivy-text))))
+      (with-current-buffer buffer
+        (let ((inhibit-read-only t))
+          (erase-buffer)
+          (if occur-fn
+              (funcall occur-fn)
+            (ivy-occur-mode)
+            (insert (format "%d candidates:\n" (length ivy--old-cands)))
+            (ivy--occur-insert-lines
+             (mapcar
+              (lambda (cand) (concat "    " cand))
+              ivy--old-cands))))
+        (setf (ivy-state-text ivy-last) ivy-text)
+        (setq ivy-occur-last ivy-last)
+        (setq-local ivy--directory ivy--directory))
+      (ivy-exit-with-action
+       `(lambda (_) (pop-to-buffer ,buffer))))))
+
+(defun ivy-occur-revert-buffer ()
+  "Refresh the buffer making it up-to date with the collection.
+
+Currently only works for `swiper'. In that specific case, the
+*ivy-occur* buffer becomes nearly useless as the orignal buffer
+is updated, since the line numbers no longer match.
+
+Calling this function is as if you called `ivy-occur' on the
+updated original buffer."
+  (interactive)
+  (let ((caller (ivy-state-caller ivy-occur-last))
+        (ivy-last ivy-occur-last))
+    (cond ((eq caller 'swiper)
+           (let ((buffer (ivy-state-buffer ivy-occur-last)))
+             (unless (buffer-live-p buffer)
+               (error "buffer was killed"))
+             (let ((inhibit-read-only t))
+               (erase-buffer)
+               (funcall (plist-get ivy--occurs-list caller) t))))
+          ((memq caller '(counsel-git-grep counsel-grep counsel-ag))
+           (let ((inhibit-read-only t))
+             (erase-buffer)
+             (funcall (plist-get ivy--occurs-list caller)))))))
+
+(declare-function wgrep-change-to-wgrep-mode "ext:wgrep")
+
+(defun ivy-wgrep-change-to-wgrep-mode ()
+  "Forward to `wgrep-change-to-wgrep-mode'."
+  (interactive)
+  (if (require 'wgrep nil 'noerror)
+      (wgrep-change-to-wgrep-mode)
+    (error "Package wgrep isn't installed")))
+
+(defun ivy-occur-read-action ()
+  "Select one of the available actions as the current one."
+  (interactive)
+  (let ((ivy-last ivy-occur-last))
+    (ivy-read-action)))
+
+(defun ivy-occur-dispatch ()
+  "Call one of the available actions on the current item."
+  (interactive)
+  (let* ((state-action (ivy-state-action ivy-occur-last))
+         (actions (if (symbolp state-action)
+                      state-action
+                    (copy-sequence state-action))))
+    (unwind-protect
+         (progn
+           (ivy-occur-read-action)
+           (ivy-occur-press))
+      (setf (ivy-state-action ivy-occur-last) actions))))
+
+(defun ivy-occur-click (event)
+  "Execute action for the current candidate.
+EVENT gives the mouse position."
+  (interactive "e")
+  (let ((window (posn-window (event-end event)))
+        (pos (posn-point (event-end event))))
+    (with-current-buffer (window-buffer window)
+      (goto-char pos)
+      (ivy-occur-press))))
+
+(declare-function swiper--cleanup "swiper")
+(declare-function swiper--add-overlays "swiper")
+(defvar ivy-occur-timer nil)
+
+(defun ivy-occur-press ()
+  "Execute action for the current candidate."
+  (interactive)
+  (when (save-excursion
+          (beginning-of-line)
+          (looking-at "\\(?:./\\|    \\)\\(.*\\)$"))
+    (when (memq (ivy-state-caller ivy-occur-last)
+                '(swiper counsel-git-grep counsel-grep counsel-ag
+                  counsel-describe-function counsel-describe-variable))
+      (let ((window (ivy-state-window ivy-occur-last)))
+        (when (or (null (window-live-p window))
+                  (equal window (selected-window)))
+          (save-selected-window
+            (setf (ivy-state-window ivy-occur-last)
+                  (display-buffer (ivy-state-buffer ivy-occur-last)
+                                  'display-buffer-pop-up-window))))))
+    (let* ((ivy-last ivy-occur-last)
+           (ivy-text (ivy-state-text ivy-last))
+           (str (buffer-substring
+                 (match-beginning 1)
+                 (match-end 1)))
+           (coll (ivy-state-collection ivy-last))
+           (action (ivy--get-action ivy-last))
+           (ivy-exit 'done))
+      (with-ivy-window
+        (funcall action
+                 (if (and (consp coll)
+                          (consp (car coll)))
+                     (cdr (assoc str coll))
+                   str))
+        (if (memq (ivy-state-caller ivy-last)
+                  '(swiper counsel-git-grep counsel-grep))
+            (with-current-buffer (window-buffer (selected-window))
+              (swiper--cleanup)
+              (swiper--add-overlays
+               (ivy--regex ivy-text)
+               (line-beginning-position)
+               (line-end-position)
+               (selected-window))
+              (when (timerp ivy-occur-timer)
+                (cancel-timer ivy-occur-timer))
+              (setq ivy-occur-timer (run-at-time 1.0 nil 'swiper--cleanup))))))))
+
+(defvar ivy-help-file (let ((default-directory
+                             (if load-file-name
+                                 (file-name-directory load-file-name)
+                               default-directory)))
+                        (if (file-exists-p "ivy-help.org")
+                            (expand-file-name "ivy-help.org")
+                          (if (file-exists-p "doc/ivy-help.org")
+                              (expand-file-name "doc/ivy-help.org"))))
+  "The file for `ivy-help'.")
+
+(defun ivy-help ()
+  "Help for `ivy'."
+  (interactive)
+  (let ((buf (get-buffer "*Ivy Help*")))
+    (unless buf
+      (setq buf (get-buffer-create "*Ivy Help*"))
+      (with-current-buffer buf
+        (insert-file-contents ivy-help-file)
+        (org-mode)
+        (view-mode)
+        (goto-char (point-min))))
+    (if (eq this-command 'ivy-help)
+        (switch-to-buffer buf)
+      (with-ivy-window
+        (pop-to-buffer buf)))
+    (view-mode)
+    (goto-char (point-min))))
+
 (provide 'ivy)
 
 ;;; ivy.el ends here