]> code.delx.au - gnu-emacs-elpa/blob - swiper.el
ivy.el (ivy--format-minibuffer-line): Add ignore-errors
[gnu-emacs-elpa] / swiper.el
1 ;;; swiper.el --- Isearch with an overview. Oh, man! -*- lexical-binding: t -*-
2
3 ;; Copyright (C) 2015 Free Software Foundation, Inc.
4
5 ;; Author: Oleh Krehel <ohwoeowho@gmail.com>
6 ;; URL: https://github.com/abo-abo/swiper
7 ;; Version: 0.7.0
8 ;; Package-Requires: ((emacs "24.1"))
9 ;; Keywords: matching
10
11 ;; This file is part of GNU Emacs.
12
13 ;; This file is free software; you can redistribute it and/or modify
14 ;; it under the terms of the GNU General Public License as published by
15 ;; the Free Software Foundation; either version 3, or (at your option)
16 ;; any later version.
17
18 ;; This program is distributed in the hope that it will be useful,
19 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 ;; GNU General Public License for more details.
22
23 ;; For a full copy of the GNU General Public License
24 ;; see <http://www.gnu.org/licenses/>.
25
26 ;;; Commentary:
27 ;;
28 ;; This package gives an overview of the current regex search
29 ;; candidates. The search regex can be split into groups with a
30 ;; space. Each group is highlighted with a different face.
31 ;;
32 ;; It can double as a quick `regex-builder', although only single
33 ;; lines will be matched.
34 ;;
35 ;; It also provides `ivy-mode': a global minor mode that uses the
36 ;; matching back end of `swiper' for all matching on your system,
37 ;; including file matching. You can use it in place of `ido-mode'
38 ;; (can't have both on at once).
39
40 ;;; Code:
41 (require 'ivy)
42
43 (defgroup swiper nil
44 "`isearch' with an overview."
45 :group 'matching
46 :prefix "swiper-")
47
48 (defface swiper-match-face-1
49 '((t (:inherit isearch-lazy-highlight-face)))
50 "The background face for `swiper' matches.")
51
52 (defface swiper-match-face-2
53 '((t (:inherit isearch)))
54 "Face for `swiper' matches modulo 1.")
55
56 (defface swiper-match-face-3
57 '((t (:inherit match)))
58 "Face for `swiper' matches modulo 2.")
59
60 (defface swiper-match-face-4
61 '((t (:inherit isearch-fail)))
62 "Face for `swiper' matches modulo 3.")
63
64 (defface swiper-line-face
65 '((t (:inherit highlight)))
66 "Face for current `swiper' line.")
67
68 (defcustom swiper-faces '(swiper-match-face-1
69 swiper-match-face-2
70 swiper-match-face-3
71 swiper-match-face-4)
72 "List of `swiper' faces for group matches."
73 :group 'ivy-faces
74 :type 'list)
75
76 (defcustom swiper-min-highlight 2
77 "Only highlight matches for regexps at least this long."
78 :type 'integer)
79
80 (defvar swiper-map
81 (let ((map (make-sparse-keymap)))
82 (define-key map (kbd "M-q") 'swiper-query-replace)
83 (define-key map (kbd "C-l") 'swiper-recenter-top-bottom)
84 (define-key map (kbd "C-'") 'swiper-avy)
85 (define-key map (kbd "C-7") 'swiper-mc)
86 (define-key map (kbd "C-c C-f") 'swiper-toggle-face-matching)
87 map)
88 "Keymap for swiper.")
89
90 (defun swiper-query-replace ()
91 "Start `query-replace' with string to replace from last search string."
92 (interactive)
93 (if (null (window-minibuffer-p))
94 (user-error "Should only be called in the minibuffer through `swiper-map'")
95 (let* ((enable-recursive-minibuffers t)
96 (from (ivy--regex ivy-text))
97 (to (minibuffer-with-setup-hook
98 (lambda ()
99 (setq minibuffer-default
100 (if (string-match "\\`\\\\_<\\(.*\\)\\\\_>\\'" ivy-text)
101 (match-string 1 ivy-text)
102 ivy-text)))
103 (read-from-minibuffer (format "Query replace %s with: " from)))))
104 (swiper--cleanup)
105 (ivy-exit-with-action
106 (lambda (_)
107 (with-ivy-window
108 (move-beginning-of-line 1)
109 (perform-replace from to
110 t t nil)))))))
111
112 (defvar avy-background)
113 (defvar avy-all-windows)
114 (defvar avy-style)
115 (defvar avy-keys)
116 (declare-function avy--regex-candidates "ext:avy")
117 (declare-function avy--process "ext:avy")
118 (declare-function avy--overlay-post "ext:avy")
119 (declare-function avy-action-goto "ext:avy")
120 (declare-function avy--done "ext:avy")
121 (declare-function avy--make-backgrounds "ext:avy")
122 (declare-function avy-window-list "ext:avy")
123 (declare-function avy-read "ext:avy")
124 (declare-function avy-read-de-bruijn "ext:avy")
125 (declare-function avy-tree "ext:avy")
126 (declare-function avy-push-mark "ext:avy")
127 (declare-function avy--remove-leading-chars "ext:avy")
128
129 ;;;###autoload
130 (defun swiper-avy ()
131 "Jump to one of the current swiper candidates."
132 (interactive)
133 (unless (string= ivy-text "")
134 (let* ((avy-all-windows nil)
135 (candidates (append
136 (with-ivy-window
137 (avy--regex-candidates
138 (ivy--regex ivy-text)))
139 (save-excursion
140 (save-restriction
141 (narrow-to-region (window-start) (window-end))
142 (goto-char (point-min))
143 (forward-line)
144 (let ((cands))
145 (while (< (point) (point-max))
146 (push (cons (1+ (point))
147 (selected-window))
148 cands)
149 (forward-line))
150 cands)))))
151 (candidate (unwind-protect
152 (prog2
153 (avy--make-backgrounds
154 (append (avy-window-list)
155 (list (ivy-state-window ivy-last))))
156 (if (eq avy-style 'de-bruijn)
157 (avy-read-de-bruijn
158 candidates avy-keys)
159 (avy-read (avy-tree candidates avy-keys)
160 #'avy--overlay-post
161 #'avy--remove-leading-chars))
162 (avy-push-mark))
163 (avy--done))))
164 (if (window-minibuffer-p (cdr candidate))
165 (progn
166 (ivy-set-index (- (line-number-at-pos (car candidate)) 2))
167 (ivy--exhibit)
168 (ivy-done)
169 (ivy-call))
170 (ivy-quit-and-run
171 (avy-action-goto (caar candidate)))))))
172
173 (declare-function mc/create-fake-cursor-at-point "ext:multiple-cursors-core")
174 (declare-function multiple-cursors-mode "ext:multiple-cursors-core")
175
176 (defun swiper-mc ()
177 (unless (require 'multiple-cursors nil t)
178 (error "multiple-cursors isn't installed"))
179 (let ((cands (nreverse ivy--old-cands)))
180 (unless (string= ivy-text "")
181 (ivy-exit-with-action
182 (lambda (_)
183 (let (cand)
184 (while (setq cand (pop cands))
185 (swiper--action cand)
186 (when cands
187 (mc/create-fake-cursor-at-point))))
188 (multiple-cursors-mode 1))))))
189
190 (defun swiper-recenter-top-bottom (&optional arg)
191 "Call (`recenter-top-bottom' ARG)."
192 (interactive "P")
193 (with-ivy-window
194 (recenter-top-bottom arg)))
195
196 (defvar swiper-font-lock-exclude
197 '(package-menu-mode
198 gnus-summary-mode
199 gnus-article-mode
200 gnus-group-mode
201 emms-playlist-mode
202 emms-stream-mode
203 erc-mode
204 org-agenda-mode
205 dired-mode
206 jabber-chat-mode
207 elfeed-search-mode
208 elfeed-show-mode
209 fundamental-mode
210 Man-mode
211 woman-mode
212 mu4e-view-mode
213 mu4e-headers-mode
214 help-mode
215 debbugs-gnu-mode
216 occur-mode
217 occur-edit-mode
218 bongo-mode
219 bongo-library-mode
220 bongo-playlist-mode
221 eww-mode
222 twittering-mode
223 vc-dir-mode
224 rcirc-mode
225 sauron-mode
226 w3m-mode)
227 "List of major-modes that are incompatible with font-lock-ensure.")
228
229 (defun swiper-font-lock-ensure-p ()
230 "Return non-nil if we should font-lock-ensure."
231 (or (derived-mode-p 'magit-mode)
232 (bound-and-true-p magit-blame-mode)
233 (memq major-mode swiper-font-lock-exclude)))
234
235 (defun swiper-font-lock-ensure ()
236 "Ensure the entired buffer is highlighted."
237 (unless (swiper-font-lock-ensure-p)
238 (unless (or (> (buffer-size) 100000) (null font-lock-mode))
239 (if (fboundp 'font-lock-ensure)
240 (font-lock-ensure)
241 (with-no-warnings (font-lock-fontify-buffer))))))
242
243 (defvar swiper--format-spec ""
244 "Store the current candidates format spec.")
245
246 (defvar swiper--width nil
247 "Store the number of digits needed for the longest line nubmer.")
248
249 (defvar swiper-use-visual-line nil
250 "When non-nil, use `line-move' instead of `forward-line'.")
251
252 (declare-function outline-show-all "outline")
253
254 (defun swiper--candidates (&optional numbers-width)
255 "Return a list of this buffer lines.
256
257 NUMBERS-WIDTH, when specified, is used for width spec of line
258 numbers; replaces calculating the width from buffer line count."
259 (if (and visual-line-mode
260 ;; super-slow otherwise
261 (< (buffer-size) 20000))
262 (progn
263 (when (eq major-mode 'org-mode)
264 (require 'outline)
265 (if (fboundp 'outline-show-all)
266 (outline-show-all)
267 (with-no-warnings
268 (show-all))))
269 (setq swiper-use-visual-line t))
270 (setq swiper-use-visual-line nil))
271 (let ((n-lines (count-lines (point-min) (point-max))))
272 (unless (zerop n-lines)
273 (setq swiper--width (or numbers-width
274 (1+ (floor (log n-lines 10)))))
275 (setq swiper--format-spec
276 (format "%%-%dd " swiper--width))
277 (let ((line-number 0)
278 (advancer (if swiper-use-visual-line
279 (lambda (arg) (line-move arg t))
280 #'forward-line))
281 candidates)
282 (save-excursion
283 (goto-char (point-min))
284 (swiper-font-lock-ensure)
285 (while (< (point) (point-max))
286 (let ((str (concat
287 " "
288 (replace-regexp-in-string
289 "\t" " "
290 (if swiper-use-visual-line
291 (buffer-substring
292 (save-excursion
293 (beginning-of-visual-line)
294 (point))
295 (save-excursion
296 (end-of-visual-line)
297 (point)))
298 (buffer-substring
299 (point)
300 (line-end-position)))))))
301 (remove-text-properties 0 (length str) '(field) str)
302 (put-text-property 0 1 'display
303 (format swiper--format-spec
304 (cl-incf line-number))
305 str)
306 (push str candidates))
307 (funcall advancer 1))
308 (nreverse candidates))))))
309
310 (defvar swiper--opoint 1
311 "The point when `swiper' starts.")
312
313 ;;;###autoload
314 (defun swiper (&optional initial-input)
315 "`isearch' with an overview.
316 When non-nil, INITIAL-INPUT is the initial search pattern."
317 (interactive)
318 (swiper--ivy (swiper--candidates) initial-input))
319
320 (declare-function string-trim-right "subr-x")
321
322 (defun swiper-occur (&optional revert)
323 "Generate a custom occur buffer for `swiper'.
324 When REVERT is non-nil, regenerate the current *ivy-occur* buffer."
325 (let* ((buffer (ivy-state-buffer ivy-last))
326 (fname (propertize
327 (with-ivy-window
328 (if (buffer-file-name buffer)
329 (file-name-nondirectory
330 (buffer-file-name buffer))
331 (buffer-name buffer)))
332 'face
333 'compilation-info))
334 (cands (mapcar
335 (lambda (s)
336 (format "%s:%s:%s"
337 fname
338 (propertize
339 (string-trim-right
340 (get-text-property 0 'display s))
341 'face 'compilation-line-number)
342 (substring s 1)))
343 (if (null revert)
344 ivy--old-cands
345 (setq ivy--old-re nil)
346 (let ((ivy--regex-function 'swiper--re-builder))
347 (ivy--filter
348 (progn (string-match "\"\\(.*\\)\"" (buffer-name))
349 (match-string 1 (buffer-name)))
350 (with-current-buffer buffer
351 (swiper--candidates))))))))
352 (unless (eq major-mode 'ivy-occur-grep-mode)
353 (ivy-occur-grep-mode)
354 (font-lock-mode -1))
355 (insert (format "-*- mode:grep; default-directory: %S -*-\n\n\n"
356 default-directory))
357 (insert (format "%d candidates:\n" (length cands)))
358 (ivy--occur-insert-lines
359 (mapcar
360 (lambda (cand) (concat "./" cand))
361 cands))
362 (goto-char (point-min))
363 (forward-line 4)))
364
365 (ivy-set-occur 'swiper 'swiper-occur)
366
367 (declare-function evil-jumper--set-jump "ext:evil-jumper")
368
369 (defvar swiper--current-line nil)
370 (defvar swiper--current-match-start nil)
371
372 (defun swiper--init ()
373 "Perform initialization common to both completion methods."
374 (setq swiper--current-line nil)
375 (setq swiper--current-match-start nil)
376 (setq swiper--opoint (point))
377 (when (bound-and-true-p evil-jumper-mode)
378 (evil-jumper--set-jump)))
379
380 (defun swiper--re-builder (str)
381 "Transform STR into a swiper regex.
382 This is the regex used in the minibuffer where candidates have
383 line numbers. For the buffer, use `ivy--regex' instead."
384 (replace-regexp-in-string
385 "\t" " "
386 (cond
387 ((equal str "")
388 "")
389 ((equal str "^")
390 (setq ivy--subexps 0)
391 ".")
392 ((string-match "^\\^" str)
393 (setq ivy--old-re "")
394 (let ((re (ivy--regex-plus (substring str 1))))
395 (if (zerop ivy--subexps)
396 (prog1 (format "^ ?\\(%s\\)" re)
397 (setq ivy--subexps 1))
398 (format "^ %s" re))))
399 (t
400 (ivy--regex-plus str)))))
401
402 (defvar swiper-history nil
403 "History for `swiper'.")
404
405 (defvar swiper-invocation-face nil
406 "The face at the point of invocation of `swiper'.")
407
408 (defun swiper--ivy (candidates &optional initial-input)
409 "Select one of CANDIDATES and move there.
410 When non-nil, INITIAL-INPUT is the initial search pattern."
411 (interactive)
412 (swiper--init)
413 (setq swiper-invocation-face
414 (plist-get (text-properties-at (point)) 'face))
415 (let ((preselect
416 (if swiper-use-visual-line
417 (count-screen-lines
418 (point-min)
419 (save-excursion (beginning-of-visual-line) (point)))
420 (1- (line-number-at-pos))))
421 (minibuffer-allow-text-properties t)
422 res)
423 (unwind-protect
424 (and
425 (setq res
426 (ivy-read
427 "Swiper: "
428 candidates
429 :initial-input initial-input
430 :keymap swiper-map
431 :preselect preselect
432 :require-match t
433 :update-fn #'swiper--update-input-ivy
434 :unwind #'swiper--cleanup
435 :action #'swiper--action
436 :re-builder #'swiper--re-builder
437 :history 'swiper-history
438 :caller 'swiper))
439 (point))
440 (unless res
441 (goto-char swiper--opoint)))))
442
443 (defun swiper-toggle-face-matching ()
444 "Toggle matching only the candidates with `swiper-invocation-face'."
445 (interactive)
446 (setf (ivy-state-matcher ivy-last)
447 (if (ivy-state-matcher ivy-last)
448 nil
449 #'swiper--face-matcher))
450 (setq ivy--old-re nil))
451
452 (defun swiper--face-matcher (regexp candidates)
453 "Return REGEXP-matching CANDIDATES.
454 Matched candidates should have `swiper-invocation-face'."
455 (cl-remove-if-not
456 (lambda (x)
457 (and
458 (string-match regexp x)
459 (let ((s (match-string 0 x))
460 (i 0))
461 (while (and (< i (length s))
462 (text-property-any
463 i (1+ i)
464 'face swiper-invocation-face
465 s))
466 (cl-incf i))
467 (eq i (length s)))))
468 candidates))
469
470 (defun swiper--ensure-visible ()
471 "Remove overlays hiding point."
472 (let ((overlays (overlays-at (1- (point))))
473 ov expose)
474 (while (setq ov (pop overlays))
475 (if (and (invisible-p (overlay-get ov 'invisible))
476 (setq expose (overlay-get ov 'isearch-open-invisible)))
477 (funcall expose ov)))))
478
479 (defvar swiper--overlays nil
480 "Store overlays.")
481
482 (defun swiper--cleanup ()
483 "Clean up the overlays."
484 (while swiper--overlays
485 (delete-overlay (pop swiper--overlays)))
486 (save-excursion
487 (goto-char (point-min))
488 (isearch-clean-overlays)))
489
490 (defun swiper--update-input-ivy ()
491 "Called when `ivy' input is updated."
492 (with-ivy-window
493 (swiper--cleanup)
494 (when (> (length ivy--current) 0)
495 (let* ((re (replace-regexp-in-string
496 " " "\t"
497 (funcall ivy--regex-function ivy-text)))
498 (re (if (stringp re) re (caar re)))
499 (str (get-text-property 0 'display ivy--current))
500 (num (if (string-match "^[0-9]+" str)
501 (string-to-number (match-string 0 str))
502 0)))
503 (unless (eq this-command 'ivy-yank-word)
504 (when (cl-plusp num)
505 (unless (if swiper--current-line
506 (eq swiper--current-line num)
507 (eq (line-number-at-pos) num))
508 (goto-char (point-min))
509 (if swiper-use-visual-line
510 (line-move (1- num))
511 (forward-line (1- num))))
512 (if (and (equal ivy-text "")
513 (>= swiper--opoint (line-beginning-position))
514 (<= swiper--opoint (line-end-position)))
515 (goto-char swiper--opoint)
516 (if (eq swiper--current-line num)
517 (when swiper--current-match-start
518 (goto-char swiper--current-match-start))
519 (setq swiper--current-line num))
520 (when (re-search-forward re (line-end-position) t)
521 (setq swiper--current-match-start (match-beginning 0))))
522 (isearch-range-invisible (line-beginning-position)
523 (line-end-position))
524 (unless (and (>= (point) (window-start))
525 (<= (point) (window-end (ivy-state-window ivy-last) t)))
526 (recenter))))
527 (swiper--add-overlays re)))))
528
529 (defun swiper--add-overlays (re &optional beg end wnd)
530 "Add overlays for RE regexp in visible part of the current buffer.
531 BEG and END, when specified, are the point bounds.
532 WND, when specified is the window."
533 (setq wnd (or wnd (ivy-state-window ivy-last)))
534 (let ((ov (if visual-line-mode
535 (make-overlay
536 (save-excursion
537 (beginning-of-visual-line)
538 (point))
539 (save-excursion
540 (end-of-visual-line)
541 (point)))
542 (make-overlay
543 (line-beginning-position)
544 (1+ (line-end-position))))))
545 (overlay-put ov 'face 'swiper-line-face)
546 (overlay-put ov 'window wnd)
547 (push ov swiper--overlays)
548 (let* ((wh (window-height))
549 (beg (or beg (save-excursion
550 (forward-line (- wh))
551 (point))))
552 (end (or end (save-excursion
553 (forward-line wh)
554 (point)))))
555 (when (>= (length re) swiper-min-highlight)
556 (save-excursion
557 (goto-char beg)
558 ;; RE can become an invalid regexp
559 (while (and (ignore-errors (re-search-forward re end t))
560 (> (- (match-end 0) (match-beginning 0)) 0))
561 (let ((i 0))
562 (while (<= i ivy--subexps)
563 (when (match-beginning i)
564 (let ((overlay (make-overlay (match-beginning i)
565 (match-end i)))
566 (face
567 (cond ((zerop ivy--subexps)
568 (cadr swiper-faces))
569 ((zerop i)
570 (car swiper-faces))
571 (t
572 (nth (1+ (mod (+ i 2) (1- (length swiper-faces))))
573 swiper-faces)))))
574 (push overlay swiper--overlays)
575 (overlay-put overlay 'face face)
576 (overlay-put overlay 'window wnd)
577 (overlay-put overlay 'priority i)))
578 (cl-incf i)))))))))
579
580 (defun swiper--action (x)
581 "Goto line X."
582 (let ((ln (1- (read (or (get-text-property 0 'display x)
583 (and (string-match ":\\([0-9]+\\):.*\\'" x)
584 (match-string-no-properties 1 x))))))
585 (re (ivy--regex ivy-text)))
586 (if (null x)
587 (user-error "No candidates")
588 (with-ivy-window
589 (unless (equal (current-buffer)
590 (ivy-state-buffer ivy-last))
591 (switch-to-buffer (ivy-state-buffer ivy-last)))
592 (goto-char (point-min))
593 (funcall (if swiper-use-visual-line
594 #'line-move
595 #'forward-line)
596 ln)
597 (re-search-forward re (line-end-position) t)
598 (swiper--ensure-visible)
599 (when (/= (point) swiper--opoint)
600 (unless (and transient-mark-mode mark-active)
601 (when (eq ivy-exit 'done)
602 (push-mark swiper--opoint t)
603 (message "Mark saved where search started"))))
604 (add-to-history
605 'regexp-search-ring
606 re
607 regexp-search-ring-max)))))
608
609 ;; (define-key isearch-mode-map (kbd "C-o") 'swiper-from-isearch)
610 (defun swiper-from-isearch ()
611 "Invoke `swiper' from isearch."
612 (interactive)
613 (let ((query (if isearch-regexp
614 isearch-string
615 (regexp-quote isearch-string))))
616 (isearch-exit)
617 (swiper query)))
618
619 (defvar swiper-multi-buffers nil
620 "Store the current list of buffers.")
621
622 (defvar swiper-multi-candidates nil
623 "Store the list of candidates for `swiper-multi'.")
624
625 (defun swiper-multi-prompt ()
626 (format "Buffers (%s): "
627 (mapconcat #'identity swiper-multi-buffers ", ")))
628
629 (defun swiper-multi ()
630 "Select one or more buffers.
631 Run `swiper' for those buffers."
632 (interactive)
633 (setq swiper-multi-buffers nil)
634 (ivy-read (swiper-multi-prompt)
635 'internal-complete-buffer
636 :action 'swiper-multi-action-1)
637 (ivy-read "Swiper: " swiper-multi-candidates
638 :action 'swiper-multi-action-2
639 :unwind #'swiper--cleanup
640 :caller 'swiper-multi))
641
642 (defun swiper-all ()
643 "Run `swiper' for all opened buffers."
644 (interactive)
645 (ivy-read "Swiper: " (swiper--multi-candidates
646 (cl-remove-if-not
647 #'buffer-file-name
648 (buffer-list)))
649 :action 'swiper-multi-action-2
650 :unwind #'swiper--cleanup
651 :update-fn (lambda ()
652 (swiper-multi-action-2 ivy--current))
653 :caller 'swiper-multi))
654
655 (defun swiper--multi-candidates (buffers)
656 (let* ((ww (window-width))
657 (res nil)
658 (column-2 (apply #'max
659 (mapcar
660 (lambda (b)
661 (length (buffer-name b)))
662 buffers)))
663 (column-1 (- ww 4 column-2 1)))
664 (dolist (buf buffers)
665 (with-current-buffer buf
666 (setq res
667 (append
668 (mapcar
669 (lambda (s)
670 (setq s (concat (ivy--truncate-string s column-1) " "))
671 (let ((len (length s)))
672 (put-text-property
673 (1- len) len 'display
674 (concat
675 (make-string
676 (- ww (string-width s) (length (buffer-name)) 3)
677 ?\ )
678 (buffer-name))
679 s)
680 s))
681 (swiper--candidates 4))
682 res))
683 nil))
684 res))
685
686 (defun swiper-multi-action-1 (x)
687 (if (member x swiper-multi-buffers)
688 (progn
689 (setq swiper-multi-buffers (delete x swiper-multi-buffers)))
690 (unless (equal x "")
691 (setq swiper-multi-buffers (append swiper-multi-buffers (list x)))))
692 (let ((prompt (swiper-multi-prompt)))
693 (setf (ivy-state-prompt ivy-last) prompt)
694 (setq ivy--prompt (concat "%-4d " prompt)))
695 (cond ((memq this-command '(ivy-done
696 ivy-alt-done
697 ivy-immediate-done))
698 (setq swiper-multi-candidates
699 (swiper--multi-candidates
700 (mapcar #'get-buffer swiper-multi-buffers))))
701 ((eq this-command 'ivy-call)
702 (delete-minibuffer-contents))))
703
704 (defun swiper-multi-action-2 (x)
705 (let ((buf-space (get-text-property (1- (length x)) 'display x)))
706 (with-ivy-window
707 (when (string-match "\\` *\\([^ ]+\\)\\'" buf-space)
708 (switch-to-buffer (match-string 1 buf-space))
709 (goto-char (point-min))
710 (forward-line (1- (read (get-text-property 0 'display x))))
711 (re-search-forward
712 (ivy--regex ivy-text)
713 (line-end-position) t)
714 (unless (eq ivy-exit 'done)
715 (swiper--cleanup)
716 (swiper--add-overlays (ivy--regex ivy-text)))))))
717
718 (provide 'swiper)
719
720 ;;; swiper.el ends here