]> code.delx.au - gnu-emacs-elpa/commitdiff
Merge commit '09f86fca437f1b2e168093824e9d4ee0aea5130a' from swiper
authorOleh Krehel <ohwoeowho@gmail.com>
Fri, 21 Aug 2015 12:00:21 +0000 (14:00 +0200)
committerOleh Krehel <ohwoeowho@gmail.com>
Fri, 21 Aug 2015 12:00:21 +0000 (14:00 +0200)
1  2 
packages/swiper/counsel.el
packages/swiper/doc/Changelog.org
packages/swiper/ivy-hydra.el
packages/swiper/ivy-test.el
packages/swiper/ivy.el
packages/swiper/swiper.el

index 94c8608eee308daa3b2e87bb1a7e53f1c7815607,63c9552f8cfa499593f7e0710cefede247df9561..63c9552f8cfa499593f7e0710cefede247df9561
  
  (require 'swiper)
  
+ (defvar counsel-completion-beg nil
+   "Completion bounds start.")
+ (defvar counsel-completion-end nil
+   "Completion bounds end.")
  ;;;###autoload
  (defun counsel-el ()
    "Elisp completion at point."
                :initial-input str
                :action #'counsel--el-action)))
  
- (defvar counsel-completion-beg nil
-   "Completion bounds start.")
- (defvar counsel-completion-end nil
-   "Completion bounds end.")
  (defun counsel--el-action (symbol)
    "Insert SYMBOL, erasing the previous one."
    (when (stringp symbol)
               (match-string 1 s)
             s))))
  
