]> code.delx.au - gnu-emacs-elpa/commitdiff
Merge commit 'ba49407c5b4c719dd5dcc298c260513abf0c70df' from swiper
authorOleh Krehel <ohwoeowho@gmail.com>
Tue, 29 Sep 2015 14:09:53 +0000 (16:09 +0200)
committerOleh Krehel <ohwoeowho@gmail.com>
Tue, 29 Sep 2015 14:09:53 +0000 (16:09 +0200)
1  2 
packages/swiper/counsel.el
packages/swiper/ivy.el
packages/swiper/swiper.el

index 63c9552f8cfa499593f7e0710cefede247df9561,ac04e6775ae2e51152674e21c70b69e4bb67c19f..ac04e6775ae2e51152674e21c70b69e4bb67c19f
@@@ -33,6 -33,7 +33,7 @@@
  ;;; Code:
  
  (require 'swiper)
+ (require 'etags)
  
  (defvar counsel-completion-beg nil
    "Completion bounds start.")
                :initial-input str
                :action #'counsel--el-action)))
  
+ (declare-function slime-symbol-start-pos "ext:slime")
+ (declare-function slime-symbol-end-pos "ext:slime")
+ (declare-function slime-contextual-completions "ext:slime-c-p-c")
+ ;;;###autoload
+ (defun counsel-cl ()
+   "Common Lisp completion at point."
+   (interactive)
+   (setq counsel-completion-beg (slime-symbol-start-pos))
+   (setq counsel-completion-end (slime-symbol-end-pos))
+   (ivy-read "Symbol name: "
+             (car (slime-contextual-completions
+                   counsel-completion-beg
+                   counsel-completion-end))
+             :action #'counsel--el-action))
  (defun counsel--el-action (symbol)
    "Insert SYMBOL, erasing the previous one."
    (when (stringp symbol)
-     (when counsel-completion-beg
-       (delete-region
-        counsel-completion-beg
-        counsel-completion-end))
-     (setq counsel-completion-beg
-           (move-marker (make-marker) (point)))
-     (insert symbol)
-     (setq counsel-completion-end
-           (move-marker (make-marker) (point)))))
+     (with-ivy-window
+       (when counsel-completion-beg
+         (delete-region
+          counsel-completion-beg
+          counsel-completion-end))
+       (setq counsel-completion-beg
+             (move-marker (make-marker) (point)))
+       (insert symbol)
+       (setq counsel-completion-end
+             (move-marker (make-marker) (point))))))
+ (declare-function deferred:sync! "ext:deferred")
+ (declare-function jedi:complete-request "ext:jedi-core")
+ (declare-function jedi:ac-direct-matches "ext:jedi")
+ (defun counsel-jedi ()
+   "Python completion at point."
+   (interactive)
+   (let ((bnd (bounds-of-thing-at-point 'symbol)))
+     (if bnd
+         (progn
+           (setq counsel-completion-beg (car bnd))
+           (setq counsel-completion-end (cdr bnd)))
+       (setq counsel-completion-beg nil)
+       (setq counsel-completion-end nil)))
+   (deferred:sync!
+    (jedi:complete-request))
+   (ivy-read "Symbol name: " (jedi:ac-direct-matches)
+             :action #'counsel--py-action))
+ (defun counsel--py-action (symbol)
+   "Insert SYMBOL, erasing the previous one."
+   (when (stringp symbol)
+     (with-ivy-window
+       (when counsel-completion-beg
+         (delete-region
+          counsel-completion-beg
+          counsel-completion-end))
+       (setq counsel-completion-beg
+             (move-marker (make-marker) (point)))
+       (insert symbol)
+       (setq counsel-completion-end
+             (move-marker (make-marker) (point)))
+       (when (equal (get-text-property 0 'symbol symbol) "f")
+         (insert "()")
+         (setq counsel-completion-end
+               (move-marker (make-marker) (point)))
+         (backward-char 1)))))
  
  (defvar counsel-describe-map
    (let ((map (make-sparse-keymap)))
  
  (defun counsel--find-symbol (x)
    "Find symbol definition that corresponds to string X."
+   (ring-insert find-tag-marker-ring (point-marker))
    (let ((full-name (get-text-property 0 'full-name x)))
      (if full-name
          (find-library full-name)
    "Return current symbol at point as a string."
    (let ((s (thing-at-point 'symbol)))
      (and (stringp s)
-          (if (string-match "\\`[`']?\\(.*\\)'?\\'" s)
+          (if (string-match "\\`[`']?\\(.*?\\)'?\\'" s)
               (match-string 1 s)
             s))))
  
    (require 'info-look)
    (info-lookup 'symbol symbol mode))
  
+ (defvar counsel-unicode-char-history nil
+   "History for `counsel-unicode-char'.")
  ;;;###autoload
  (defun counsel-unicode-char ()
    "Insert a Unicode character at point."
    (interactive)
    (let ((minibuffer-allow-text-properties t))
+     (setq counsel-completion-beg (point))
+     (setq counsel-completion-end (point))
      (ivy-read "Unicode name: "
                (mapcar (lambda (x)
                          (propertize
                           'result (cdr x)))
                        (ucs-names))
                :action (lambda (char)
-                         (insert-char (get-text-property 0 'result char))))))
+                         (with-ivy-window
+                           (delete-region counsel-completion-beg counsel-completion-end)
+                           (setq counsel-completion-beg (point))
+                           (insert-char (get-text-property 0 'result char))
+                           (setq counsel-completion-end (point))))
+               :history 'counsel-unicode-char-history)))
  
  (declare-function cider-sync-request:complete "ext:cider-client")
  ;;;###autoload
        (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))))
+                         (setq ivy--old-re (ivy--regex string t)))))
        (if (<= counsel--git-grep-count 20000)
            (split-string (shell-command-to-string cmd) "\n" t)
          (counsel--gg-candidates (ivy--regex string))
@@@ -430,7 -497,9 +497,9 @@@ Skip some dotfiles unless `ivy-text' re
    (if (string= event "finished\n")
        (progn
          (with-current-buffer (process-buffer process)
-           (setq ivy--all-candidates (split-string (buffer-string) "\n" t))
+           (setq ivy--all-candidates
+                 (ivy--sort-maybe
+                  (split-string (buffer-string) "\n" t)))
            (setq ivy--old-cands ivy--all-candidates))
          (ivy--exhibit))
      (if (string= event "exited abnormally with code 1\n")
    (call-process shell-file-name nil
                  nil nil
                  shell-command-switch
-                 (format "xdg-open %s" (shell-quote-argument x))))
+                 (format "%s %s"
+                         (if (eq system-type 'darwin)
+                                     "open"
+                                   "xdg-open")
+                         (shell-quote-argument x))))
  
  (declare-function dired-jump "dired-x")
  (defun counsel-locate-action-dired (x)
  (defvar counsel-locate-history nil
    "History for `counsel-locate'.")
  
+ (defcustom counsel-locate-options (if (eq system-type 'darwin)
+                                       '("-i")
+                                     '("-i" "--regex"))
+   "Command line options for `locate`."
+   :group 'ivy
+   :type  '(repeat string))
  (ivy-set-actions
   'counsel-locate
   '(("x" counsel-locate-action-extern "xdg-open")
     ("d" counsel-locate-action-dired "dired")))
  
+ (defun counsel-unquote-regex-parens (str)
+   (replace-regexp-in-string
+    "\\\\)" ")"
+    (replace-regexp-in-string
+     "\\\\(" "("
+     str)))
  (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)))
+      (format "locate %s '%s'"
+              (mapconcat #'identity counsel-locate-options " ")
+              (counsel-unquote-regex-parens
+               (ivy--regex str))))
      '("" "working...")))
  
  ;;;###autoload
@@@ -783,22 -873,50 +873,50 @@@ Usable with `ivy-resume', `ivy-next-lin
        (t (error "Tags alignment failed")))
      (org-move-to-column col)))
  
+ (defun counsel-org--set-tags ()
+   (counsel-org-change-tags
+    (if counsel-org-tags
+        (format ":%s:"
+                (mapconcat #'identity counsel-org-tags ":"))
+      "")))
+ (defvar org-agenda-bulk-marked-entries)
+ (declare-function org-get-at-bol "org")
+ (declare-function org-agenda-error "org-agenda")
  (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)))))
+     (unless (equal x "")
+       (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 ":"))
-             "")))
+   (cond ((memq this-command '(ivy-done
+                               ivy-alt-done
+                               ivy-immediate-done))
+          (if (eq major-mode 'org-agenda-mode)
+              (if (null org-agenda-bulk-marked-entries)
+                  (let ((hdmarker (or (org-get-at-bol 'org-hd-marker)
+                                      (org-agenda-error))))
+                    (with-current-buffer (marker-buffer hdmarker)
+                      (goto-char hdmarker)
+                      (counsel-org--set-tags)))
+                (let ((add-tags (copy-sequence counsel-org-tags)))
+                  (dolist (m org-agenda-bulk-marked-entries)
+                    (with-current-buffer (marker-buffer m)
+                      (save-excursion
+                        (goto-char m)
+                        (setq counsel-org-tags
+                              (delete-dups
+                               (append (split-string (org-get-tags-string) ":" t)
+                                       add-tags)))
+                        (counsel-org--set-tags))))))
+            (counsel-org--set-tags)))
          ((eq this-command 'ivy-call)
           (delete-minibuffer-contents))))
  
    "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))
+     (if (eq major-mode 'org-agenda-mode)
+         (if org-agenda-bulk-marked-entries
+             (setq counsel-org-tags nil)
+           (let ((hdmarker (or (org-get-at-bol 'org-hd-marker)
+                               (org-agenda-error))))
+             (with-current-buffer (marker-buffer hdmarker)
+               (goto-char hdmarker)
+               (setq counsel-org-tags
+                     (split-string (org-get-tags-string) ":" t)))))
+       (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
+                     (or org-complete-tags-always-offer-all-agenda-tags
+                         (eq major-mode 'org-agenda-mode))
                      (org-global-tags-completion-table
                       (org-agenda-files))))))
        (ivy-read (counsel-org-tag-prompt)
    "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)))))
+     (let ((regex (counsel-unquote-regex-parens
+                   (setq ivy--old-re
+                         (ivy--regex string)))))
        (counsel--async-command
         (format "ag --noheading --nocolor %S" regex))
        nil)))
@@@ -912,6 -1038,54 +1038,54 @@@ INITIAL-INPUT can be given as the initi
                            (unless (string-match "pdf$" x)
                              (swiper ivy-text)))))))
  
+ (defcustom counsel-yank-pop-truncate nil
+   "When non-nil, truncate the display of long strings."
+   :group 'ivy)
+ ;;;###autoload
+ (defun counsel-yank-pop ()
+   "Ivy replacement for `yank-pop'."
+   (interactive)
+   (if (eq last-command 'yank)
+       (progn
+         (setq counsel-completion-end (point))
+         (setq counsel-completion-beg
+               (save-excursion
+                 (search-backward (car kill-ring))
+                 (point))))
+     (setq counsel-completion-beg (point))
+     (setq counsel-completion-end (point)))
+   (let ((candidates (cl-remove-if
+                      (lambda (s)
+                        (or (< (length s) 3)
+                            (string-match "\\`[\n[:blank:]]+\\'" s)))
+                      (delete-dups kill-ring))))
+     (when counsel-yank-pop-truncate
+       (setq candidates
+             (mapcar (lambda (s)
+                       (if (string-match "\\`\\(.*\n.*\n.*\n.*\\)\n" s)
+                           (progn
+                             (let ((s (copy-sequence s)))
+                               (put-text-property
+                                (match-end 1)
+                                (length s)
+                                'display
+                                " [...]"
+                                s)
+                               s))
+                         s))
+                     candidates)))
+     (ivy-read "kill-ring: " candidates
+               :action 'counsel-yank-pop-action)))
+ (defun counsel-yank-pop-action (s)
+   "Insert S into the buffer, overwriting the previous yank."
+   (with-ivy-window
+     (delete-region counsel-completion-beg
+                    counsel-completion-end)
+     (insert (substring-no-properties s))
+     (setq counsel-completion-end (point))))
  (provide 'counsel)
  
  ;;; counsel.el ends here
diff --combined packages/swiper/ivy.el
index 21197c3e397a54422ecf8315365ff0f459a50469,04c254e8eb1d19df7e6d2912d90b74e0e23660b7..04c254e8eb1d19df7e6d2912d90b74e0e23660b7
--- 2/ivy.el
    :group 'convenience)
  
  (defface ivy-current-match
-   '((t (:inherit highlight)))
+   '((((class color) (background light))
+      :background "#1a4b77" :foreground "white")
+     (((class color) (background dark))
+      :background "#65a7e2" :foreground "black"))
    "Face used by Ivy for highlighting first match.")
  
  (defface ivy-confirm-face
@@@ -78,6 -81,17 +81,17 @@@ and the candidate count.
    "Whether to wrap around after the first and last candidate."
    :type 'boolean)
  
+ (defcustom ivy-display-style nil
+   "The style for formatting the minibuffer.
+ By default, the matched strings will be copied as they are.
+ With the fancy method, the matching parts of the regexp will be
+ additionally highlighted, just like `swiper' does it."
+   :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."
@@@ -123,8 -137,6 +137,6 @@@ Only \"./\" and \"../\" apply here. The
      (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 (kbd "<left>") 'ivy-beginning-of-buffer)
-     (define-key map (kbd "<right>") '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 "M-o") 'ivy-dispatching-done)
      (define-key map (kbd "C-k") 'ivy-kill-line)
      (define-key map (kbd "S-SPC") 'ivy-restrict-to-matches)
+     (define-key map (kbd "M-w") 'ivy-kill-ring-save)
      map)
    "Keymap used in the minibuffer.")
  (autoload 'hydra-ivy/body "ivy-hydra" "" t)
@@@ -428,6 -441,7 +441,7 @@@ If the text hasn't changed as a result
    (setq ivy-exit 'done)
    (exit-minibuffer))
  
+ ;;;###autoload
  (defun ivy-resume ()
    "Resume the last completion session."
    (interactive)
    (interactive)
    (ivy-set-index (max (- ivy--index ivy-height)
                        0)))
  (defun ivy-minibuffer-grow ()
    "Grow the minibuffer window by 1 line."
    (interactive)
@@@ -875,6 -890,10 +890,10 @@@ candidates with each input.
               (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)
@@@ -954,6 -973,7 +973,7 @@@ This is useful for recursive `ivy-read'
              ((eq collection 'internal-complete-buffer)
               (setq coll (ivy--buffer-list "" ivy-use-virtual-buffers)))
              ((or (functionp collection)
+                  (byte-code-function-p collection)
                   (vectorp collection)
                   (listp (car collection)))
               (setq coll (all-completions "" collection predicate)))
                   nil)))
      (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)
@@@ -1038,7 -1059,11 +1059,11 @@@ The history, defaults and input-method 
              :require-match require-match
              :initial-input (if (consp initial-input)
                                 (car initial-input)
-                              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
@@@ -1209,6 -1234,8 +1234,8 @@@ Insert .* between each char.
    (set (make-local-variable 'minibuffer-default-add-function)
         (lambda ()
           (list ivy--default)))
+   (when (display-graphic-p)
+     (setq truncate-lines t))
    (setq-local max-mini-window-height ivy-height)
    (add-hook 'post-command-hook #'ivy--exhibit nil t)
    ;; show completions with empty input
          (save-excursion
            (goto-char (point-min))
            (delete-region (point-min) (minibuffer-prompt-end))
+           (when (> (length n-str) (window-width))
+             (setq n-str (concat (substring n-str 0
+                                            (max (- (window-width) 30)
+                                                 10)) "... ")))
            (set-text-properties 0 (length n-str)
                                 `(face minibuffer-prompt ,@std-props)
                                 n-str)
  
  (defvar inhibit-message)
  
+ (defun ivy--sort-maybe (collection)
+   "Sort COLLECTION if needed."
+   (let ((sort (ivy-state-sort ivy-last))
+         entry)
+     (if (null sort)
+         collection
+       (let ((sort-fn (cond ((functionp sort)
+                             sort)
+                            ((setq entry (assoc (ivy-state-collection ivy-last)
+                                                ivy-sort-functions-alist))
+                             (cdr entry))
+                            (t
+                             (cdr (assoc t ivy-sort-functions-alist))))))
+         (if (functionp sort-fn)
+             (cl-sort (copy-sequence collection) sort-fn)
+           collection)))))
  (defun ivy--exhibit ()
    "Insert Ivy completions display.
  Should be run via minibuffer `post-command-hook'."
            (unless (equal ivy--old-text ivy-text)
              (while-no-input
                (setq ivy--all-candidates
-                     (funcall (ivy-state-collection ivy-last) ivy-text))
+                     (ivy--sort-maybe
+                      (funcall (ivy-state-collection ivy-last) ivy-text)))
                (setq ivy--old-text ivy-text)))
            (when ivy--all-candidates
              (ivy--insert-minibuffer
        (let ((buffer-undo-list t))
          (save-excursion
            (forward-line 1)
-           (insert text))))))
+           (insert text))))
+     (when (display-graphic-p)
+       (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)))
+         (let ((text-height (count-screen-lines))
+               (body-height (window-body-height)))
+           (when (> text-height body-height)
+             (window-resize nil (- text-height body-height) nil t))))))
  
  (declare-function colir-blend-face-background "ext:colir")
  
  `propertize' or `add-face-text-property' in this case."
    (require 'colir)
    (condition-case nil
-       (colir-blend-face-background 0 (length str) face str)
+       (progn
+         (colir-blend-face-background 0 (length str) face str)
+         (let ((foreground (face-foreground face)))
+           (when foreground
+             (add-face-text-property
+              0 (length str)
+              `(:foreground ,foreground)
+              nil
+              str))))
      (error
       (ignore-errors
         (font-lock-append-text-property 0 (length str) 'face face str))))
    "Return all items that match NAME in CANDIDATES.
  CANDIDATES are assumed to be static."
    (let* ((re (funcall ivy--regex-function name))
+          (re-str (if (listp re) (caar re) re))
           (matcher (ivy-state-matcher ivy-last))
           (case-fold-search (string= name (downcase name)))
           (cands (cond
           (tail (nthcdr ivy--index ivy--old-cands))
           idx)
      (when (and tail ivy--old-cands (not (equal "^" ivy--old-re)))
-       (unless (and (not (equal re ivy--old-re))
+       (unless (and (not (equal re-str ivy--old-re))
                     (or (setq ivy--index
                               (or
-                               (cl-position (if (and (> (length re) 0)
-                                                     (eq ?^ (aref re 0)))
-                                                (substring re 1)
-                                              re) cands
+                               (cl-position (if (and (> (length re-str) 0)
+                                                     (eq ?^ (aref re-str 0)))
+                                                (substring re-str 1)
+                                              re-str) cands
                                               :test #'equal)
                                (and ivy--directory
                                     (cl-position
-                                     (concat re "/") cands
+                                     (concat re-str "/") cands
                                      :test #'equal))))))
          (while (and tail (null idx))
            ;; Compare with eq to handle equal duplicates in cands
              (or (cl-position (ivy-state-preselect ivy-last)
                               cands :test #'equal)
                  ivy--index)))
-     (setq ivy--old-re (if cands re ""))
+     (setq ivy--old-re (if cands re-str ""))
      (setq ivy--old-cands cands)))
  
  (defvar ivy-format-function 'ivy-format-function-default
@@@ -1442,13 -1516,16 +1516,16 @@@ This string will be inserted into the m
  
  (defun ivy-format-function-default (cands)
    "Transform CANDS into a string for minibuffer."
-   (let ((ww (window-width)))
-     (mapconcat
-      (lambda (s)
-        (if (> (length s) ww)
-            (concat (substring s 0 (- ww 3)) "...")
-          s))
-      cands "\n")))
+   (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
+        (lambda (s)
+          (if (> (length s) ww)
+              (concat (substring s 0 (- ww 3)) "...")
+            s))
+        cands "\n"))))
  
  (defun ivy-format-function-arrow (cands)
    "Transform CANDS into a string for minibuffer."
                 s))
       cands "\n")))
  
+ (defcustom swiper-minibuffer-faces
+   '(swiper-minibuffer-match-face-1
+     swiper-minibuffer-match-face-2
+     swiper-minibuffer-match-face-3
+     swiper-minibuffer-match-face-4)
+   "List of `swiper' faces for minibuffer group matches.")
+ (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 swiper-minibuffer-faces))
+                          ((zerop i)
+                           (car swiper-minibuffer-faces))
+                          (t
+                           (nth (1+ (mod (+ i 2) (1- (length swiper-minibuffer-faces))))
+                                swiper-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)))))
+     str))
  (defun ivy--format (cands)
    "Return a string for CANDS suitable for display in the minibuffer.
  CANDS is a list of strings."
                                  x))
                              cands)))
        (setq ivy--current (copy-sequence (nth index cands)))
-       (setf (nth index cands)
-             (ivy--add-face ivy--current 'ivy-current-match))
        (setq cands (mapcar
-                    (lambda (s)
-                      (let ((s (copy-sequence s)))
-                        (when (fboundp 'add-face-text-property)
-                          (add-face-text-property
-                           0 (length s)
-                           `(:height ,(face-attribute 'default :height)
-                                     :overline nil) nil s))
-                        s))
+                    #'ivy--format-minibuffer-line
                     cands))
+       (setf (nth index cands)
+             (ivy--add-face (nth index cands) 'ivy-current-match))
        (let* ((ivy--index index)
               (res (concat "\n" (funcall ivy-format-function cands))))
          (put-text-property 0 (length res) 'read-only nil res)
@@@ -1556,15 -1668,16 +1668,16 @@@ When VIRTUAL is non-nil, add virtual bu
  (defun ivy--switch-buffer-action (buffer)
    "Switch to BUFFER.
  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))
+   (with-ivy-window
+     (if (zerop (length buffer))
          (switch-to-buffer
-          buffer nil 'force-same-window)))))
+          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))))))
  
  (defun ivy--switch-buffer-other-window-action (buffer)
    "Switch to BUFFER in other window.
@@@ -1577,6 -1690,12 +1690,12 @@@ BUFFER may be a string or nil.
            (find-file-other-window (cdr virtual))
          (switch-to-buffer-other-window buffer)))))
  
+ (defun ivy--rename-buffer-action (buffer)
+   "Rename BUFFER."
+   (let ((new-name (read-string "Rename buffer (to new name): ")))
+     (with-current-buffer buffer
+       (rename-buffer new-name))))
  (defvar ivy-switch-buffer-map (make-sparse-keymap))
  
  (ivy-set-actions
      "kill")
     ("j"
      ivy--switch-buffer-other-window-action
-     "other")))
+     "other")
+    ("r"
+     ivy--rename-buffer-action
+     "rename")))
  
+ ;;;###autoload
  (defun ivy-switch-buffer ()
    "Switch to another buffer."
    (interactive)
                  :action #'ivy--switch-buffer-action
                  :keymap ivy-switch-buffer-map))))
  
+ ;;;###autoload
  (defun ivy-recentf ()
    "Find a file on `recentf-list'."
    (interactive)
    (ivy-read "Recentf: " recentf-list
-             :action #'find-file))
+             :action
+             (lambda (f)
+               (with-ivy-window
+                 (find-file f)))))
  
  (defun ivy-yank-word ()
    "Pull next word from buffer into search string."
      (when amend
        (insert amend))))
  
+ (defun ivy-kill-ring-save ()
+   "Store the current candidates into the kill ring.
+ If the region is active, forward to `kill-ring-save' instead."
+   (interactive)
+   (if (region-active-p)
+       (call-interactively 'kill-ring-save)
+     (kill-new
+      (mapconcat
+       #'identity
+       ivy--old-cands
+       "\n"))))
  (defun ivy-insert-current ()
    "Make the current candidate into current input.
  Don't finish completion."
index 1032f04869eb77423f69b4145254f37c7d1dddd6,1b2d9067a2ead450a3eb42c67ff2e4493f72a8d3..1b2d9067a2ead450a3eb42c67ff2e4493f72a8d3
    '((t (:inherit isearch-fail)))
    "Face for `swiper' matches modulo 3.")
  
+ (defface swiper-minibuffer-match-face-1
+   '((((class color) (background light))
+      :background "#d3d3d3")
+     (((class color) (background dark))
+      :background "#555555"))
+   "The background face for `swiper' minibuffer matches."
+   :group 'function-args-faces)
+ (defface swiper-minibuffer-match-face-2
+   '((((class color) (background light))
+      :background "#e99ce8" :weight bold)
+     (((class color) (background dark))
+      :background "#777777" :weight bold))
+   "Face for `swiper' minibuffer matches modulo 1.")
+ (defface swiper-minibuffer-match-face-3
+   '((((class color) (background light))
+      :background "#bbbbff" :weight bold)
+     (((class color) (background dark))
+      :background "#7777ff" :weight bold))
+   "Face for `swiper' minibuffer matches modulo 2.")
+ (defface swiper-minibuffer-match-face-4
+   '((((class color) (background light))
+      :background "#ffbbff" :weight bold)
+     (((class color) (background dark))
+      :background "#8a498a" :weight bold))
+   "Face for `swiper' minibuffer matches modulo 3.")
  (defface swiper-line-face
    '((t (:inherit highlight)))
    "Face for current `swiper' line.")
                                   elfeed-search-mode
                                   fundamental-mode
                                   Man-mode
-                                  woman-mode)))
+                                  woman-mode
+                                  mu4e-view-mode
+                                  mu4e-headers-mode)))
      (unless (> (buffer-size) 100000)
        (if (fboundp 'font-lock-ensure)
            (font-lock-ensure)
      (unless (zerop n-lines)
        (setq swiper--width (1+ (floor (log n-lines 10))))
        (setq swiper--format-spec
-             (format "%%-%dd %%s" swiper--width))
+             (format "%%-%dd " swiper--width))
        (let ((line-number 0)
              candidates)
          (save-excursion
            (goto-char (point-min))
            (swiper-font-lock-ensure)
            (while (< (point) (point-max))
-             (push (format swiper--format-spec
-                           (cl-incf line-number)
-                           (buffer-substring
-                            (line-beginning-position)
-                            (line-end-position)))
-                   candidates)
+             (let ((str (concat " " (buffer-substring
+                                     (line-beginning-position)
+                                     (line-end-position)))))
+               (put-text-property 0 1 'display
+                                  (format swiper--format-spec
+                                          (cl-incf line-number))
+                                  str)
+               (push str candidates))
              (forward-line 1))
            (nreverse candidates))))))
  
@@@ -228,17 -261,12 +261,12 @@@ there have line numbers. In the buffer
    "`isearch' with an overview using `ivy'.
  When non-nil, INITIAL-INPUT is the initial search pattern."
    (interactive)
-   (unless (eq (length (help-function-arglist 'ivy-read)) 4)
-     (warn "You seem to be using the outdated stand-alone \"ivy\" package.
- Please remove it and update the \"swiper\" package."))
    (swiper--init)
    (let ((candidates (swiper--candidates))
-         (preselect (format
-                     swiper--format-spec
-                     (line-number-at-pos)
-                     (buffer-substring-no-properties
-                      (line-beginning-position)
-                      (line-end-position))))
+         (preselect (buffer-substring-no-properties
+                     (line-beginning-position)
+                     (line-end-position)))
+         (minibuffer-allow-text-properties t)
          res)
      (unwind-protect
           (setq res (ivy-read
    "Called when `ivy' input is updated."
    (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)
+     (when (> (length ivy--current) 0)
+       (let* ((re (funcall ivy--regex-function ivy-text))
+              (re (if (stringp re) re (caar re)))
+              (str (get-text-property 0 'display ivy--current))
+              (num (if (string-match "^[0-9]+" str)
+                       (string-to-number (match-string 0 str))
+                     0)))
          (goto-char (point-min))
-         (forward-line (1- num))
-         (if (and (equal ivy-text "")
-                  (>= swiper--opoint (line-beginning-position))
-                  (<= swiper--opoint (line-end-position)))
-             (goto-char swiper--opoint)
-           (re-search-forward re (line-end-position) t))
-         (isearch-range-invisible (line-beginning-position)
-                                  (line-end-position))
-         (unless (and (>= (point) (window-start))
-                      (<= (point) (window-end (ivy-state-window ivy-last) t)))
-           (recenter)))
-       (swiper--add-overlays re))))
+         (when (cl-plusp num)
+           (goto-char (point-min))
+           (forward-line (1- num))
+           (if (and (equal ivy-text "")
+                    (>= swiper--opoint (line-beginning-position))
+                    (<= swiper--opoint (line-end-position)))
+               (goto-char swiper--opoint)
+             (re-search-forward re (line-end-position) t))
+           (isearch-range-invisible (line-beginning-position)
+                                    (line-end-position))
+           (unless (and (>= (point) (window-start))
+                        (<= (point) (window-end (ivy-state-window ivy-last) t)))
+             (recenter)))
+         (swiper--add-overlays re)))))
  
  (defun swiper--add-overlays (re &optional beg end)
    "Add overlays for RE regexp in visible part of the current buffer.
@@@ -347,7 -377,7 +377,7 @@@ BEG and END, when specified, are the po
    (if (null x)
        (user-error "No candidates")
      (goto-char (point-min))
-     (forward-line (1- (read x)))
+     (forward-line (1- (read (get-text-property 0 'display x))))
      (re-search-forward
       (ivy--regex input) (line-end-position) t)
      (swiper--ensure-visible)
      (isearch-exit)
      (swiper query)))
  
+ (defvar swiper-multi-buffers nil
+   "Store the current list of buffers.")
+ (defvar swiper-multi-candidates nil
+   "Store the list of candidates for `swiper-multi'.")
+ (defun swiper-multi-prompt ()
+   (format "Buffers (%s): "
+           (mapconcat #'identity swiper-multi-buffers ", ")))
+ (defun swiper-multi ()
+   "Select one or more buffers.
+ Run `swiper' for those buffers."
+   (interactive)
+   (setq swiper-multi-buffers nil)
+   (setq swiper-multi-candidates nil)
+   (ivy-read (swiper-multi-prompt)
+             'internal-complete-buffer
+             :action 'swiper-multi-action-1)
+   (ivy-read "Swiper: " swiper-multi-candidates
+             :action 'swiper-multi-action-2
+             :unwind #'swiper--cleanup))
+ (defun swiper-multi-action-1 (x)
+   (if (member x swiper-multi-buffers)
+       (progn
+         (setq swiper-multi-buffers (delete x swiper-multi-buffers)))
+     (unless (equal x "")
+       (setq swiper-multi-buffers (append swiper-multi-buffers (list x)))))
+   (let ((prompt (swiper-multi-prompt)))
+     (setf (ivy-state-prompt ivy-last) prompt)
+     (setq ivy--prompt (concat "%-4d " prompt)))
+   (cond ((memq this-command '(ivy-done
+                               ivy-alt-done
+                               ivy-immediate-done))
+          (let ((ww (window-width)))
+            (dolist (buf swiper-multi-buffers)
+              (with-current-buffer buf
+                (setq swiper-multi-candidates
+                      (append
+                       (mapcar
+                        (lambda (s)
+                          (setq s (concat s " "))
+                          (let ((len (length s)))
+                            (put-text-property
+                             (1- len) len 'display
+                             (concat
+                              (make-string
+                               (max
+                                (- ww
+                                   (string-width s)
+                                   (length (buffer-name))
+                                   1)
+                                0)
+                               ?\ )
+                              (buffer-name))
+                             s)
+                            s))
+                        (swiper--candidates))
+                       swiper-multi-candidates))))))
+         ((eq this-command 'ivy-call)
+          (delete-minibuffer-contents))))
+ (defun swiper-multi-action-2 (x)
+   (let ((buf-space (get-text-property (1- (length x)) 'display x)))
+     (with-ivy-window
+       (when (string-match "\\` *\\([^ ]+\\)\\'" buf-space)
+         (switch-to-buffer (match-string 1 buf-space))
+         (goto-char (point-min))
+         (forward-line (1- (read x)))
+         (re-search-forward
+          (ivy--regex ivy-text)
+          (line-end-position) t)
+         (unless (eq ivy-exit 'done)
+           (swiper--cleanup)
+           (swiper--add-overlays (ivy--regex ivy-text)))))))
  (provide 'swiper)
  
  ;;; swiper.el ends here