+ (defun counsel-variable-list ()
+   "Return the list of all currently bound variables."
+   (let (cands)
+     (mapatoms
+      (lambda (vv)
+        (when (or (get vv 'variable-documentation)
+                  (and (boundp vv) (not (keywordp vv))))
+          (push (symbol-name vv) cands))))
+     cands))
  ;;;###autoload
  (defun counsel-describe-variable ()
    "Forward to `describe-variable'."
    (let ((enable-recursive-minibuffers t))
      (ivy-read
       "Describe variable: "
-      (let (cands)
-        (mapatoms
-         (lambda (vv)
-           (when (or (get vv 'variable-documentation)
-                     (and (boundp vv) (not (keywordp vv))))
-             (push (symbol-name vv) cands))))
-        cands)
+      (counsel-variable-list)
       :keymap counsel-describe-map
       :preselect (counsel-symbol-at-point)
       :history 'counsel-describe-symbol-history
                 (describe-variable
                  (intern x))))))
  
+ (ivy-set-actions
+  'counsel-describe-variable
+  '(("i" counsel-info-lookup-symbol "info")
+    ("d" counsel--find-symbol "definition")))
+ (ivy-set-actions
+  'counsel-describe-function
+  '(("i" counsel-info-lookup-symbol "info")
+    ("d" counsel--find-symbol "definition")))
  ;;;###autoload
  (defun counsel-describe-function ()
    "Forward to `describe-function'."
  (defvar counsel--git-grep-count nil
    "Store the line count in current repository.")
  
+ (defun counsel-more-chars (n)
+   "Return two fake candidates prompting for at least N input."
+   (list ""
+         (format "%d chars more" (- n (length ivy-text)))))
  (defun counsel-git-grep-function (string &optional _pred &rest _unused)
    "Grep in the current git repository for STRING."
    (if (and (> counsel--git-grep-count 20000)
             (< (length string) 3))
-       (progn
-         (setq ivy--full-length counsel--git-grep-count)
-         (list ""
-               (format "%d chars more" (- 3 (length ivy-text)))))
+       (counsel-more-chars 3)
      (let* ((default-directory counsel--git-grep-dir)
             (cmd (format "git --no-pager grep --full-name -n --no-color -i -e %S"
-                         (ivy--regex string t)))
-            res)
+                         (ivy--regex string t))))
        (if (<= counsel--git-grep-count 20000)
-           (progn
-             (setq res (shell-command-to-string cmd))
-             (setq ivy--full-length nil)
-             (split-string res "\n" t))
-         (setq ivy--full-length -1)
+           (split-string (shell-command-to-string cmd) "\n" t)
          (counsel--gg-candidates (ivy--regex string))
          nil))))
  
  
  (defun counsel-git-grep-recenter ()
    (interactive)
-   (with-selected-window (ivy-state-window ivy-last)
+   (with-ivy-window
      (counsel-git-grep-action ivy--current)
      (recenter-top-bottom)))
  
  (defun counsel-git-grep-action (x)
    (when (string-match "\\`\\(.*?\\):\\([0-9]+\\):\\(.*\\)\\'" x)
-     (let ((file-name (match-string-no-properties 1 x))
-           (line-number (match-string-no-properties 2 x)))
-       (find-file (expand-file-name file-name counsel--git-grep-dir))
-       (goto-char (point-min))
-       (forward-line (1- (string-to-number line-number)))
-       (re-search-forward (ivy--regex ivy-text t) (line-end-position) t)
-       (unless (eq ivy-exit 'done)
-         (setq swiper--window (selected-window))
-         (swiper--cleanup)
-         (swiper--add-overlays (ivy--regex ivy-text))))))
+     (with-ivy-window
+       (let ((file-name (match-string-no-properties 1 x))
+             (line-number (match-string-no-properties 2 x)))
+         (find-file (expand-file-name file-name counsel--git-grep-dir))
+         (goto-char (point-min))
+         (forward-line (1- (string-to-number line-number)))
+         (re-search-forward (ivy--regex ivy-text t) (line-end-position) t)
+         (unless (eq ivy-exit 'done)
+           (swiper--cleanup)
+           (swiper--add-overlays (ivy--regex ivy-text)))))))
  
  (defvar counsel-git-grep-history nil
    "History for `counsel-git-grep'.")
  
  ;;;###autoload
  (defun counsel-git-grep (&optional initial-input)
-   "Grep for a string in the current git repository."
+   "Grep for a string in the current git repository.
+ INITIAL-INPUT can be given as the initial minibuffer input."
    (interactive)
    (setq counsel--git-grep-dir
          (locate-dominating-file default-directory ".git"))
    (if (null counsel--git-grep-dir)
        (error "Not in a git repository")
      (setq counsel--git-grep-count (counsel--gg-count "" t))
-     (ivy-read "pattern: " 'counsel-git-grep-function
+     (ivy-read "git grep: " 'counsel-git-grep-function
                :initial-input initial-input
                :matcher #'counsel-git-grep-matcher
-               :dynamic-collection (when (> counsel--git-grep-count 20000)
-                                     'counsel-git-grep-function)
+               :dynamic-collection (> counsel--git-grep-count 20000)
                :keymap counsel-git-grep-map
                :action #'counsel-git-grep-action
                :unwind #'swiper--cleanup
  
  (declare-function ffap-guesser "ffap")
  
+ (defvar counsel-find-file-map (make-sparse-keymap))
  ;;;###autoload
  (defun counsel-find-file ()
    "Forward to `find-file'."
              :matcher #'counsel--find-file-matcher
              :action
              (lambda (x)
-               (find-file (expand-file-name x ivy--directory)))
+               (with-ivy-window
+                 (find-file (expand-file-name x ivy--directory))))
              :preselect (when counsel-find-file-at-point
                           (require 'ffap)
                           (ffap-guesser))
              :require-match 'confirm-after-completion
-             :history 'file-name-history))
+             :history 'file-name-history
+             :keymap counsel-find-file-map))
  
  (defcustom counsel-find-file-ignore-regexp nil
    "A regexp of files to ignore while in `counsel-find-file'.
@@@ -397,13 -412,6 +412,6 @@@ Skip some dotfiles unless `ivy-text' re
                   candidates))
          (setq ivy--old-re regexp))))
  
- (defun counsel-locate-function (str &rest _u)
-   (if (< (length str) 3)
-       (list ""
-             (format "%d chars more" (- 3 (length ivy-text))))
-     (counsel--async-command
-      (concat "locate -i --regex " (ivy--regex str)))))
  (defun counsel--async-command (cmd)
    (let* ((counsel--process " *counsel*")
           (proc (get-process counsel--process))
          (with-current-buffer (process-buffer process)
            (setq ivy--all-candidates (split-string (buffer-string) "\n" t))
            (setq ivy--old-cands ivy--all-candidates))
-         (ivy--insert-minibuffer
-          (ivy--format ivy--all-candidates)))
+         (ivy--exhibit))
      (if (string= event "exited abnormally with code 1\n")
-         (message "Error"))))
+         (progn
+           (setq ivy--all-candidates '("Error"))
+           (setq ivy--old-cands ivy--all-candidates)
+           (ivy--exhibit)))))
+ (defun counsel-locate-action-extern (x)
+   "Use xdg-open shell command on X."
+   (call-process shell-file-name nil
+                 nil nil
+                 shell-command-switch
+                 (format "xdg-open %s" (shell-quote-argument x))))
+ (declare-function dired-jump "dired-x")
+ (defun counsel-locate-action-dired (x)
+   "Use `dired-jump' on X."
+   (dired-jump nil x))
+ (defvar counsel-locate-history nil
+   "History for `counsel-locate'.")
+ (ivy-set-actions
+  'counsel-locate
+  '(("x" counsel-locate-action-extern "xdg-open")
+    ("d" counsel-locate-action-dired "dired")))
+ (defun counsel-locate-function (str &rest _u)
+   (if (< (length str) 3)
+       (counsel-more-chars 3)
+     (counsel--async-command
+      (concat "locate -i --regex " (ivy--regex str)))
+     '("" "working...")))
  
  ;;;###autoload
  (defun counsel-locate ()
-   "Call locate."
+   "Call locate shell command."
    (interactive)
-   (ivy-read "pattern: " nil
-             :dynamic-collection #'counsel-locate-function
-             :action (lambda (val)
-                       (when val
-                         (find-file val)))))
+   (ivy-read "Locate: " #'counsel-locate-function
+             :dynamic-collection t
+             :history 'counsel-locate-history
+             :action (lambda (file)
+                       (when file
+                         (find-file file)))))
  
  (defun counsel--generic (completion-fn)
    "Complete thing at point with COMPLETION-FN."
@@@ -517,8 -555,12 +555,12 @@@ The libraries are offered from `load-pa
                           (get-text-property 0 'full-name x)))
                :keymap counsel-describe-map)))
  
+ (defvar counsel-gg-state nil
+   "The current state of candidates / count sync.")
  (defun counsel--gg-candidates (regex)
    "Return git grep candidates for REGEX."
+   (setq counsel-gg-state -2)
    (counsel--gg-count regex)
    (let* ((default-directory counsel--git-grep-dir)
           (counsel-gg-process " *counsel-gg*")
          (with-current-buffer (process-buffer process)
            (setq ivy--all-candidates (split-string (buffer-string) "\n" t))
            (setq ivy--old-cands ivy--all-candidates))
-         (unless (eq ivy--full-length -1)
-           (ivy--insert-minibuffer
-            (ivy--format ivy--all-candidates))))
+         (when (= 0 (cl-incf counsel-gg-state))
+           (ivy--exhibit)))
      (if (string= event "exited abnormally with code 1\n")
-         (message "Error"))))
+         (progn
+           (setq ivy--all-candidates '("Error"))
+           (setq ivy--old-cands ivy--all-candidates)
+           (ivy--exhibit)))))
  
  (defun counsel--gg-count (regex &optional no-async)
    "Quickly and asynchronously count the amount of git grep REGEX matches.
@@@ -574,8 -618,8 +618,8 @@@ When NO-ASYNC is non-nil, do it synchro
               (when (string= event "finished\n")
                 (with-current-buffer (process-buffer process)
                   (setq ivy--full-length (string-to-number (buffer-string))))
-                (ivy--insert-minibuffer
-                 (ivy--format ivy--all-candidates)))))))))
+                (when (= 0 (cl-incf counsel-gg-state))
+                  (ivy--exhibit)))))))))
  
  (defun counsel--M-x-transformer (cmd)
    "Add a binding to CMD if it's bound in the current window.
@@@ -608,7 -652,7 +652,7 @@@ Optional INITIAL-INPUT is the initial i
            (lambda (cands)
              (funcall
               store
-              (with-selected-window (ivy-state-window ivy-last)
+              (with-ivy-window
                 (mapcar #'counsel--M-x-transformer cands)))))
           (cands obarray)
           (pred 'commandp)
@@@ -660,6 -704,213 +704,213 @@@ Usable with `ivy-resume', `ivy-next-lin
                      (custom-available-themes))
              :action #'counsel--load-theme-action))
  
+ (defvar rhythmbox-library)
+ (declare-function rhythmbox-load-library "ext:helm-rhythmbox")
+ (declare-function dbus-call-method "dbus")
+ (declare-function rhythmbox-song-uri "ext:helm-rhythmbox")
+ (declare-function helm-rhythmbox-candidates "ext:helm-rhythmbox")
+ (defun counsel-rhythmbox-enqueue-song (song)
+   "Let Rhythmbox enqueue SONG."
+   (let ((service "org.gnome.Rhythmbox3")
+         (path "/org/gnome/Rhythmbox3/PlayQueue")
+         (interface "org.gnome.Rhythmbox3.PlayQueue"))
+     (dbus-call-method :session service path interface
+                       "AddToQueue" (rhythmbox-song-uri song))))
+ (defvar counsel-rhythmbox-history nil
+   "History for `counsel-rhythmbox'.")
+ ;;;###autoload
+ (defun counsel-rhythmbox ()
+   "Choose a song from the Rhythmbox library to play or enqueue."
+   (interactive)
+   (unless (require 'helm-rhythmbox nil t)
+     (error "Please install `helm-rhythmbox'"))
+   (unless rhythmbox-library
+     (rhythmbox-load-library)
+     (while (null rhythmbox-library)
+       (sit-for 0.1)))
+   (ivy-read "Rhythmbox: "
+             (helm-rhythmbox-candidates)
+             :history 'counsel-rhythmbox-history
+             :action
+             '(1
+               ("p" helm-rhythmbox-play-song "Play song")
+               ("e" counsel-rhythmbox-enqueue-song "Enqueue song"))))
+ (defvar counsel-org-tags nil
+   "Store the current list of tags.")
+ (defvar org-outline-regexp)
+ (defvar org-indent-mode)
+ (defvar org-indent-indentation-per-level)
+ (defvar org-tags-column)
+ (declare-function org-get-tags-string "org")
+ (declare-function org-move-to-column "org")
+ (defun counsel-org-change-tags (tags)
+   (let ((current (org-get-tags-string))
+         (col (current-column))
+         level)
+     ;; Insert new tags at the correct column
+     (beginning-of-line 1)
+     (setq level (or (and (looking-at org-outline-regexp)
+                          (- (match-end 0) (point) 1))
+                     1))
+     (cond
+       ((and (equal current "") (equal tags "")))
+       ((re-search-forward
+         (concat "\\([ \t]*" (regexp-quote current) "\\)[ \t]*$")
+         (point-at-eol) t)
+        (if (equal tags "")
+            (delete-region
+             (match-beginning 0)
+             (match-end 0))
+          (goto-char (match-beginning 0))
+          (let* ((c0 (current-column))
+                 ;; compute offset for the case of org-indent-mode active
+                 (di (if (bound-and-true-p org-indent-mode)
+                         (* (1- org-indent-indentation-per-level) (1- level))
+                       0))
+                 (p0 (if (equal (char-before) ?*) (1+ (point)) (point)))
+                 (tc (+ org-tags-column (if (> org-tags-column 0) (- di) di)))
+                 (c1 (max (1+ c0) (if (> tc 0) tc (- (- tc) (string-width tags)))))
+                 (rpl (concat (make-string (max 0 (- c1 c0)) ?\ ) tags)))
+            (replace-match rpl t t)
+            (and c0 indent-tabs-mode (tabify p0 (point)))
+            tags)))
+       (t (error "Tags alignment failed")))
+     (org-move-to-column col)))
+ (defun counsel-org-tag-action (x)
+   (if (member x counsel-org-tags)
+       (progn
+         (setq counsel-org-tags (delete x counsel-org-tags)))
+     (setq counsel-org-tags (append counsel-org-tags (list x)))
+     (unless (member x ivy--all-candidates)
+       (setq ivy--all-candidates (append ivy--all-candidates (list x)))))
+   (let ((prompt (counsel-org-tag-prompt)))
+     (setf (ivy-state-prompt ivy-last) prompt)
+     (setq ivy--prompt (concat "%-4d " prompt)))
+   (cond ((memq this-command '(ivy-done ivy-alt-done))
+          (counsel-org-change-tags
+           (if counsel-org-tags
+               (format ":%s:"
+                       (mapconcat #'identity counsel-org-tags ":"))
+             "")))
+         ((eq this-command 'ivy-call)
+          (delete-minibuffer-contents))))
+ (defun counsel-org-tag-prompt ()
+   (format "Tags (%s): "
+           (mapconcat #'identity counsel-org-tags ", ")))
+ (defvar org-setting-tags)
+ (defvar org-last-tags-completion-table)
+ (defvar org-tag-persistent-alist)
+ (defvar org-tag-alist)
+ (defvar org-complete-tags-always-offer-all-agenda-tags)
+ (declare-function org-at-heading-p "org")
+ (declare-function org-back-to-heading "org")
+ (declare-function org-get-buffer-tags "org")
+ (declare-function org-global-tags-completion-table "org")
+ (declare-function org-agenda-files "org")
+ (declare-function org-agenda-set-tags "org-agenda")
+ ;;;###autoload
+ (defun counsel-org-tag ()
+   "Add or remove tags in org-mode."
+   (interactive)
+   (save-excursion
+     (unless (org-at-heading-p)
+       (org-back-to-heading t))
+     (setq counsel-org-tags (split-string (org-get-tags-string) ":" t))
+     (let ((org-setting-tags t)
+           (org-last-tags-completion-table
+            (append org-tag-persistent-alist
+                    (or org-tag-alist (org-get-buffer-tags))
+                    (and
+                     org-complete-tags-always-offer-all-agenda-tags
+                     (org-global-tags-completion-table
+                      (org-agenda-files))))))
+       (ivy-read (counsel-org-tag-prompt)
+                 (lambda (str &rest _unused)
+                   (delete-dups
+                    (all-completions str 'org-tags-completion-function)))
+                 :history 'org-tags-history
+                 :action 'counsel-org-tag-action))))
+ ;;;###autoload
+ (defun counsel-org-tag-agenda ()
+   "Set tags for the current agenda item."
+   (interactive)
+   (let ((store (symbol-function 'org-set-tags)))
+     (unwind-protect
+          (progn
+            (fset 'org-set-tags
+                  (symbol-function 'counsel-org-tag))
+            (org-agenda-set-tags nil nil))
+       (fset 'org-set-tags store))))
+ (defun counsel-ag-function (string &optional _pred &rest _unused)
+   "Grep in the current directory for STRING."
+   (if (< (length string) 3)
+       (counsel-more-chars 3)
+     (let ((regex (replace-regexp-in-string
+                   "\\\\)" ")"
+                   (replace-regexp-in-string
+                    "\\\\(" "("
+                    (ivy--regex string)))))
+       (counsel--async-command
+        (format "ag --noheading --nocolor %S" regex))
+       nil)))
+ (defun counsel-ag (&optional initial-input)
+   "Grep for a string in the current directory using ag.
+ INITIAL-INPUT can be given as the initial minibuffer input."
+   (interactive)
+   (setq counsel--git-grep-dir default-directory)
+   (ivy-read "ag: " 'counsel-ag-function
+             :initial-input initial-input
+             :dynamic-collection t
+             :history 'counsel-git-grep-history
+             :action #'counsel-git-grep-action
+             :unwind #'swiper--cleanup))
+ (defun counsel-recoll-function (string &optional _pred &rest _unused)
+   "Grep in the current directory for STRING."
+   (if (< (length string) 3)
+       (counsel-more-chars 3)
+     (counsel--async-command
+      (format "recoll -t -b '%s'" string))
+     nil))
+ ;; This command uses the recollq command line tool that comes together
+ ;; with the recoll (the document indexing database) source:
+ ;;     http://www.lesbonscomptes.com/recoll/download.html
+ ;; You need to build it yourself (together with recoll):
+ ;;     cd ./query && make && sudo cp recollq /usr/local/bin
+ ;; You can try the GUI version of recoll with:
+ ;;     sudo apt-get install recoll
+ ;; Unfortunately, that does not install recollq.
+ (defun counsel-recoll (&optional initial-input)
+   "Search for a string in the recoll database.
+ You'll be given a list of files that match.
+ Selecting a file will launch `swiper' for that file.
+ INITIAL-INPUT can be given as the initial minibuffer input."
+   (interactive)
+   (ivy-read "recoll: " 'counsel-recoll-function
+             :initial-input initial-input
+             :dynamic-collection t
+             :history 'counsel-git-grep-history
+             :action (lambda (x)
+                       (when (string-match "file://\\(.*\\)\\'" x)
+                         (let ((file-name (match-string 1 x)))
+                           (find-file file-name)
+                           (unless (string-match "pdf$" x)
+                             (swiper ivy-text)))))))
  
  (provide 'counsel)
  
index 0000000000000000000000000000000000000000,0f5ac2c4f3b13d655f0c1a70809dd72573b21363..0f5ac2c4f3b13d655f0c1a70809dd72573b21363
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,296 +1,296 @@@
+ #+OPTIONS: toc:nil
+ * 0.6.0
+ ** Fixes
+ *** =swiper-avy= should use only the current window
+ Not all windows. See [[https://github.com/abo-abo/swiper/issues/117][#117]].
+ *** fix wrap-around for =ivy-next-line=
+ See [[https://github.com/abo-abo/swiper/issues/118][#118]].
+ *** =swiper-avy= should do nothing for empty input
+ See [[https://github.com/abo-abo/avy/issues/50][#50]].
+ *** =ivy-alt-done= should require TRAMP if necessary
+ See [[https://github.com/abo-abo/swiper/pull/145][#145]].
+ *** =swiper-query-replace= shouldn't miss the first occurrence
+ See [[https://github.com/abo-abo/swiper/pull/144][#144]].
+ *** =swiper= should not deactivate mark
+ *** =ivy-mode= should not switch to TRAMP for certain input
+ See [[https://github.com/abo-abo/swiper/pull/145][#145]].
+ *** =counsel-find-file= should work better with TRAMP
+ "/ssh:foo" should not be cut off
+ See [[https://github.com/abo-abo/swiper/pull/145][#145]].
+ *** =counsel-find-file= supports Windows drive letters
+ See [[https://github.com/abo-abo/swiper/pull/155][#155]].
+ *** =counsel-file-file= should work better with files that contain "~"
+ See [[https://github.com/abo-abo/swiper/pull/157][#157]].
+ *** =counsel-M-x= should respect =ivy-format-function=
+ See [[https://github.com/abo-abo/swiper/pull/150][#150]].
+ *** =counsel-git-grep= should position better on exit
+ See [[https://github.com/abo-abo/swiper/pull/153][#153]].
+ *** =ivy-mode= should re-scale text to minibuffer height
+ See [[https://github.com/abo-abo/swiper/pull/151][#151]].
+ *** =counsel-unicode-char= should use action-style call
+ See [[https://github.com/abo-abo/swiper/pull/160][#160]].
+ *** =ivy-read= should allow % in prompt string
+ See [[https://github.com/abo-abo/swiper/pull/171][#171]].
+ *** =ivy-call= should execute in proper window
+ See [[https://github.com/abo-abo/swiper/pull/176][#176]].
+ ** New Features
+ *** =ivy-mode=
+ **** Open an Info file on the file system
+ When in =Info-mode=, press ~g~ and select either "(./)" or "(../)" to
+ switch to file name completion. That file will be opened with Info.
+ **** Account for =minibuffer-depth-indication-mode=
+ If you have =minibuffer-depth-indication-mode= on, the minibuffer
+ prompt will indicate the current depth.
+ See [[https://github.com/abo-abo/swiper/pull/134][#134]].
+ **** Add fuzzy matching function
+ To enable fuzzy matching, set your =ivy-re-builders-alist= accordingly:
+ #+begin_src elisp
+ (setq ivy-re-builders-alist
+       '((t . ivy--regex-fuzzy)))
+ #+end_src
+ See [[https://github.com/abo-abo/swiper/pull/136][#136]].
+ See also [[https://github.com/abo-abo/swiper/pull/142][#142]] for toggling fuzzy matching with ~C-o m~.
+ **** =case-fold-search= optimization
+ Bind case-fold-search to t when the input is all lower-case:
+ - input "the" matches both "the" and "The".
+ - input "The" matches only "The".
+ See [[https://github.com/abo-abo/swiper/pull/166][#166]].
+ **** Allow to see the candidate index a la =anzu= via =ivy-count-format=
+ To have this feature, use something like this:
+ #+begin_src elisp
+ (setq ivy-count-format "(%d/%d) ")
+ #+end_src
+ See [[https://github.com/abo-abo/swiper/pull/167][#167]].
+ You can also set this to nil, if you don't want any count, see [[https://github.com/abo-abo/swiper/pull/188][#188]].
+ **** Allow to add additional exit points for any command
+ Example for =ivy-switch-to-buffer=:
+ #+begin_src elisp
+ (ivy-set-actions
+  'ivy-switch-buffer
+  '(("k"
+     (lambda (x)
+       (kill-buffer x)
+       (ivy--reset-state ivy-last))
+     "kill")
+    ("j"
+     ivy--switch-buffer-other-window-action
+     "other")))
+ #+end_src
+ After this:
+ - use ~M-o k~ to kill a buffer
+ - use ~M-o j~ to switch to a buffer in other window
+ You can always use ~M-o o~ to access the default action. When there is
+ only one action, ~M-o~ does the same as ~C-m~.
+ See [[https://github.com/abo-abo/swiper/pull/164][#164]].
+ *** =counsel-describe-function= and =counsel-decribe-variable=
+ **** Add a binding to look up the symbol in info
+ Press ~C-,~ to look up the symbol in info, instead of the default
+ describe action.
+ See [[https://github.com/abo-abo/swiper/pull/121][#121]].
+ **** Handle symbol-at-point better in non-Elisp buffers
+ See [[https://github.com/abo-abo/swiper/pull/126][#126]].
+ *** =ivy-switch-buffer=
+ **** New face =ivy-virtual=
+ See [[https://github.com/abo-abo/swiper/pull/129][#129]].
+ **** Deal better with invisible buffers
+ See [[https://github.com/abo-abo/swiper/pull/135][#135]].
+ **** Add custom keymap
+ You can customize =ivy-switch-buffer-map=.
+ See [[https://github.com/abo-abo/swiper/pull/164][#164]].
+ **** Add extra actions
+ Add a =kill-buffer= action, and =switch-to-buffer-other-window= action.
+ *** =counsel-git-grep=
+ **** Add Async
+ Make it fully async: the process =git grep= will be killed and
+ restarted on new input. This results in almost no keyboard delay.
+ **** Own history variable
+ *** =swiper=
+ **** Own history variable
+ Having own history variable allows to get more use of ~M-p~, ~M-n~ and ~C-r~.
+ *** =counsel-el=
+ **** Switch to action-style call
+ This allows to make use of ~C-M-n~ and ~C-M-p~.
+ *** =counsel-locate=
+ **** Add Async
+ **** Add extra actions
+ In addition to the default action of opening a file add:
+ - =xdg-open= action
+ - =dired= action
+ Press ~M-o~ or ~C-o~ to access these actions.
+ **** Add own history
+ *** API
+ **** Add :matcher
+ A matcher is a function that accepts a regexp and a list of candidates
+ and returns the filtered list of candidates.
+ The default matcher is basically =cl-remove-if-not= + =string-match=.
+ If you'd like to customize this, pass your own matcher.
+ See =counsel-git-grep-matcher= for an example.
+ **** Allow to customize the initial input for all commands
+ Customize =ivy-initial-inputs-alist= for this.
+ See [[https://github.com/abo-abo/swiper/pull/140][#140]].
+ **** =ivy-sort-functions-alist= should also examine =this-command=
+ **** :dynamic-collection is now a boolean
+ Pass the collection function as the second var instead.
+ ** New Commands
+ *** =ivy-call=
+ Execute the current action for the current candidate without exiting
+ the minibuffer.  Bound to ~C-M-m~ or ~M-RET~ or ~C-o g~.
+ *** =counsel-find-file=
+ Forward to =find-file= with Ivy completion.
+ =ivy-next-line-and-call= as well as =ivy-resume= should work for this command.
+ The variable =counsel-find-file-ignore-regexp= allows to ignore
+ certain files, like dot files.  Input a leading dot to see all files.
+ The variable =counsel-find-file-at-point= allows to automatically use
+ =ffap=.  You also can do it manually with ~M-n~ when the point is on a file name.
+ The variable =counsel-find-file-map= allows to customize the
+ minibuffer key bindings for this command.
+ Recommended binding:
+ #+begin_src elisp
+ (global-set-key (kbd "C-x C-f") 'counsel-find-file)
+ #+end_src
+ You can peek at files with ~C-M-n~ and ~C-M-p~.
+ See [[https://github.com/abo-abo/swiper/issues/122][#122]] and [[https://github.com/abo-abo/swiper/issues/123][#123]].
+ See [[https://github.com/abo-abo/swiper/pull/152][#152]] about ~M-n~, ~M-p~ and ~M-i~ switching directories when necessary.
+ *** =ivy-recentf=
+ Find a file on =recentf-list=.
+ Note that if your set =ivy-use-virtual-buffers=, =recentf-list= is
+ merged into candidates list for =ivy-switch-buffer=. But if you want
+ it separately, you can use this command.
+ See [[https://github.com/abo-abo/swiper/issues/124][#124]].
+ *** =ivy-yank-word=
+ Add word at point to minibuffer input.
+ This is similar to what ~C-w~ does for =isearch=.  However it's bound
+ to ~M-j~ instead of ~C-w~, since ~C-w~ is bound to =kill-region= - a
+ useful command.
+ See [[https://github.com/abo-abo/swiper/issues/125][#125]].
+ *** =counsel-M-x=
+ Forward to =execute-extended-command= with Ivy completion.
+ The candidate list will also display the key binding for each bound command.
+ This command will piggyback on =smex= for sorting, if =smex= is installed.
+ Use =counsel-M-x-initial-input= to customize the initial input for
+ this command.  By default, it's "^" - the regex character that
+ indicates beginning of string.  This results in much faster matching,
+ since you usually type the command name from the start.
+ See [[https://github.com/abo-abo/swiper/pull/136][#136]] and [[https://github.com/abo-abo/swiper/pull/138][#138]].
+ *** =hydra-ivy=
+ Press ~C-o~ to toggle the Hydra for Ivy.
+ It gives access to shorter bindings and many customizable options.
+ Use ~C-o >~ to grow the minibuffer.
+ Use ~C-o <~ to shrink the minibuffer.
+ See [[https://github.com/abo-abo/swiper/pull/151][#151]].
+ *** =ivy-toggle-calling=
+ Toggle executing the current action each time a new candidate is selected.
+ This command is bound to ~C-o c~.
+ To explain how this is useful: ~C-M-m C-M-f C-M-f C-M-f~  is equivalent to ~C-o cjjj~.
+ *** =ivy-insert-current=
+ Inserts the current candidate into the minibuffer.
+ Press ~M-i~ if you want something close to the current candidate. You
+ can follow up with an edit and select.
+ I find this very useful when creating new files with a similar name to
+ the existing file: ~C-x C-f M-i~ + a bit of editing is very fast.
+ See [[https://github.com/abo-abo/swiper/pull/141][#141]].
+ *** =counsel-load-theme=
+ Forward to =load-theme= with Ivy completion. Allows to rapidly try themes (e.g. with ~C-M-n~).
+ *** =ivy-reverse-i-search=
+ Allow to recursively match history with ~C-r~.
+ I like this command from bash shell. The usual way to search through
+ history is with ~M-p~ and ~M-n~.  Using =ivy-reverse-i-search= will
+ open a recursive completion session with the current history as the
+ candidates.
+ *** =counsel-rhythmbox=
+ [[http://oremacs.com/2015/07/09/counsel-rhythmbox/][Control Rhythmbox from Emacs.]]
+ *** =ivy-dispatching-done=
+ Select an action for the current candidate and execute it. Bound to ~M-o~.
+ Some commands that support ~M-o~:
+ - =counsel-rhythmbox=
+ - =counsel-describe-function=
+ - =counsel-describe-variable=
+ - =ivy-switch-buffer=
+ - =counsel-locate=
+ *** =counsel-org-tag=
+ Forward to =org-set-tags= with Ivy completion.
+ Selecting any tag each time will toggle it on/off.
+ The current list of selected tags will be displayed in the prompt.
+ See [[https://github.com/abo-abo/swiper/pull/177][#177]] and [[https://github.com/abo-abo/swiper/pull/91][#91]].
+ *** =counsel-org-tag-agenda=
+ Forward to =org-agenda-set-tags= with Ivy completion.
+ See [[https://github.com/abo-abo/swiper/pull/177][#177]].
+ *** =counsel-ag=
+ Interactively =ag= using Ivy completion.
+ *** =counsel-recoll=
+ Use =recoll= with Ivy completion.
+ See [[http://oremacs.com/2015/07/27/counsel-recoll/][Using Recoll desktop search database with Emacs]].
+ Install recoll with =sudo apt-get install recoll=.
+ *** =swiper-from-isearch=
+ Start =swiper= from the current =isearch= input.
+ *** =ivy-immediate-done=
+ Use this command to exit the minibuffer choosing not the current
+ candidate, but the current text.  Bound to ~C-M-j~ or ~C-u C-j~.
+ See [[https://github.com/abo-abo/swiper/pull/183][#183]].
index 03e4d208204a7de9a158e93a66718c3931c7aecc,6ab1f9aebe79a8cf0daa0e702d251fea01d3da15..6ab1f9aebe79a8cf0daa0e702d251fea01d3da15
@@@ -30,7 -30,7 +30,7 @@@
  (require 'ivy)
  
  (eval-when-compile
-   (unless (package-installed-p 'hydra)
+   (unless (or (featurep 'hydra) (package-installed-p 'hydra))
      (defmacro defhydra (name &rest _)
        "This is a stub for the uninstalled `hydra' package."
        `(defun ,(intern (format "%S/body" name)) ()
  (defhydra hydra-ivy (:hint nil
                       :color pink)
    "
- ^^^^^^          ^Yes^     ^No^     ^Maybe^
- ^^^^^^^^^^^^^^---------------------------------------
- ^ ^ _k_ ^ ^     _f_ollow  _i_nsert _c_: calling %s(if ivy-calling \"on\" \"off\")
+ ^^^^^^          ^Yes^     ^No^     ^Maybe^           ^Action^
+ ^^^^^^^^^^^^^^---------------------------------------------------
+ ^ ^ _k_ ^ ^     _f_ollow  _i_nsert _c_: calling %s(if ivy-calling \"on\" \"off\")  _w_/_s_: %s(ivy-action-name)
  _h_ ^+^ _l_     _d_one    _o_ops   _m_: matcher %s(if (eq ivy--regex-function 'ivy--regex-fuzzy) \"fuzzy\" \"ivy\")
- ^ ^ _j_ ^ ^     ^ ^       ^ ^      _<_/_>_: shrink/grow window
+ ^ ^ _j_ ^ ^     _g_o      ^ ^      _<_/_>_: shrink/grow window
  "
    ;; arrows
    ("h" ivy-beginning-of-buffer)
    ("f" ivy-alt-done :exit nil)
    ("C-j" ivy-alt-done :exit nil)
    ("d" ivy-done :exit t)
+   ("g" ivy-call)
    ("C-m" ivy-done :exit t)
    ("c" ivy-toggle-calling)
    ("m" ivy-toggle-fuzzy)
    (">" ivy-minibuffer-grow)
-   ("<" ivy-minibuffer-shrink))
+   ("<" ivy-minibuffer-shrink)
+   ("w" ivy-prev-action)
+   ("s" ivy-next-action))
  
  (provide 'ivy-hydra)
  
index af0fc60b95fba572227fccbf66123cb183f19d6f,10dd8f98400516b90c6a55d84c7143bbf38fc34f..10dd8f98400516b90c6a55d84c7143bbf38fc34f
                     #("\nDESCRIPTION\nFUNCTION LETTERS\nSWITCHES\nDIAGNOSTICS\nEXAMPLE 1\nEXAMPLE 2\nEXAMPLE 3\nSEE ALSO\nAUTHOR"
                       0 90 (read-only nil)
                       90 96 (face ivy-current-match read-only nil)))))
+ (ert-deftest ivy--filter ()
+   (setq ivy-last (make-ivy-state))
+   (should (equal (ivy--filter "the" '("foo" "the" "The"))
+                  '("the" "The")))
+   (should (equal (ivy--filter "The" '("foo" "the" "The"))
+                  '("The"))))
diff --combined packages/swiper/ivy.el
index f64782cb940acf76ac32332e21f8e9784c22dca2,21197c3e397a54422ecf8315365ff0f459a50469..21197c3e397a54422ecf8315365ff0f459a50469
--- 2/ivy.el
  
  (defcustom ivy-count-format "%-4d "
    "The style of showing the current candidate count for `ivy-read'.
- Set this to nil if you don't want the count."
-   :type 'string)
+ Set this to nil 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."
+   :type '(choice (const :tag "Count disabled" nil) string))
  
  (defcustom ivy-wrap nil
    "Whether to wrap around after the first and last candidate."
@@@ -90,12 -92,22 +92,22 @@@ Only \"./\" and \"../\" apply here. The
    "When non-nil, add `recentf-mode' and bookmarks to the list of buffers."
    :type 'boolean)
  
+ (defvar ivy--actions-list nil
+   "A list of extra actions per command.")
+ (defun ivy-set-actions (cmd actions)
+   "Set CMD extra exit points to ACTIONS."
+   (setq ivy--actions-list
+         (plist-put ivy--actions-list cmd actions)))
  ;;* Keymap
  (require 'delsel)
  (defvar ivy-minibuffer-map
    (let ((map (make-sparse-keymap)))
      (define-key map (kbd "C-m") 'ivy-done)
+     (define-key map (kbd "C-M-m") 'ivy-call)
      (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 "M-j") 'ivy-yank-word)
      (define-key map (kbd "M-i") 'ivy-insert-current)
      (define-key map (kbd "C-o") 'hydra-ivy/body)
+     (define-key map (kbd "M-o") 'ivy-dispatching-done)
      (define-key map (kbd "C-k") 'ivy-kill-line)
+     (define-key map (kbd "S-SPC") 'ivy-restrict-to-matches)
      map)
    "Keymap used in the minibuffer.")
  (autoload 'hydra-ivy/body "ivy-hydra" "" t)
@@@ -223,6 -237,13 +237,13 @@@ When non-nil, it should contain one %d.
                      ,@body))
       (minibuffer-keyboard-quit)))
  
+ (defmacro with-ivy-window (&rest body)
+   "Execute BODY in the window from which `ivy-read' was called."
+   (declare (indent 0)
+            (debug t))
+   `(with-selected-window (ivy-state-window ivy-last)
+      ,@body))
  (defun ivy--done (text)
    "Insert TEXT and exit minibuffer."
    (if (and ivy--directory
           (insert ivy-text)
           (ivy--exhibit))))
  
+ (defun ivy-dispatching-done ()
+   "Select one of the available actions and call `ivy-done'."
+   (interactive)
+   (let ((actions (ivy-state-action ivy-last)))
+     (if (null (ivy--actionp actions))
+         (ivy-done)
+       (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"))
+              (key (string (read-key hint)))
+              (action (assoc key (cdr actions))))
+         (cond ((string= key "\a"))
+               ((null action)
+                (error "%s is not bound" key))
+               (t
+                (message "")
+                (ivy-set-action (nth 1 action))
+                (ivy-done)))))))
  (defun ivy-build-tramp-name (x)
    "Reconstruct X into a path.
  Is is a cons cell, related to `tramp-get-completion-function'."
@@@ -433,7 -482,7 +482,7 @@@ If the text hasn't changed as a result
    (ivy-set-index (max (- ivy--index ivy-height)
                        0)))
  (defun ivy-minibuffer-grow ()
-   "Grow the minibuffer window by 1 line"
+   "Grow the minibuffer window by 1 line."
    (interactive)
    (setq-local max-mini-window-height
                (cl-incf ivy-height)))
@@@ -485,16 -534,62 +534,62 @@@ If the input is empty, select the previ
    (ivy-previous-line arg))
  
  (defun ivy-toggle-calling ()
-   "Flip `ivy-calling'"
+   "Flip `ivy-calling'."
    (interactive)
    (when (setq ivy-calling (not ivy-calling))
      (ivy-call)))
  
+ (defun ivy--get-action (state)
+   "Get the action function from STATE."
+   (let ((action (ivy-state-action state)))
+     (when action
+       (if (functionp action)
+           action
+         (cadr (nth (car action) action))))))
+ (defun ivy--actionp (x)
+   "Return non-nil when X is a list of actions."
+   (and x (listp x) (not (eq (car x) 'closure))))
+ (defun ivy-next-action ()
+   "When the current action is a list, scroll it forwards."
+   (interactive)
+   (let ((action (ivy-state-action ivy-last)))
+     (when (ivy--actionp action)
+       (unless (>= (car action) (1- (length action)))
+         (cl-incf (car action))))))
+ (defun ivy-prev-action ()
+   "When the current action is a list, scroll it backwards."
+   (interactive)
+   (let ((action (ivy-state-action ivy-last)))
+     (when (ivy--actionp action)
+       (unless (<= (car action) 1)
+         (cl-decf (car action))))))
+ (defun ivy-action-name ()
+   "Return the name associated with the current action."
+   (let ((action (ivy-state-action ivy-last)))
+     (if (ivy--actionp action)
+         (format "[%d/%d] %s"
+                 (car action)
+                 (1- (length action))
+                 (nth 2 (nth (car action) action)))
+       "[1/1] default")))
  (defun ivy-call ()
    "Call the current action without exiting completion."
-   (when (ivy-state-action ivy-last)
-     (with-selected-window (ivy-state-window ivy-last)
-       (funcall (ivy-state-action ivy-last) ivy--current))))
+   (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))))
+         (funcall action x)))))
  
  (defun ivy-next-line-and-call (&optional arg)
    "Move cursor vertically down ARG candidates.
@@@ -617,7 -712,9 +712,9 @@@ On error (read-only), call `ivy-on-del-
                      ivy--directory))))
          (ivy--exhibit))
      (ignore-errors
-       (backward-kill-word 1))))
+       (let ((pt (point)))
+         (forward-word -1)
+         (delete-region (point) pt)))))
  
  (defvar ivy--regexp-quote 'regexp-quote
    "Store the regexp quoting state.")
@@@ -649,7 -746,7 +746,7 @@@ 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
+ 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'.
  
@@@ -716,7 -813,8 +813,8 @@@ Directories come first.
  
  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.
+ the current number of matching candidates.  If % appears elsewhere
+ in the PROMPT it should be quoted as %%.
  See also `ivy-count-format'.
  
  COLLECTION is a list of strings.
@@@ -743,6 -841,14 +841,14 @@@ MATCHER can completely override matchin
  
  DYNAMIC-COLLECTION is a function to call to update the list of
  candidates with each input."
+   (let ((extra-actions (plist-get ivy--actions-list this-command)))
+     (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
                   (let ((item (if ivy--directory
                                   ivy--current
                                 ivy-text)))
-                    (set hist (cons (propertize item 'ivy-index ivy--index)
-                                    (delete item
-                                            (cdr (symbol-value hist))))))
+                    (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)))
-     (when (setq action (ivy-state-action ivy-last))
-       (funcall action ivy--current))))
+     (ivy-call)))
  
  (defun ivy--reset-state (state)
    "Reset the ivy to STATE.
@@@ -801,7 -907,8 +907,8 @@@ This is useful for recursive `ivy-read'
          (re-builder (ivy-state-re-builder state))
          (dynamic-collection (ivy-state-dynamic-collection state))
          (initial-input (ivy-state-initial-input state))
-         (require-match (ivy-state-require-match state)))
+         (require-match (ivy-state-require-match state))
+         (matcher (ivy-state-matcher state)))
      (unless initial-input
        (setq initial-input (cdr (assoc this-command
                                        ivy-initial-inputs-alist))))
              ((eq collection 'read-file-name-internal)
               (setq ivy--directory default-directory)
               (require 'dired)
-              (setq coll
-                    (ivy--sorted-files default-directory))
+              (when preselect
+                (let ((preselect-directory (file-name-directory preselect)))
+                  (unless (or (null preselect-directory)
+                              (string= preselect-directory
+                                       default-directory))
+                    (setq ivy--directory preselect-directory))
+                  (setq preselect (file-name-nondirectory preselect))))
+              (setq coll (ivy--sorted-files ivy--directory))
               (when initial-input
                 (unless (or require-match
                             (equal initial-input default-directory)
                               ivy--index)
                          (and preselect
                               (ivy--preselect-index
-                               coll initial-input preselect))
+                               coll initial-input preselect matcher))
                          0))
        (setq ivy--old-re nil)
        (setq ivy--old-cands nil)
      (setq ivy--prompt
            (cond ((string-match "%.*d" prompt)
                   prompt)
+                 ((null ivy-count-format)
+                  nil)
+                 ((string-match "%d.*%d" ivy-count-format)
+                  (let ((w (length (number-to-string
+                                    (length ivy--all-candidates))))
+                        (s (copy-sequence ivy-count-format)))
+                    (string-match "%d" s)
+                    (match-end 0)
+                    (string-match "%d" s (match-end 0))
+                    (setq s (replace-match (format "%%-%dd" w) nil nil s))
+                    (string-match "%d" s)
+                    (concat (replace-match (format "%%%dd" w) nil nil s)
+                            prompt)))
                  ((string-match "%.*d" ivy-count-format)
                   (concat ivy-count-format prompt))
                  (ivy--directory
@@@ -906,7 -1032,8 +1032,8 @@@ 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 prompt collection
+   (ivy-read (replace-regexp-in-string "%" "%%" prompt)
+             collection
              :predicate predicate
              :require-match require-match
              :initial-input (if (consp initial-input)
@@@ -941,15 -1068,21 +1068,21 @@@ Minibuffer bindings
        (setq completing-read-function 'ivy-completing-read)
      (setq completing-read-function 'completing-read-default)))
  
- (defun ivy--preselect-index (candidates initial-input preselect)
-   "Return the index in CANDIDATES filtered by INITIAL-INPUT for PRESELECT."
-   (when initial-input
-     (setq initial-input (ivy--regex-plus initial-input))
-     (setq candidates
-           (cl-remove-if-not
-            (lambda (x)
-              (string-match initial-input x))
-            candidates)))
+ (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)
        (cl-position-if
         (lambda (x)
@@@ -1001,6 -1134,8 +1134,8 @@@ When GREEDY is non-nil, join words in 
      (if hashed
          (prog1 (cdr hashed)
            (setq ivy--subexps (car hashed)))
+       (when (string-match "\\([^\\]\\|^\\)\\\\$" str)
+         (setq str (substring str 0 -1)))
        (cdr (puthash str
                      (let ((subs (ivy--split str)))
                        (if (= (length subs) 1)
@@@ -1108,21 -1243,27 +1243,27 @@@ Insert .* between each char.
        (let ((inhibit-read-only t)
              (std-props '(front-sticky t rear-nonsticky t field t read-only t))
              (n-str
-              (format
+              (concat
+               (if (and (bound-and-true-p minibuffer-depth-indicate-mode)
+                        (> (minibuffer-depth) 1))
+                   (format "[%d] " (minibuffer-depth))
+                 "")
                (concat
-                (if (and (bound-and-true-p minibuffer-depth-indicate-mode)
-                         (> (minibuffer-depth) 1))
-                    (format "[%d] " (minibuffer-depth))
-                  "")
-                head
+                (if (string-match "%d.*%d" ivy-count-format)
+                    (format head
+                            (1+ ivy--index)
+                            (or (and (ivy-state-dynamic-collection ivy-last)
+                                     ivy--full-length)
+                                ivy--length))
+                  (format head
+                          (or (and (ivy-state-dynamic-collection ivy-last)
+                                   ivy--full-length)
+                              ivy--length)))
                 ivy--prompt-extra
-                tail
-                (if ivy--directory
-                    (abbreviate-file-name ivy--directory)
-                  ""))
-               (or (and (ivy-state-dynamic-collection ivy-last)
-                        ivy--full-length)
-                   ivy--length))))
+                tail)
+               (if ivy--directory
+                   (abbreviate-file-name ivy--directory)
+                 ""))))
          (save-excursion
            (goto-char (point-min))
            (delete-region (point-min) (minibuffer-prompt-end))
  (defun ivy--exhibit ()
    "Insert Ivy completions display.
  Should be run via minibuffer `post-command-hook'."
-   (setq ivy-text (ivy--input))
-   (if (ivy-state-dynamic-collection ivy-last)
-       ;; while-no-input would cause annoying
-       ;; "Waiting for process to die...done" message interruptions
-       (let ((inhibit-message t))
-         (unless (equal ivy--old-text ivy-text)
-           (while-no-input
-             ;; dynamic collection should take care of everything
-             (funcall (ivy-state-dynamic-collection ivy-last) ivy-text)
-             (setq ivy--old-text ivy-text)))
-         (unless (eq ivy--full-length -1)
-           (ivy--insert-minibuffer
-            (ivy--format ivy--all-candidates))))
-     (cond (ivy--directory
-            (if (string-match "/\\'" ivy-text)
-                (if (member ivy-text ivy--all-candidates)
-                    (ivy--cd (expand-file-name ivy-text ivy--directory))
-                  (when (string-match "//\\'" ivy-text)
-                  (if (and default-directory
-                           (string-match "\\`[[:alpha:]]:/" default-directory))
-                      (ivy--cd (match-string 0 default-directory))
-                    (ivy--cd "/")))
-                (when (string-match "[[:alpha:]]:/" ivy-text)
-                  (let ((drive-root (match-string 0 ivy-text)))
-                    (when (file-exists-p drive-root)
-                      (ivy--cd drive-root)))))
-              (if (string-match "\\`~\\'" ivy-text)
-                  (ivy--cd (expand-file-name "~/")))))
-           ((eq (ivy-state-collection ivy-last) 'internal-complete-buffer)
-            (when (or (and (string-match "\\` " ivy-text)
-                           (not (string-match "\\` " ivy--old-text)))
-                      (and (string-match "\\` " ivy--old-text)
-                           (not (string-match "\\` " ivy-text))))
-              (setq ivy--all-candidates
-                    (if (and (> (length ivy-text) 0)
-                             (eq (aref ivy-text 0)
-                                 ?\ ))
-                        (ivy--buffer-list " ")
-                      (ivy--buffer-list "" ivy-use-virtual-buffers)))
-              (setq ivy--old-re nil))))
-     (ivy--insert-minibuffer
-      (ivy--format
-       (ivy--filter ivy-text ivy--all-candidates)))
-     (setq ivy--old-text ivy-text)))
+   (when (memq 'ivy--exhibit post-command-hook)
+     (setq ivy-text (ivy--input))
+     (if (ivy-state-dynamic-collection ivy-last)
+         ;; while-no-input would cause annoying
+         ;; "Waiting for process to die...done" message interruptions
+         (let ((inhibit-message t))
+           (unless (equal ivy--old-text ivy-text)
+             (while-no-input
+               (setq ivy--all-candidates
+                     (funcall (ivy-state-collection ivy-last) ivy-text))
+               (setq ivy--old-text ivy-text)))
+           (when ivy--all-candidates
+             (ivy--insert-minibuffer
+              (ivy--format ivy--all-candidates))))
+       (cond (ivy--directory
+              (if (string-match "/\\'" ivy-text)
+                  (if (member ivy-text ivy--all-candidates)
+                      (ivy--cd (expand-file-name ivy-text ivy--directory))
+                    (when (string-match "//\\'" ivy-text)
+                      (if (and default-directory
+                               (string-match "\\`[[:alpha:]]:/" default-directory))
+                          (ivy--cd (match-string 0 default-directory))
+                        (ivy--cd "/")))
+                    (when (string-match "[[:alpha:]]:/" ivy-text)
+                      (let ((drive-root (match-string 0 ivy-text)))
+                        (when (file-exists-p drive-root)
+                          (ivy--cd drive-root)))))
+                (if (string-match "\\`~\\'" ivy-text)
+                    (ivy--cd (expand-file-name "~/")))))
+             ((eq (ivy-state-collection ivy-last) 'internal-complete-buffer)
+              (when (or (and (string-match "\\` " ivy-text)
+                             (not (string-match "\\` " ivy--old-text)))
+                        (and (string-match "\\` " ivy--old-text)
+                             (not (string-match "\\` " ivy-text))))
+                (setq ivy--all-candidates
+                      (if (and (> (length ivy-text) 0)
+                               (eq (aref ivy-text 0)
+                                   ?\ ))
+                          (ivy--buffer-list " ")
+                        (ivy--buffer-list "" ivy-use-virtual-buffers)))
+                (setq ivy--old-re nil))))
+       (ivy--insert-minibuffer
+        (ivy--format
+         (ivy--filter ivy-text ivy--all-candidates)))
+       (setq ivy--old-text ivy-text))))
  
  (defun ivy--insert-minibuffer (text)
    "Insert TEXT into minibuffer with appropriate cleanup."
  CANDIDATES are assumed to be static."
    (let* ((re (funcall ivy--regex-function name))
           (matcher (ivy-state-matcher ivy-last))
+          (case-fold-search (string= name (downcase name)))
           (cands (cond
                    (matcher
                     (funcall matcher re candidates))
        (unless (and (not (equal re ivy--old-re))
                     (or (setq ivy--index
                               (or
-                               (cl-position re cands
-                                            :test #'equal)
+                               (cl-position (if (and (> (length re) 0)
+                                                     (eq ?^ (aref re 0)))
+                                                (substring re 1)
+                                              re) cands
+                                              :test #'equal)
                                (and ivy--directory
                                     (cl-position
                                      (concat re "/") cands
@@@ -1420,14 -1566,40 +1566,40 @@@ BUFFER may be a string or nil.
          (switch-to-buffer
           buffer nil 'force-same-window)))))
  
+ (defun ivy--switch-buffer-other-window-action (buffer)
+   "Switch to BUFFER in other window.
+ BUFFER may be a string or nil."
+   (if (zerop (length buffer))
+       (switch-to-buffer-other-window ivy-text)
+     (let ((virtual (assoc buffer ivy--virtual-buffers)))
+       (if (and virtual
+                (not (get-buffer buffer)))
+           (find-file-other-window (cdr virtual))
+         (switch-to-buffer-other-window buffer)))))
+ (defvar ivy-switch-buffer-map (make-sparse-keymap))
+ (ivy-set-actions
+  'ivy-switch-buffer
+  '(("k"
+     (lambda (x)
+       (kill-buffer x)
+       (ivy--reset-state ivy-last))
+     "kill")
+    ("j"
+     ivy--switch-buffer-other-window-action
+     "other")))
  (defun ivy-switch-buffer ()
    "Switch to another buffer."
    (interactive)
    (if (not ivy-mode)
        (call-interactively 'switch-to-buffer)
-     (ivy-read "Switch to buffer: " 'internal-complete-buffer
-               :preselect (buffer-name (other-buffer (current-buffer)))
-               :action #'ivy--switch-buffer-action)))
+     (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))))
  
  (defun ivy-recentf ()
    "Find a file on `recentf-list'."
    "Pull next word from buffer into search string."
    (interactive)
    (let (amend)
-     (with-selected-window (ivy-state-window ivy-last)
+     (with-ivy-window
        (let ((pt (point))
              (le (line-end-position)))
          (forward-word 1)
@@@ -1483,6 -1655,13 +1655,13 @@@ The selected history element will be in
                          (insert (substring-no-properties x))
                          (ivy--cd-maybe)))))
  
+ (defun ivy-restrict-to-matches ()
+   "Restrict candidates to current matches and erase input."
+   (interactive)
+   (delete-minibuffer-contents)
+   (setq ivy--all-candidates
+         (ivy--filter ivy-text ivy--all-candidates)))
  (provide 'ivy)
  
  ;;; ivy.el ends here
index 1975ae2d0aad873887fb64057d8df873d9c6f800,1032f04869eb77423f69b4145254f37c7d1dddd6..1032f04869eb77423f69b4145254f37c7d1dddd6
@@@ -83,9 -83,6 +83,6 @@@
      map)
    "Keymap for swiper.")
  
- (defvar swiper--window nil
-   "Store the current window.")
  (defun swiper-query-replace ()
    "Start `query-replace' with string to replace from last search string."
    (interactive)
@@@ -96,7 -93,7 +93,7 @@@
             (to (query-replace-read-to from "Query replace" t)))
        (delete-minibuffer-contents)
        (ivy-set-action (lambda (_)
-                         (with-selected-window swiper--window
+                         (with-ivy-window
                            (move-beginning-of-line 1)
                            (perform-replace from to
                                             t t nil))))
  (declare-function avy--regex-candidates "ext:avy")
  (declare-function avy--process "ext:avy")
  (declare-function avy--overlay-post "ext:avy")
- (declare-function avy--goto "ext:avy")
+ (declare-function avy-action-goto "ext:avy")
  
  ;;;###autoload
  (defun swiper-avy ()
    "Jump to one of the current swiper candidates."
    (interactive)
    (unless (string= ivy-text "")
-     (with-selected-window (ivy-state-window ivy-last)
+     (with-ivy-window
        (let* ((avy-all-windows nil)
               (candidates
                (avy--regex-candidates
               (candidate
                (avy--process candidates #'avy--overlay-post)))
          (ivy-quit-and-run
-          (avy--goto candidate))))))
+          (avy-action-goto candidate))))))
  
  (defun swiper-recenter-top-bottom (&optional arg)
-   "Call (`recenter-top-bottom' ARG) in `swiper--window'."
+   "Call (`recenter-top-bottom' ARG)."
    (interactive "P")
-   (with-selected-window swiper--window
+   (with-ivy-window
      (recenter-top-bottom arg)))
  
  (defun swiper-font-lock-ensure ()
                                   dired-mode
                                   jabber-chat-mode
                                   elfeed-search-mode
-                                  fundamental-mode)))
+                                  fundamental-mode
+                                  Man-mode
+                                  woman-mode)))
      (unless (> (buffer-size) 100000)
        (if (fboundp 'font-lock-ensure)
            (font-lock-ensure)
@@@ -199,8 -198,7 +198,7 @@@ When non-nil, INITIAL-INPUT is the init
    "Perform initialization common to both completion methods."
    (setq swiper--opoint (point))
    (setq swiper--len 0)
-   (setq swiper--anchor (line-number-at-pos))
-   (setq swiper--window (selected-window)))
+   (setq swiper--anchor (line-number-at-pos)))
  
  (defun swiper--re-builder (str)
    "Transform STR into a swiper regex.
@@@ -244,8 -242,7 +242,7 @@@ Please remove it and update the \"swipe
          res)
      (unwind-protect
           (setq res (ivy-read
-                     (replace-regexp-in-string
-                      "%s" "pattern: " swiper--format-spec)
+                     "Swiper: "
                      candidates
                      :initial-input initial-input
                      :keymap swiper-map
  
  (defun swiper--update-input-ivy ()
    "Called when `ivy' input is updated."
-   (swiper--cleanup)
-   (let* ((re (ivy--regex ivy-text))
-          (str ivy--current)
-          (num (if (string-match "^[0-9]+" str)
-                   (string-to-number (match-string 0 str))
-                 0)))
-     (with-selected-window swiper--window
+   (with-ivy-window
+     (swiper--cleanup)
+     (let* ((re (ivy--regex ivy-text))
+            (str ivy--current)
+            (num (if (string-match "^[0-9]+" str)
+                     (string-to-number (match-string 0 str))
+                   0)))
        (goto-char (point-min))
        (when (cl-plusp num)
          (goto-char (point-min))
          (isearch-range-invisible (line-beginning-position)
                                   (line-end-position))
          (unless (and (>= (point) (window-start))
-                      (<= (point) (window-end swiper--window t)))
+                      (<= (point) (window-end (ivy-state-window ivy-last) t)))
            (recenter)))
        (swiper--add-overlays re))))
  
@@@ -311,39 -308,39 +308,39 @@@ BEG and END, when specified, are the po
               (line-beginning-position)
               (1+ (line-end-position)))))
      (overlay-put ov 'face 'swiper-line-face)
-     (overlay-put ov 'window swiper--window)
-     (push ov swiper--overlays))
-   (let* ((wh (window-height))
-          (beg (or beg (save-excursion
-                         (forward-line (- wh))
-                         (point))))
-          (end (or end (save-excursion
-                         (forward-line wh)
-                         (point)))))
-     (when (>= (length re) swiper-min-highlight)
-       (save-excursion
-         (goto-char beg)
-         ;; RE can become an invalid regexp
-         (while (and (ignore-errors (re-search-forward re end t))
-                     (> (- (match-end 0) (match-beginning 0)) 0))
-           (let ((i 0))
-             (while (<= i ivy--subexps)
-               (when (match-beginning i)
-                 (let ((overlay (make-overlay (match-beginning i)
-                                              (match-end i)))
-                       (face
-                        (cond ((zerop ivy--subexps)
-                               (cadr swiper-faces))
-                              ((zerop i)
-                               (car swiper-faces))
-                              (t
-                               (nth (1+ (mod (+ i 2) (1- (length swiper-faces))))
-                                    swiper-faces)))))
-                   (push overlay swiper--overlays)
-                   (overlay-put overlay 'face face)
-                   (overlay-put overlay 'window swiper--window)
-                   (overlay-put overlay 'priority i)))
-               (cl-incf i))))))))
+     (overlay-put ov 'window (ivy-state-window ivy-last))
+     (push ov swiper--overlays)
+     (let* ((wh (window-height))
+            (beg (or beg (save-excursion
+                           (forward-line (- wh))
+                           (point))))
+            (end (or end (save-excursion
+                           (forward-line wh)
+                           (point)))))
+       (when (>= (length re) swiper-min-highlight)
+         (save-excursion
+           (goto-char beg)
+           ;; RE can become an invalid regexp
+           (while (and (ignore-errors (re-search-forward re end t))
+                       (> (- (match-end 0) (match-beginning 0)) 0))
+             (let ((i 0))
+               (while (<= i ivy--subexps)
+                 (when (match-beginning i)
+                   (let ((overlay (make-overlay (match-beginning i)
+                                                (match-end i)))
+                         (face
+                          (cond ((zerop ivy--subexps)
+                                 (cadr swiper-faces))
+                                ((zerop i)
+                                 (car swiper-faces))
+                                (t
+                                 (nth (1+ (mod (+ i 2) (1- (length swiper-faces))))
+                                      swiper-faces)))))
+                     (push overlay swiper--overlays)
+                     (overlay-put overlay 'face face)
+                     (overlay-put overlay 'window (ivy-state-window ivy-last))
+                     (overlay-put overlay 'priority i)))
+                 (cl-incf i)))))))))
  
  (defun swiper--action (x input)
    "Goto line X and search for INPUT."
          (push-mark swiper--opoint t)
          (message "Mark saved where search started")))))
  
+ ;; (define-key isearch-mode-map (kbd "C-o") 'swiper-from-isearch)
+ (defun swiper-from-isearch ()
+   "Invoke `swiper' from isearch."
+   (interactive)
+   (let ((query (if isearch-regexp
+                    isearch-string
+                  (regexp-quote isearch-string))))
+     (isearch-exit)
+     (swiper query)))
  (provide 'swiper)
  
  ;;; swiper.el ends here