]> code.delx.au - gnu-emacs-elpa/blob - ivy.el
ivy.el (ivy-resume): Add a guard against null :action
[gnu-emacs-elpa] / ivy.el
1 ;;; ivy.el --- Incremental Vertical completYon -*- 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 ;; Package-Requires: ((emacs "24.1"))
8 ;; Keywords: matching
9
10 ;; This file is part of GNU Emacs.
11
12 ;; This file is free software; you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 3, or (at your option)
15 ;; any later version.
16
17 ;; This program is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ;; GNU General Public License for more details.
21
22 ;; For a full copy of the GNU General Public License
23 ;; see <http://www.gnu.org/licenses/>.
24
25 ;;; Commentary:
26 ;;
27 ;; This package provides `ivy-read' as an alternative to
28 ;; `completing-read' and similar functions.
29 ;;
30 ;; There's no intricate code to determine the best candidate.
31 ;; Instead, the user can navigate to it with `ivy-next-line' and
32 ;; `ivy-previous-line'.
33 ;;
34 ;; The matching is done by splitting the input text by spaces and
35 ;; re-building it into a regex.
36 ;; So "for example" is transformed into "\\(for\\).*\\(example\\)".
37
38 ;;; Code:
39 (require 'cl-lib)
40 (require 'ffap)
41
42 ;;* Customization
43 (defgroup ivy nil
44 "Incremental vertical completion."
45 :group 'convenience)
46
47 (defgroup ivy-faces nil
48 "Font-lock faces for `ivy'."
49 :group 'ivy
50 :group 'faces)
51
52 (defface ivy-current-match
53 '((((class color) (background light))
54 :background "#1a4b77" :foreground "white")
55 (((class color) (background dark))
56 :background "#65a7e2" :foreground "black"))
57 "Face used by Ivy for highlighting the current match.")
58
59 (defface ivy-minibuffer-match-face-1
60 '((((class color) (background light))
61 :background "#d3d3d3")
62 (((class color) (background dark))
63 :background "#555555"))
64 "The background face for `ivy' minibuffer matches.")
65
66 (defface ivy-minibuffer-match-face-2
67 '((((class color) (background light))
68 :background "#e99ce8" :weight bold)
69 (((class color) (background dark))
70 :background "#777777" :weight bold))
71 "Face for `ivy' minibuffer matches numbered 1 modulo 3.")
72
73 (defface ivy-minibuffer-match-face-3
74 '((((class color) (background light))
75 :background "#bbbbff" :weight bold)
76 (((class color) (background dark))
77 :background "#7777ff" :weight bold))
78 "Face for `ivy' minibuffer matches numbered 2 modulo 3.")
79
80 (defface ivy-minibuffer-match-face-4
81 '((((class color) (background light))
82 :background "#ffbbff" :weight bold)
83 (((class color) (background dark))
84 :background "#8a498a" :weight bold))
85 "Face for `ivy' minibuffer matches numbered 3 modulo 3.")
86
87 (defface ivy-confirm-face
88 '((t :foreground "ForestGreen" :inherit minibuffer-prompt))
89 "Face used by Ivy for a confirmation prompt.")
90
91 (defface ivy-match-required-face
92 '((t :foreground "red" :inherit minibuffer-prompt))
93 "Face used by Ivy for a match required prompt.")
94
95 (defface ivy-subdir
96 '((t :inherit dired-directory))
97 "Face used by Ivy for highlighting subdirs in the alternatives.")
98
99 (defface ivy-modified-buffer
100 '((t :inherit default))
101 "Face used by Ivy for highlighting modified file visiting buffers.")
102
103 (defface ivy-remote
104 '((t :foreground "#110099"))
105 "Face used by Ivy for highlighting remotes in the alternatives.")
106
107 (defface ivy-virtual
108 '((t :inherit font-lock-builtin-face))
109 "Face used by Ivy for matching virtual buffer names.")
110
111 (setcdr (assoc load-file-name custom-current-group-alist) 'ivy)
112
113 (defcustom ivy-height 10
114 "Number of lines for the minibuffer window."
115 :type 'integer)
116
117 (defcustom ivy-count-format "%-4d "
118 "The style to use for displaying the current candidate count for `ivy-read'.
119 Set this to \"\" to suppress the count visibility.
120 Set this to \"(%d/%d) \" to display both the index and the count."
121 :type '(choice
122 (const :tag "Count disabled" "")
123 (const :tag "Count matches" "%-4d ")
124 (const :tag "Count matches and show current match" "(%d/%d) ")
125 string))
126
127 (defcustom ivy-wrap nil
128 "When non-nil, wrap around after the first and the last candidate."
129 :type 'boolean)
130
131 (defcustom ivy-display-style (unless (version< emacs-version "24.5") 'fancy)
132 "The style for formatting the minibuffer.
133
134 By default, the matched strings are copied as is.
135
136 The fancy display style highlights matching parts of the regexp,
137 a behavior similar to `swiper'.
138
139 This setting depends on `add-face-text-property' - a C function
140 available as of Emacs 24.5. Fancy style will render poorly in
141 earlier versions of Emacs."
142 :type '(choice
143 (const :tag "Plain" nil)
144 (const :tag "Fancy" fancy)))
145
146 (defcustom ivy-on-del-error-function 'minibuffer-keyboard-quit
147 "The handler for when `ivy-backward-delete-char' throws.
148 Usually a quick exit out of the minibuffer."
149 :type 'function)
150
151 (defcustom ivy-extra-directories '("../" "./")
152 "Add this to the front of the list when completing file names.
153 Only \"./\" and \"../\" apply here. They appear in reverse order."
154 :type '(repeat :tag "Dirs"
155 (choice
156 (const :tag "Parent Directory" "../")
157 (const :tag "Current Directory" "./"))))
158
159 (defcustom ivy-use-virtual-buffers nil
160 "When non-nil, add `recentf-mode' and bookmarks to `ivy-switch-buffer'."
161 :type 'boolean)
162
163 (defvar ivy--actions-list nil
164 "A list of extra actions per command.")
165
166 (defun ivy-set-actions (cmd actions)
167 "Set CMD extra exit points to ACTIONS."
168 (setq ivy--actions-list
169 (plist-put ivy--actions-list cmd actions)))
170
171 (defvar ivy--display-transformers-list nil
172 "A list of str->str transformers per command.")
173
174 (defun ivy-set-display-transformer (cmd transformer)
175 "Set CMD a displayed candidate TRANSFORMER.
176
177 It's a lambda that takes a string one of the candidates in the
178 collection and returns a string for display, the same candidate
179 plus some extra information.
180
181 This lambda is called only on the `ivy-height' candidates that
182 are about to be displayed, not on the whole collection."
183 (setq ivy--display-transformers-list
184 (plist-put ivy--display-transformers-list cmd transformer)))
185
186 (defvar ivy--sources-list nil
187 "A list of extra sources per command.")
188
189 (defun ivy-set-sources (cmd sources)
190 "Attach to CMD a list of extra SOURCES.
191
192 Each static source is a function that takes no argument and
193 returns a list of strings.
194
195 The '(original-source) determines the position of the original
196 dynamic source.
197
198 Extra dynamic sources aren't supported yet.
199
200 Example:
201
202 (defun small-recentf ()
203 (cl-subseq recentf-list 0 20))
204
205 (ivy-set-sources
206 'counsel-locate
207 '((small-recentf)
208 (original-source)))
209 "
210 (setq ivy--sources-list
211 (plist-put ivy--sources-list cmd sources)))
212
213 ;;* Keymap
214 (require 'delsel)
215 (defvar ivy-minibuffer-map
216 (let ((map (make-sparse-keymap)))
217 (define-key map (kbd "C-m") 'ivy-done)
218 (define-key map (kbd "C-M-m") 'ivy-call)
219 (define-key map (kbd "C-j") 'ivy-alt-done)
220 (define-key map (kbd "C-M-j") 'ivy-immediate-done)
221 (define-key map (kbd "TAB") 'ivy-partial-or-done)
222 (define-key map (kbd "C-n") 'ivy-next-line)
223 (define-key map (kbd "C-p") 'ivy-previous-line)
224 (define-key map (kbd "<down>") 'ivy-next-line)
225 (define-key map (kbd "<up>") 'ivy-previous-line)
226 (define-key map (kbd "C-s") 'ivy-next-line-or-history)
227 (define-key map (kbd "C-r") 'ivy-reverse-i-search)
228 (define-key map (kbd "SPC") 'self-insert-command)
229 (define-key map (kbd "DEL") 'ivy-backward-delete-char)
230 (define-key map (kbd "M-DEL") 'ivy-backward-kill-word)
231 (define-key map (kbd "C-d") 'ivy-delete-char)
232 (define-key map (kbd "C-f") 'ivy-forward-char)
233 (define-key map (kbd "M-d") 'ivy-kill-word)
234 (define-key map (kbd "M-<") 'ivy-beginning-of-buffer)
235 (define-key map (kbd "M->") 'ivy-end-of-buffer)
236 (define-key map (kbd "M-n") 'ivy-next-history-element)
237 (define-key map (kbd "M-p") 'ivy-previous-history-element)
238 (define-key map (kbd "C-g") 'minibuffer-keyboard-quit)
239 (define-key map (kbd "C-v") 'ivy-scroll-up-command)
240 (define-key map (kbd "M-v") 'ivy-scroll-down-command)
241 (define-key map (kbd "C-M-n") 'ivy-next-line-and-call)
242 (define-key map (kbd "C-M-p") 'ivy-previous-line-and-call)
243 (define-key map (kbd "M-q") 'ivy-toggle-regexp-quote)
244 (define-key map (kbd "M-j") 'ivy-yank-word)
245 (define-key map (kbd "M-i") 'ivy-insert-current)
246 (define-key map (kbd "C-o") 'hydra-ivy/body)
247 (define-key map (kbd "M-o") 'ivy-dispatching-done)
248 (define-key map (kbd "C-M-o") 'ivy-dispatching-call)
249 (define-key map (kbd "C-k") 'ivy-kill-line)
250 (define-key map (kbd "S-SPC") 'ivy-restrict-to-matches)
251 (define-key map (kbd "M-w") 'ivy-kill-ring-save)
252 (define-key map (kbd "C-'") 'ivy-avy)
253 (define-key map (kbd "C-M-a") 'ivy-read-action)
254 (define-key map (kbd "C-c C-o") 'ivy-occur)
255 (define-key map (kbd "C-c C-a") 'ivy-toggle-ignore)
256 (define-key map (kbd "C-h m") 'ivy-help)
257 map)
258 "Keymap used in the minibuffer.")
259 (autoload 'hydra-ivy/body "ivy-hydra" "" t)
260
261 (defvar ivy-mode-map
262 (let ((map (make-sparse-keymap)))
263 (define-key map [remap switch-to-buffer]
264 'ivy-switch-buffer)
265 (define-key map [remap switch-to-buffer-other-window]
266 'ivy-switch-buffer-other-window)
267 map)
268 "Keymap for `ivy-mode'.")
269
270 ;;* Globals
271 (cl-defstruct ivy-state
272 prompt collection
273 predicate require-match initial-input
274 history preselect keymap update-fn sort
275 ;; The window in which `ivy-read' was called
276 window
277 ;; The buffer in which `ivy-read' was called
278 buffer
279 ;; The value of `ivy-text' to be used by `ivy-occur'
280 text
281 action
282 unwind
283 re-builder
284 matcher
285 ;; When this is non-nil, call it for each input change to get new candidates
286 dynamic-collection
287 ;; A lambda that transforms candidates only for display
288 display-transformer-fn
289 caller)
290
291 (defvar ivy-last (make-ivy-state)
292 "The last parameters passed to `ivy-read'.
293
294 This should eventually become a stack so that you could use
295 `ivy-read' recursively.")
296
297 (defsubst ivy-set-action (action)
298 (setf (ivy-state-action ivy-last) action))
299
300 (defun ivy-thing-at-point ()
301 "Return a string that corresponds to the current thing at point."
302 (or
303 (thing-at-point 'url)
304 (let (s)
305 (cond ((stringp (setq s (thing-at-point 'symbol)))
306 (if (string-match "\\`[`']?\\(.*?\\)'?\\'" s)
307 (match-string 1 s)
308 s))
309 ((looking-at "(+\\(\\(?:\\sw\\|\\s_\\)+\\)\\_>")
310 (match-string-no-properties 1))
311 (t
312 "")))))
313
314 (defvar ivy-history nil
315 "History list of candidates entered in the minibuffer.
316
317 Maximum length of the history list is determined by the value
318 of `history-length'.")
319
320 (defvar ivy--directory nil
321 "Current directory when completing file names.")
322
323 (defvar ivy--length 0
324 "Store the amount of viable candidates.")
325
326 (defvar ivy-text ""
327 "Store the user's string as it is typed in.")
328
329 (defvar ivy--current ""
330 "Current candidate.")
331
332 (defvar ivy--index 0
333 "Store the index of the current candidate.")
334
335 (defvar ivy-exit nil
336 "Store 'done if the completion was successfully selected.
337 Otherwise, store nil.")
338
339 (defvar ivy--all-candidates nil
340 "Store the candidates passed to `ivy-read'.")
341
342 (defvar ivy--extra-candidates '((original-source))
343 "Store candidates added by the extra sources.
344
345 This is an internal-use alist. Each key is a function name, or
346 original-source (which represents where the current dynamic
347 candidates should go).
348
349 Each value is an evaluation of the function, in case of static
350 sources. These values will subsequently be filtered on `ivy-text'.
351
352 This variable is set by `ivy-read' and used by `ivy--set-candidates'.")
353
354 (defvar ivy-use-ignore t
355 "Store policy for user-configured candidate filtering.")
356
357 (defvar ivy--default nil
358 "Default initial input.")
359
360 (defvar ivy--prompt nil
361 "Store the format-style prompt.
362 When non-nil, it should contain at least one %d.")
363
364 (defvar ivy--prompt-extra ""
365 "Temporary modifications to the prompt.")
366
367 (defvar ivy--old-re nil
368 "Store the old regexp.")
369
370 (defvar ivy--old-cands nil
371 "Store the candidates matched by `ivy--old-re'.")
372
373 (defvar ivy--regex-function 'ivy--regex
374 "Current function for building a regex.")
375
376 (defvar ivy--subexps 0
377 "Number of groups in the current `ivy--regex'.")
378
379 (defvar ivy--full-length nil
380 "When :dynamic-collection is non-nil, this can be the total amount of candidates.")
381
382 (defvar ivy--old-text ""
383 "Store old `ivy-text' for dynamic completion.")
384
385 (defvar ivy-case-fold-search 'auto
386 "Store the current overriding `case-fold-search'.")
387
388 (defvar Info-current-file)
389
390 (defmacro ivy-quit-and-run (&rest body)
391 "Quit the minibuffer and run BODY afterwards."
392 `(progn
393 (put 'quit 'error-message "")
394 (run-at-time nil nil
395 (lambda ()
396 (put 'quit 'error-message "Quit")
397 ,@body))
398 (minibuffer-keyboard-quit)))
399
400 (defun ivy-exit-with-action (action)
401 "Quit the minibuffer and call ACTION afterwards."
402 (ivy-set-action
403 `(lambda (x)
404 (funcall ',action x)
405 (ivy-set-action ',(ivy-state-action ivy-last))))
406 (setq ivy-exit 'done)
407 (exit-minibuffer))
408
409 (defmacro with-ivy-window (&rest body)
410 "Execute BODY in the window from which `ivy-read' was called."
411 (declare (indent 0)
412 (debug t))
413 `(with-selected-window (ivy--get-window ivy-last)
414 ,@body))
415
416 (defun ivy--done (text)
417 "Insert TEXT and exit minibuffer."
418 (if (and ivy--directory
419 (not (eq (ivy-state-history ivy-last) 'grep-files-history)))
420 (insert (setq ivy--current (expand-file-name
421 text ivy--directory)))
422 (insert (setq ivy--current text)))
423 (setq ivy-exit 'done)
424 (exit-minibuffer))
425
426 ;;* Commands
427 (defun ivy-done ()
428 "Exit the minibuffer with the selected candidate."
429 (interactive)
430 (delete-minibuffer-contents)
431 (cond ((> ivy--length 0)
432 (ivy--done ivy--current))
433 ((memq (ivy-state-collection ivy-last)
434 '(read-file-name-internal internal-complete-buffer))
435 (if (or (not (eq confirm-nonexistent-file-or-buffer t))
436 (equal " (confirm)" ivy--prompt-extra))
437 (ivy--done ivy-text)
438 (setq ivy--prompt-extra " (confirm)")
439 (insert ivy-text)
440 (ivy--exhibit)))
441 ((memq (ivy-state-require-match ivy-last)
442 '(nil confirm confirm-after-completion))
443 (ivy--done ivy-text))
444 (t
445 (setq ivy--prompt-extra " (match required)")
446 (insert ivy-text)
447 (ivy--exhibit))))
448
449 (defun ivy-read-action ()
450 "Change the action to one of the available ones.
451
452 Return nil for `minibuffer-keyboard-quit' or wrong key during the
453 selection, non-nil otherwise."
454 (interactive)
455 (let ((actions (ivy-state-action ivy-last)))
456 (if (null (ivy--actionp actions))
457 t
458 (let* ((hint (concat (if (eq this-command 'ivy-read-action)
459 "Select action: "
460 ivy--current)
461 "\n"
462 (mapconcat
463 (lambda (x)
464 (format "%s: %s"
465 (propertize
466 (car x)
467 'face 'font-lock-builtin-face)
468 (nth 2 x)))
469 (cdr actions)
470 "\n")
471 "\n"))
472 (resize-mini-windows 'grow-only)
473 (key (string (read-key hint)))
474 (action-idx (cl-position-if
475 (lambda (x) (equal (car x) key))
476 (cdr actions))))
477 (cond ((string= key "\a")
478 nil)
479 ((null action-idx)
480 (message "%s is not bound" key)
481 nil)
482 (t
483 (message "")
484 (setcar actions (1+ action-idx))
485 (ivy-set-action actions)))))))
486
487 (defun ivy-dispatching-done ()
488 "Select one of the available actions and call `ivy-done'."
489 (interactive)
490 (when (ivy-read-action)
491 (ivy-done)))
492
493 (defun ivy-dispatching-call ()
494 "Select one of the available actions and call `ivy-call'."
495 (interactive)
496 (let ((actions (copy-sequence (ivy-state-action ivy-last))))
497 (unwind-protect
498 (when (ivy-read-action)
499 (ivy-call))
500 (ivy-set-action actions))))
501
502 (defun ivy-build-tramp-name (x)
503 "Reconstruct X into a path.
504 Is is a cons cell, related to `tramp-get-completion-function'."
505 (let ((user (car x))
506 (domain (cadr x)))
507 (if user
508 (concat user "@" domain)
509 domain)))
510
511 (declare-function tramp-get-completion-function "tramp")
512 (declare-function Info-find-node "info")
513
514 (defun ivy-alt-done (&optional arg)
515 "Exit the minibuffer with the selected candidate.
516 When ARG is t, exit with current text, ignoring the candidates."
517 (interactive "P")
518 (cond (arg
519 (ivy-immediate-done))
520 (ivy--directory
521 (ivy--directory-done))
522 ((eq (ivy-state-collection ivy-last) 'Info-read-node-name-1)
523 (if (member ivy--current '("(./)" "(../)"))
524 (ivy-quit-and-run
525 (ivy-read "Go to file: " 'read-file-name-internal
526 :action (lambda (x)
527 (Info-find-node
528 (expand-file-name x ivy--directory)
529 "Top"))))
530 (ivy-done)))
531 (t
532 (ivy-done))))
533
534 (defun ivy--directory-done ()
535 "Handle exit from the minibuffer when completing file names."
536 (let (dir)
537 (cond
538 ((equal ivy-text "/sudo::")
539 (setq dir (concat ivy-text ivy--directory))
540 (ivy--cd dir)
541 (ivy--exhibit))
542 ((or
543 (and
544 (not (string= ivy-text ""))
545 (setq dir (ivy-expand-file-if-directory ivy-text)))
546 (and
547 (> ivy--length 0)
548 (not (string= ivy--current "./"))
549 (setq dir (ivy-expand-file-if-directory ivy--current))))
550 (ivy--cd dir)
551 (ivy--exhibit))
552 ((or (and (equal ivy--directory "/")
553 (string-match "\\`[^/]+:.*:.*\\'" ivy-text))
554 (string-match "\\`/[^/]+:.*:.*\\'" ivy-text))
555 (ivy-done))
556 ((or (and (equal ivy--directory "/")
557 (cond ((string-match
558 "\\`\\([^/]+?\\):\\(?:\\(.*\\)@\\)?\\(.*\\)\\'"
559 ivy-text))
560 ((string-match
561 "\\`\\([^/]+?\\):\\(?:\\(.*\\)@\\)?\\(.*\\)\\'"
562 ivy--current)
563 (setq ivy-text ivy--current))))
564 (string-match
565 "\\`/\\([^/]+?\\):\\(?:\\(.*\\)@\\)?\\(.*\\)\\'"
566 ivy-text))
567 (let ((method (match-string 1 ivy-text))
568 (user (match-string 2 ivy-text))
569 (rest (match-string 3 ivy-text))
570 res)
571 (require 'tramp)
572 (dolist (x (tramp-get-completion-function method))
573 (setq res (append res (funcall (car x) (cadr x)))))
574 (setq res (delq nil res))
575 (when user
576 (dolist (x res)
577 (setcar x user)))
578 (setq res (cl-delete-duplicates res :test #'equal))
579 (let* ((old-ivy-last ivy-last)
580 (enable-recursive-minibuffers t)
581 (host (ivy-read "user@host: "
582 (mapcar #'ivy-build-tramp-name res)
583 :initial-input rest)))
584 (setq ivy-last old-ivy-last)
585 (when host
586 (setq ivy--directory "/")
587 (ivy--cd (concat "/" method ":" host ":"))))))
588 (t
589 (ivy-done)))))
590
591 (defun ivy-expand-file-if-directory (file-name)
592 "Expand FILE-NAME as directory.
593 When this directory doesn't exist, return nil."
594 (when (stringp file-name)
595 (let ((full-name
596 (file-name-as-directory
597 (expand-file-name file-name ivy--directory))))
598 (when (file-directory-p full-name)
599 full-name))))
600
601 (defcustom ivy-tab-space nil
602 "When non-nil, `ivy-partial-or-done' should insert a space."
603 :type 'boolean)
604
605 (defun ivy-partial-or-done ()
606 "Complete the minibuffer text as much as possible.
607 If the text hasn't changed as a result, forward to `ivy-alt-done'."
608 (interactive)
609 (if (and (eq (ivy-state-collection ivy-last) #'read-file-name-internal)
610 (or (and (equal ivy--directory "/")
611 (string-match "\\`[^/]+:.*\\'" ivy-text))
612 (string-match "\\`/" ivy-text)))
613 (let ((default-directory ivy--directory)
614 dir)
615 (minibuffer-complete)
616 (setq ivy-text (ivy--input))
617 (when (setq dir (ivy-expand-file-if-directory ivy-text))
618 (ivy--cd dir)))
619 (or (ivy-partial)
620 (when (or (eq this-command last-command)
621 (eq ivy--length 1))
622 (ivy-alt-done)))))
623
624 (defun ivy-partial ()
625 "Complete the minibuffer text as much as possible."
626 (interactive)
627 (let* ((parts (or (split-string ivy-text " " t) (list "")))
628 (postfix (car (last parts)))
629 (completion-ignore-case t)
630 (startp (string-match "^\\^" postfix))
631 (new (try-completion (if startp
632 (substring postfix 1)
633 postfix)
634 (mapcar (lambda (str)
635 (let ((i (string-match postfix str)))
636 (when i
637 (substring str i))))
638 ivy--old-cands))))
639 (cond ((eq new t) nil)
640 ((string= new ivy-text) nil)
641 (new
642 (delete-region (minibuffer-prompt-end) (point-max))
643 (setcar (last parts)
644 (if startp
645 (concat "^" new)
646 new))
647 (insert (mapconcat #'identity parts " ")
648 (if ivy-tab-space " " ""))
649 t))))
650
651 (defun ivy-immediate-done ()
652 "Exit the minibuffer with the current input."
653 (interactive)
654 (delete-minibuffer-contents)
655 (insert (setq ivy--current
656 (if ivy--directory
657 (expand-file-name ivy-text ivy--directory)
658 ivy-text)))
659 (setq ivy-exit 'done)
660 (exit-minibuffer))
661
662 ;;;###autoload
663 (defun ivy-resume ()
664 "Resume the last completion session."
665 (interactive)
666 (if (null (ivy-state-action ivy-last))
667 (user-error "The last session isn't compatible with `ivy-resume'")
668 (when (eq (ivy-state-caller ivy-last) 'swiper)
669 (switch-to-buffer (ivy-state-buffer ivy-last)))
670 (with-current-buffer (ivy-state-buffer ivy-last)
671 (ivy-read
672 (ivy-state-prompt ivy-last)
673 (ivy-state-collection ivy-last)
674 :predicate (ivy-state-predicate ivy-last)
675 :require-match (ivy-state-require-match ivy-last)
676 :initial-input ivy-text
677 :history (ivy-state-history ivy-last)
678 :preselect (unless (eq (ivy-state-collection ivy-last)
679 'read-file-name-internal)
680 ivy--current)
681 :keymap (ivy-state-keymap ivy-last)
682 :update-fn (ivy-state-update-fn ivy-last)
683 :sort (ivy-state-sort ivy-last)
684 :action (ivy-state-action ivy-last)
685 :unwind (ivy-state-unwind ivy-last)
686 :re-builder (ivy-state-re-builder ivy-last)
687 :matcher (ivy-state-matcher ivy-last)
688 :dynamic-collection (ivy-state-dynamic-collection ivy-last)
689 :caller (ivy-state-caller ivy-last)))))
690
691 (defvar-local ivy-calling nil
692 "When non-nil, call the current action when `ivy--index' changes.")
693
694 (defun ivy-set-index (index)
695 "Set `ivy--index' to INDEX."
696 (setq ivy--index index)
697 (when ivy-calling
698 (ivy--exhibit)
699 (ivy-call)))
700
701 (defun ivy-beginning-of-buffer ()
702 "Select the first completion candidate."
703 (interactive)
704 (ivy-set-index 0))
705
706 (defun ivy-end-of-buffer ()
707 "Select the last completion candidate."
708 (interactive)
709 (ivy-set-index (1- ivy--length)))
710
711 (defun ivy-scroll-up-command ()
712 "Scroll the candidates upward by the minibuffer height."
713 (interactive)
714 (ivy-set-index (min (1- (+ ivy--index ivy-height))
715 (1- ivy--length))))
716
717 (defun ivy-scroll-down-command ()
718 "Scroll the candidates downward by the minibuffer height."
719 (interactive)
720 (ivy-set-index (max (1+ (- ivy--index ivy-height))
721 0)))
722
723 (defun ivy-minibuffer-grow ()
724 "Grow the minibuffer window by 1 line."
725 (interactive)
726 (setq-local max-mini-window-height
727 (cl-incf ivy-height)))
728
729 (defun ivy-minibuffer-shrink ()
730 "Shrink the minibuffer window by 1 line."
731 (interactive)
732 (unless (<= ivy-height 2)
733 (setq-local max-mini-window-height
734 (cl-decf ivy-height))
735 (window-resize (selected-window) -1)))
736
737 (defun ivy-next-line (&optional arg)
738 "Move cursor vertically down ARG candidates."
739 (interactive "p")
740 (setq arg (or arg 1))
741 (let ((index (+ ivy--index arg)))
742 (if (> index (1- ivy--length))
743 (if ivy-wrap
744 (ivy-beginning-of-buffer)
745 (ivy-set-index (1- ivy--length)))
746 (ivy-set-index index))))
747
748 (defun ivy-next-line-or-history (&optional arg)
749 "Move cursor vertically down ARG candidates.
750 If the input is empty, select the previous history element instead."
751 (interactive "p")
752 (if (string= ivy-text "")
753 (ivy-previous-history-element 1)
754 (ivy-next-line arg)))
755
756 (defun ivy-previous-line (&optional arg)
757 "Move cursor vertically up ARG candidates."
758 (interactive "p")
759 (setq arg (or arg 1))
760 (let ((index (- ivy--index arg)))
761 (if (< index 0)
762 (if ivy-wrap
763 (ivy-end-of-buffer)
764 (ivy-set-index 0))
765 (ivy-set-index index))))
766
767 (defun ivy-previous-line-or-history (arg)
768 "Move cursor vertically up ARG candidates.
769 If the input is empty, select the previous history element instead."
770 (interactive "p")
771 (when (string= ivy-text "")
772 (ivy-previous-history-element 1))
773 (ivy-previous-line arg))
774
775 (defun ivy-toggle-calling ()
776 "Flip `ivy-calling'."
777 (interactive)
778 (when (setq ivy-calling (not ivy-calling))
779 (ivy-call)))
780
781 (defun ivy-toggle-ignore ()
782 "Toggle user-configured candidate filtering."
783 (interactive)
784 (setq ivy-use-ignore (null ivy-use-ignore))
785 ;; invalidate cache
786 (setq ivy--old-cands nil))
787
788 (defun ivy--get-action (state)
789 "Get the action function from STATE."
790 (let ((action (ivy-state-action state)))
791 (when action
792 (if (functionp action)
793 action
794 (cadr (nth (car action) action))))))
795
796 (defun ivy--get-window (state)
797 "Get the window from STATE."
798 (if (ivy-state-p state)
799 (let ((window (ivy-state-window state)))
800 (if (window-live-p window)
801 window
802 (if (= (length (window-list)) 1)
803 (selected-window)
804 (next-window))))
805 (selected-window)))
806
807 (defun ivy--actionp (x)
808 "Return non-nil when X is a list of actions."
809 (and x (listp x) (not (eq (car x) 'closure))))
810
811 (defun ivy-next-action ()
812 "When the current action is a list, scroll it forwards."
813 (interactive)
814 (let ((action (ivy-state-action ivy-last)))
815 (when (ivy--actionp action)
816 (unless (>= (car action) (1- (length action)))
817 (cl-incf (car action))))))
818
819 (defun ivy-prev-action ()
820 "When the current action is a list, scroll it backwards."
821 (interactive)
822 (let ((action (ivy-state-action ivy-last)))
823 (when (ivy--actionp action)
824 (unless (<= (car action) 1)
825 (cl-decf (car action))))))
826
827 (defun ivy-action-name ()
828 "Return the name associated with the current action."
829 (let ((action (ivy-state-action ivy-last)))
830 (if (ivy--actionp action)
831 (format "[%d/%d] %s"
832 (car action)
833 (1- (length action))
834 (nth 2 (nth (car action) action)))
835 "[1/1] default")))
836
837 (defvar ivy-inhibit-action nil
838 "When non-nil, `ivy-call' does nothing.
839
840 Example use:
841
842 (let* ((ivy-inhibit-action t)
843 (str (counsel-locate \"lispy.el\")))
844 ;; do whatever with str - the corresponding file will not be opened
845 )")
846
847 (defun ivy-call ()
848 "Call the current action without exiting completion."
849 (interactive)
850 (unless ivy-inhibit-action
851 (let ((action (ivy--get-action ivy-last)))
852 (when action
853 (let* ((collection (ivy-state-collection ivy-last))
854 (x (if (and (consp collection)
855 (consp (car collection)))
856 (cdr (assoc ivy--current collection))
857 (if (equal ivy--current "")
858 ivy-text
859 ivy--current))))
860 (prog1 (funcall action x)
861 (unless (or (eq ivy-exit 'done)
862 (equal (selected-window)
863 (active-minibuffer-window))
864 (null (active-minibuffer-window)))
865 (select-window (active-minibuffer-window)))))))))
866
867 (defun ivy-next-line-and-call (&optional arg)
868 "Move cursor vertically down ARG candidates.
869 Call the permanent action if possible."
870 (interactive "p")
871 (ivy-next-line arg)
872 (ivy--exhibit)
873 (ivy-call))
874
875 (defun ivy-previous-line-and-call (&optional arg)
876 "Move cursor vertically down ARG candidates.
877 Call the permanent action if possible."
878 (interactive "p")
879 (ivy-previous-line arg)
880 (ivy--exhibit)
881 (ivy-call))
882
883 (defun ivy-previous-history-element (arg)
884 "Forward to `previous-history-element' with ARG."
885 (interactive "p")
886 (previous-history-element arg)
887 (ivy--cd-maybe)
888 (move-end-of-line 1)
889 (ivy--maybe-scroll-history))
890
891 (defun ivy-next-history-element (arg)
892 "Forward to `next-history-element' with ARG."
893 (interactive "p")
894 (if (and (= minibuffer-history-position 0)
895 (equal ivy-text ""))
896 (progn
897 (insert ivy--default)
898 (when (and (with-ivy-window (derived-mode-p 'prog-mode))
899 (not (file-exists-p ivy--default))
900 (not (ivy-state-dynamic-collection ivy-last))
901 (> (point) (minibuffer-prompt-end)))
902 (undo-boundary)
903 (insert "\\_>")
904 (goto-char (minibuffer-prompt-end))
905 (insert "\\_<")
906 (forward-char (+ 2 (length ivy--default)))))
907 (next-history-element arg))
908 (ivy--cd-maybe)
909 (move-end-of-line 1)
910 (ivy--maybe-scroll-history))
911
912 (defvar ivy-ffap-url-functions nil
913 "List of functions that check if the point is on a URL.")
914
915 (defun ivy--cd-maybe ()
916 "Check if the current input points to a different directory.
917 If so, move to that directory, while keeping only the file name."
918 (when ivy--directory
919 (let ((input (ivy--input))
920 url)
921 (if (setq url (or (ffap-url-p input)
922 (with-ivy-window
923 (cl-reduce
924 (lambda (a b)
925 (or a (funcall b)))
926 ivy-ffap-url-functions
927 :initial-value nil))))
928 (ivy-exit-with-action
929 (lambda (_)
930 (funcall ffap-url-fetcher url)))
931 (setq input (expand-file-name input))
932 (let ((file (file-name-nondirectory input))
933 (dir (expand-file-name (file-name-directory input))))
934 (if (string= dir ivy--directory)
935 (progn
936 (delete-minibuffer-contents)
937 (insert file))
938 (ivy--cd dir)
939 (insert file)))))))
940
941 (defun ivy--maybe-scroll-history ()
942 "If the selected history element has an index, scroll there."
943 (let ((idx (ignore-errors
944 (get-text-property
945 (minibuffer-prompt-end)
946 'ivy-index))))
947 (when idx
948 (ivy--exhibit)
949 (setq ivy--index idx))))
950
951 (defun ivy--cd (dir)
952 "When completing file names, move to directory DIR."
953 (if (null ivy--directory)
954 (error "Unexpected")
955 (setq ivy--old-cands nil)
956 (setq ivy--old-re nil)
957 (setq ivy--index 0)
958 (setq ivy--all-candidates
959 (ivy--sorted-files (setq ivy--directory dir)))
960 (setq ivy-text "")
961 (delete-minibuffer-contents)))
962
963 (defun ivy-backward-delete-char ()
964 "Forward to `backward-delete-char'.
965 On error (read-only), call `ivy-on-del-error-function'."
966 (interactive)
967 (if (and ivy--directory (= (minibuffer-prompt-end) (point)))
968 (progn
969 (ivy--cd (file-name-directory
970 (directory-file-name
971 (expand-file-name
972 ivy--directory))))
973 (ivy--exhibit))
974 (condition-case nil
975 (backward-delete-char 1)
976 (error
977 (when ivy-on-del-error-function
978 (funcall ivy-on-del-error-function))))))
979
980 (defun ivy-delete-char (arg)
981 "Forward to `delete-char' ARG."
982 (interactive "p")
983 (unless (= (point) (line-end-position))
984 (delete-char arg)))
985
986 (defun ivy-forward-char (arg)
987 "Forward to `forward-char' ARG."
988 (interactive "p")
989 (unless (= (point) (line-end-position))
990 (forward-char arg)))
991
992 (defun ivy-kill-word (arg)
993 "Forward to `kill-word' ARG."
994 (interactive "p")
995 (unless (= (point) (line-end-position))
996 (kill-word arg)))
997
998 (defun ivy-kill-line ()
999 "Forward to `kill-line'."
1000 (interactive)
1001 (if (eolp)
1002 (kill-region (minibuffer-prompt-end) (point))
1003 (kill-line)))
1004
1005 (defun ivy-backward-kill-word ()
1006 "Forward to `backward-kill-word'."
1007 (interactive)
1008 (if (and ivy--directory (= (minibuffer-prompt-end) (point)))
1009 (progn
1010 (ivy--cd (file-name-directory
1011 (directory-file-name
1012 (expand-file-name
1013 ivy--directory))))
1014 (ivy--exhibit))
1015 (ignore-errors
1016 (let ((pt (point)))
1017 (forward-word -1)
1018 (delete-region (point) pt)))))
1019
1020 (defvar ivy--regexp-quote 'regexp-quote
1021 "Store the regexp quoting state.")
1022
1023 (defun ivy-toggle-regexp-quote ()
1024 "Toggle the regexp quoting."
1025 (interactive)
1026 (setq ivy--old-re nil)
1027 (cl-rotatef ivy--regex-function ivy--regexp-quote))
1028
1029 (defvar avy-all-windows)
1030 (defvar avy-action)
1031 (defvar avy-keys)
1032 (defvar avy-keys-alist)
1033 (defvar avy-style)
1034 (defvar avy-styles-alist)
1035 (declare-function avy--process "ext:avy")
1036 (declare-function avy--style-fn "ext:avy")
1037
1038 (eval-after-load 'avy
1039 '(add-to-list 'avy-styles-alist '(ivy-avy . pre)))
1040
1041 (defun ivy-avy ()
1042 "Jump to one of the current ivy candidates."
1043 (interactive)
1044 (unless (require 'avy nil 'noerror)
1045 (error "Package avy isn't installed"))
1046 (let* ((avy-all-windows nil)
1047 (avy-keys (or (cdr (assq 'ivy-avy avy-keys-alist))
1048 avy-keys))
1049 (avy-style (or (cdr (assq 'ivy-avy
1050 avy-styles-alist))
1051 avy-style))
1052 (candidate
1053 (let ((candidates))
1054 (save-excursion
1055 (save-restriction
1056 (narrow-to-region
1057 (window-start)
1058 (window-end))
1059 (goto-char (point-min))
1060 (forward-line)
1061 (while (< (point) (point-max))
1062 (push
1063 (cons (point)
1064 (selected-window))
1065 candidates)
1066 (forward-line))))
1067 (setq avy-action #'identity)
1068 (avy--process
1069 (nreverse candidates)
1070 (avy--style-fn avy-style)))))
1071 (ivy-set-index (- (line-number-at-pos candidate) 2))
1072 (ivy--exhibit)
1073 (ivy-done)))
1074
1075 (defun ivy-sort-file-function-default (x y)
1076 "Compare two files X and Y.
1077 Prioritize directories."
1078 (if (get-text-property 0 'dirp x)
1079 (if (get-text-property 0 'dirp y)
1080 (string< x y)
1081 t)
1082 (if (get-text-property 0 'dirp y)
1083 nil
1084 (string< x y))))
1085
1086 (defcustom ivy-sort-functions-alist
1087 '((read-file-name-internal . ivy-sort-file-function-default)
1088 (internal-complete-buffer . nil)
1089 (counsel-git-grep-function . nil)
1090 (Man-goto-section . nil)
1091 (org-refile . nil)
1092 (t . string-lessp))
1093 "An alist of sorting functions for each collection function.
1094 Interactive functions that call completion fit in here as well.
1095
1096 Nil means no sorting, which is useful to turn off the sorting for
1097 functions that have candidates in the natural buffer order, like
1098 `org-refile' or `Man-goto-section'.
1099
1100 The entry associated with t is used for all fall-through cases.
1101
1102 See also `ivy-sort-max-size'."
1103 :type
1104 '(alist
1105 :key-type (choice
1106 (const :tag "Fall-through" t)
1107 (symbol :tag "Collection"))
1108 :value-type (choice
1109 (const :tag "Plain sort" string-lessp)
1110 (const :tag "File sort" ivy-sort-file-function-default)
1111 (const :tag "No sort" nil)))
1112 :group 'ivy)
1113
1114 (defvar ivy-index-functions-alist
1115 '((swiper . ivy-recompute-index-swiper)
1116 (swiper-multi . ivy-recompute-index-swiper)
1117 (counsel-git-grep . ivy-recompute-index-swiper)
1118 (counsel-grep . ivy-recompute-index-swiper-async)
1119 (t . ivy-recompute-index-zero))
1120 "An alist of index recomputing functions for each collection function.
1121 When the input changes, the appropriate function returns an
1122 integer - the index of the matched candidate that should be
1123 selected.")
1124
1125 (defvar ivy-re-builders-alist
1126 '((t . ivy--regex-plus))
1127 "An alist of regex building functions for each collection function.
1128
1129 Each key is (in order of priority):
1130 1. The actual collection function, e.g. `read-file-name-internal'.
1131 2. The symbol passed by :caller into `ivy-read'.
1132 3. `this-command'.
1133 4. t.
1134
1135 Each value is a function that should take a string and return a
1136 valid regex or a regex sequence (see below).
1137
1138 Possible choices: `ivy--regex', `regexp-quote',
1139 `ivy--regex-plus', `ivy--regex-fuzzy'.
1140
1141 If a function returns a list, it should format like this:
1142 '((\"matching-regexp\" . t) (\"non-matching-regexp\") ...).
1143
1144 The matches will be filtered in a sequence, you can mix the
1145 regexps that should match and that should not match as you
1146 like.")
1147
1148 (defvar ivy-initial-inputs-alist
1149 '((org-refile . "^")
1150 (org-agenda-refile . "^")
1151 (org-capture-refile . "^")
1152 (counsel-M-x . "^")
1153 (counsel-describe-function . "^")
1154 (counsel-describe-variable . "^")
1155 (man . "^")
1156 (woman . "^"))
1157 "Command to initial input table.")
1158
1159 (defcustom ivy-sort-max-size 30000
1160 "Sorting won't be done for collections larger than this."
1161 :type 'integer)
1162
1163 (defun ivy--sorted-files (dir)
1164 "Return the list of files in DIR.
1165 Directories come first."
1166 (let* ((default-directory dir)
1167 (seq (all-completions "" 'read-file-name-internal))
1168 sort-fn)
1169 (if (equal dir "/")
1170 seq
1171 (setq seq (delete "./" (delete "../" seq)))
1172 (when (eq (setq sort-fn (cdr (assoc 'read-file-name-internal
1173 ivy-sort-functions-alist)))
1174 #'ivy-sort-file-function-default)
1175 (setq seq (mapcar (lambda (x)
1176 (propertize x 'dirp (string-match-p "/\\'" x)))
1177 seq)))
1178 (when sort-fn
1179 (setq seq (cl-sort seq sort-fn)))
1180 (dolist (dir ivy-extra-directories)
1181 (push dir seq))
1182 seq)))
1183
1184 (defvar ivy-recursive-restore t
1185 "When non-nil, restore the above state when exiting the minibuffer.
1186 This variable is let-bound to nil by functions that take care of
1187 the restoring themselves.")
1188
1189 ;;** Entry Point
1190 (cl-defun ivy-read (prompt collection
1191 &key
1192 predicate require-match initial-input
1193 history preselect keymap update-fn sort
1194 action unwind re-builder matcher dynamic-collection caller)
1195 "Read a string in the minibuffer, with completion.
1196
1197 PROMPT is a format string, normally ending in a colon and a
1198 space; %d anywhere in the string is replaced by the current
1199 number of matching candidates. For the literal % character,
1200 escape it with %%. See also `ivy-count-format'.
1201
1202 COLLECTION is either a list of strings, a function, an alist, or
1203 a hash table.
1204
1205 If INITIAL-INPUT is not nil, then insert that input in the
1206 minibuffer initially.
1207
1208 KEYMAP is composed with `ivy-minibuffer-map'.
1209
1210 If PRESELECT is not nil, then select the corresponding candidate
1211 out of the ones that match the INITIAL-INPUT.
1212
1213 UPDATE-FN is called each time the current candidate(s) is changed.
1214
1215 When SORT is t, use `ivy-sort-functions-alist' for sorting.
1216
1217 ACTION is a lambda function to call after selecting a result. It
1218 takes a single string argument.
1219
1220 UNWIND is a lambda function to call before exiting.
1221
1222 RE-BUILDER is a lambda function to call to transform text into a
1223 regex pattern.
1224
1225 MATCHER is to override matching.
1226
1227 DYNAMIC-COLLECTION is a boolean to specify if the list of
1228 candidates is updated after each input by calling COLLECTION.
1229
1230 CALLER is a symbol to uniquely identify the caller to `ivy-read'.
1231 It is used, along with COLLECTION, to determine which
1232 customizations apply to the current completion session."
1233 (let ((extra-actions (delete-dups
1234 (append (plist-get ivy--actions-list t)
1235 (plist-get ivy--actions-list this-command)
1236 (plist-get ivy--actions-list caller)))))
1237 (when extra-actions
1238 (setq action
1239 (cond ((functionp action)
1240 `(1
1241 ("o" ,action "default")
1242 ,@extra-actions))
1243 ((null action)
1244 `(1
1245 ("o" identity "default")
1246 ,@extra-actions))
1247 (t
1248 (delete-dups (append action extra-actions)))))))
1249 (let ((extra-sources (plist-get ivy--sources-list caller)))
1250 (if extra-sources
1251 (progn
1252 (setq ivy--extra-candidates nil)
1253 (dolist (source extra-sources)
1254 (cond ((equal source '(original-source))
1255 (setq ivy--extra-candidates
1256 (cons source ivy--extra-candidates)))
1257 ((null (cdr source))
1258 (setq ivy--extra-candidates
1259 (cons
1260 (list (car source) (funcall (car source)))
1261 ivy--extra-candidates))))))
1262 (setq ivy--extra-candidates '((original-source)))))
1263 (let ((recursive-ivy-last (and (active-minibuffer-window) ivy-last))
1264 (transformer-fn
1265 (plist-get ivy--display-transformers-list
1266 (or caller (and (functionp collection)
1267 collection)))))
1268 (setq ivy-last
1269 (make-ivy-state
1270 :prompt prompt
1271 :collection collection
1272 :predicate predicate
1273 :require-match require-match
1274 :initial-input initial-input
1275 :history history
1276 :preselect preselect
1277 :keymap keymap
1278 :update-fn update-fn
1279 :sort sort
1280 :action action
1281 :window (selected-window)
1282 :buffer (current-buffer)
1283 :unwind unwind
1284 :re-builder re-builder
1285 :matcher matcher
1286 :dynamic-collection dynamic-collection
1287 :display-transformer-fn transformer-fn
1288 :caller caller))
1289 (ivy--reset-state ivy-last)
1290 (prog1
1291 (unwind-protect
1292 (minibuffer-with-setup-hook
1293 #'ivy--minibuffer-setup
1294 (let* ((hist (or history 'ivy-history))
1295 (minibuffer-completion-table collection)
1296 (minibuffer-completion-predicate predicate)
1297 (resize-mini-windows (cond
1298 ((display-graphic-p) nil)
1299 ((null resize-mini-windows) 'grow-only)
1300 (t resize-mini-windows))))
1301 (read-from-minibuffer
1302 prompt
1303 (ivy-state-initial-input ivy-last)
1304 (make-composed-keymap keymap ivy-minibuffer-map)
1305 nil
1306 hist)
1307 (when (eq ivy-exit 'done)
1308 (let ((item (if ivy--directory
1309 ivy--current
1310 ivy-text)))
1311 (unless (equal item "")
1312 (set hist (cons (propertize item 'ivy-index ivy--index)
1313 (delete item
1314 (cdr (symbol-value hist))))))))
1315 ivy--current))
1316 (remove-hook 'post-command-hook #'ivy--exhibit)
1317 (when (setq unwind (ivy-state-unwind ivy-last))
1318 (funcall unwind))
1319 (unless (eq ivy-exit 'done)
1320 (when recursive-ivy-last
1321 (ivy--reset-state (setq ivy-last recursive-ivy-last)))))
1322 (ivy-call)
1323 (when (numberp (car-safe (ivy-state-action ivy-last)))
1324 (setcar (ivy-state-action ivy-last) 1))
1325 (when (and recursive-ivy-last
1326 ivy-recursive-restore)
1327 (ivy--reset-state (setq ivy-last recursive-ivy-last))))))
1328
1329 (defun ivy--reset-state (state)
1330 "Reset the ivy to STATE.
1331 This is useful for recursive `ivy-read'."
1332 (let ((prompt (or (ivy-state-prompt state) ""))
1333 (collection (ivy-state-collection state))
1334 (predicate (ivy-state-predicate state))
1335 (history (ivy-state-history state))
1336 (preselect (ivy-state-preselect state))
1337 (sort (ivy-state-sort state))
1338 (re-builder (ivy-state-re-builder state))
1339 (dynamic-collection (ivy-state-dynamic-collection state))
1340 (initial-input (ivy-state-initial-input state))
1341 (require-match (ivy-state-require-match state))
1342 (caller (ivy-state-caller state)))
1343 (unless initial-input
1344 (setq initial-input (cdr (assoc this-command
1345 ivy-initial-inputs-alist))))
1346 (setq ivy--directory nil)
1347 (setq ivy-case-fold-search 'auto)
1348 (setq ivy--regex-function
1349 (or re-builder
1350 (and (functionp collection)
1351 (cdr (assoc collection ivy-re-builders-alist)))
1352 (and caller
1353 (cdr (assoc caller ivy-re-builders-alist)))
1354 (cdr (assoc this-command ivy-re-builders-alist))
1355 (cdr (assoc t ivy-re-builders-alist))
1356 'ivy--regex))
1357 (setq ivy--subexps 0)
1358 (setq ivy--regexp-quote 'regexp-quote)
1359 (setq ivy--old-text "")
1360 (setq ivy--full-length nil)
1361 (setq ivy-text "")
1362 (setq ivy-calling nil)
1363 (setq ivy-use-ignore t)
1364 (let (coll sort-fn)
1365 (cond ((eq collection 'Info-read-node-name-1)
1366 (if (equal Info-current-file "dir")
1367 (setq coll
1368 (mapcar (lambda (x) (format "(%s)" x))
1369 (cl-delete-duplicates
1370 (all-completions "(" collection predicate)
1371 :test #'equal)))
1372 (setq coll (all-completions "" collection predicate))))
1373 ((eq collection 'read-file-name-internal)
1374 (setq ivy--directory default-directory)
1375 (require 'dired)
1376 (when preselect
1377 (let ((preselect-directory (file-name-directory preselect)))
1378 (unless (or (null preselect-directory)
1379 (string= preselect-directory
1380 default-directory))
1381 (setq ivy--directory preselect-directory))
1382 (setf
1383 (ivy-state-preselect state)
1384 (setq preselect (file-name-nondirectory preselect)))))
1385 (setq coll (ivy--sorted-files ivy--directory))
1386 (when initial-input
1387 (unless (or require-match
1388 (equal initial-input default-directory)
1389 (equal initial-input ""))
1390 (setq coll (cons initial-input coll)))
1391 (unless (and (ivy-state-action ivy-last)
1392 (not (equal (ivy--get-action ivy-last) 'identity)))
1393 (setq initial-input nil))))
1394 ((eq collection 'internal-complete-buffer)
1395 (setq coll (ivy--buffer-list "" ivy-use-virtual-buffers)))
1396 (dynamic-collection
1397 (setq coll (funcall collection ivy-text)))
1398 ((or (functionp collection)
1399 (byte-code-function-p collection)
1400 (vectorp collection)
1401 (and (consp collection) (listp (car collection)))
1402 (hash-table-p collection)
1403 (and (listp collection) (symbolp (car collection))))
1404 (setq coll (all-completions "" collection predicate)))
1405 (t
1406 (setq coll collection)))
1407 (when sort
1408 (if (and (functionp collection)
1409 (setq sort-fn (assoc collection ivy-sort-functions-alist)))
1410 (when (and (setq sort-fn (cdr sort-fn))
1411 (not (eq collection 'read-file-name-internal)))
1412 (setq coll (cl-sort coll sort-fn)))
1413 (unless (eq history 'org-refile-history)
1414 (if (and (setq sort-fn (cdr (assoc t ivy-sort-functions-alist)))
1415 (<= (length coll) ivy-sort-max-size))
1416 (setq coll (cl-sort (copy-sequence coll) sort-fn))))))
1417 (when preselect
1418 (unless (or (and require-match
1419 (not (eq collection 'internal-complete-buffer)))
1420 dynamic-collection
1421 (let ((re (regexp-quote preselect)))
1422 (cl-find-if (lambda (x) (string-match re x))
1423 coll)))
1424 (setq coll (cons preselect coll))))
1425 (setq ivy--old-re nil)
1426 (setq ivy--old-cands nil)
1427 (when (integerp preselect)
1428 (setq ivy--old-re "")
1429 (setq ivy--index preselect))
1430 (when initial-input
1431 ;; Needed for anchor to work
1432 (setq ivy--old-cands coll)
1433 (setq ivy--old-cands (ivy--filter initial-input coll)))
1434 (setq ivy--all-candidates coll)
1435 (unless (integerp preselect)
1436 (setq ivy--index (or
1437 (and dynamic-collection
1438 ivy--index)
1439 (and preselect
1440 (ivy--preselect-index
1441 preselect
1442 (if initial-input
1443 ivy--old-cands
1444 coll)))
1445 0))))
1446 (setq ivy-exit nil)
1447 (setq ivy--default
1448 (if (region-active-p)
1449 (buffer-substring
1450 (region-beginning)
1451 (region-end))
1452 (ivy-thing-at-point)))
1453 (setq ivy--prompt
1454 (cond ((string-match "%.*d" prompt)
1455 prompt)
1456 ((null ivy-count-format)
1457 (error
1458 "`ivy-count-format' can't be nil. Set it to an empty string instead"))
1459 ((string-match "%d.*%d" ivy-count-format)
1460 (let ((w (length (number-to-string
1461 (length ivy--all-candidates))))
1462 (s (copy-sequence ivy-count-format)))
1463 (string-match "%d" s)
1464 (match-end 0)
1465 (string-match "%d" s (match-end 0))
1466 (setq s (replace-match (format "%%-%dd" w) nil nil s))
1467 (string-match "%d" s)
1468 (concat (replace-match (format "%%%dd" w) nil nil s)
1469 prompt)))
1470 ((string-match "%.*d" ivy-count-format)
1471 (concat ivy-count-format prompt))
1472 (ivy--directory
1473 prompt)
1474 (t
1475 nil)))
1476 (setf (ivy-state-initial-input ivy-last) initial-input)))
1477
1478 ;;;###autoload
1479 (defun ivy-completing-read (prompt collection
1480 &optional predicate require-match initial-input
1481 history def inherit-input-method)
1482 "Read a string in the minibuffer, with completion.
1483
1484 This interface conforms to `completing-read' and can be used for
1485 `completing-read-function'.
1486
1487 PROMPT is a string that normally ends in a colon and a space.
1488 COLLECTION is either a list of strings, an alist, an obarray, or a hash table.
1489 PREDICATE limits completion to a subset of COLLECTION.
1490 REQUIRE-MATCH is a boolean value. See `completing-read'.
1491 INITIAL-INPUT is a string inserted into the minibuffer initially.
1492 HISTORY is a list of previously selected inputs.
1493 DEF is the default value.
1494 INHERIT-INPUT-METHOD is currently ignored."
1495 (if (memq this-command '(tmm-menubar tmm-shortcut))
1496 (completing-read-default prompt collection
1497 predicate require-match
1498 initial-input history
1499 def inherit-input-method)
1500 ;; See the doc of `completing-read'.
1501 (when (consp history)
1502 (when (numberp (cdr history))
1503 (setq initial-input (nth (1- (cdr history))
1504 (symbol-value (car history)))))
1505 (setq history (car history)))
1506 (ivy-read (replace-regexp-in-string "%" "%%" prompt)
1507 collection
1508 :predicate predicate
1509 :require-match require-match
1510 :initial-input (if (consp initial-input)
1511 (car initial-input)
1512 (if (and (stringp initial-input)
1513 (string-match "\\+" initial-input))
1514 (replace-regexp-in-string
1515 "\\+" "\\\\+" initial-input)
1516 initial-input))
1517 :preselect (if (listp def) (car def) def)
1518 :history history
1519 :keymap nil
1520 :sort
1521 (let ((sort (assoc this-command ivy-sort-functions-alist)))
1522 (if sort
1523 (cdr sort)
1524 t)))))
1525
1526 (defvar ivy-completion-beg nil
1527 "Completion bounds start.")
1528
1529 (defvar ivy-completion-end nil
1530 "Completion bounds end.")
1531
1532 (defun ivy-completion-in-region-action (str)
1533 "Insert STR, erasing the previous one.
1534 The previous string is between `ivy-completion-beg' and `ivy-completion-end'."
1535 (when (stringp str)
1536 (with-ivy-window
1537 (when ivy-completion-beg
1538 (delete-region
1539 ivy-completion-beg
1540 ivy-completion-end))
1541 (setq ivy-completion-beg
1542 (move-marker (make-marker) (point)))
1543 (insert str)
1544 (setq ivy-completion-end
1545 (move-marker (make-marker) (point))))))
1546
1547 (defun ivy-completion-common-length (str)
1548 "Return the length of the first 'completions-common-part face in STR."
1549 (let ((pos 0)
1550 (len (length str)))
1551 (while (and (<= pos len)
1552 (let ((prop (get-text-property pos 'face str)))
1553 (not (eq 'completions-common-part
1554 (if (listp prop) (car prop) prop)))))
1555 (setq pos (1+ pos)))
1556 (if (< pos len)
1557 (or (next-single-property-change pos 'face str) len)
1558 0)))
1559
1560 (defun ivy-completion-in-region (start end collection &optional predicate)
1561 "An Ivy function suitable for `completion-in-region-function'."
1562 (let* ((enable-recursive-minibuffers t)
1563 (str (buffer-substring-no-properties start end))
1564 (completion-ignore-case case-fold-search)
1565 (comps
1566 (completion-all-completions str collection predicate (- end start))))
1567 (if (null comps)
1568 (message "No matches")
1569 (nconc comps nil)
1570 (setq ivy-completion-beg (- end (ivy-completion-common-length (car comps))))
1571 (setq ivy-completion-end end)
1572 (if (null (cdr comps))
1573 (if (string= str (car comps))
1574 (message "Sole match")
1575 (setf (ivy-state-window ivy-last) (selected-window))
1576 (ivy-completion-in-region-action
1577 (substring-no-properties
1578 (car comps))))
1579 (let* ((w (1+ (floor (log (length comps) 10))))
1580 (ivy-count-format (if (string= ivy-count-format "")
1581 ivy-count-format
1582 (format "%%-%dd " w)))
1583 (prompt (format "(%s): " str)))
1584 (and
1585 (ivy-read (if (string= ivy-count-format "")
1586 prompt
1587 (replace-regexp-in-string "%" "%%" prompt))
1588 ;; remove 'completions-first-difference face
1589 (mapcar #'substring-no-properties comps)
1590 :predicate predicate
1591 :action #'ivy-completion-in-region-action
1592 :require-match t)
1593 t))))))
1594
1595 (defcustom ivy-do-completion-in-region t
1596 "When non-nil `ivy-mode' will set `completion-in-region-function'."
1597 :type 'boolean)
1598
1599 ;;;###autoload
1600 (define-minor-mode ivy-mode
1601 "Toggle Ivy mode on or off.
1602 Turn Ivy mode on if ARG is positive, off otherwise.
1603 Turning on Ivy mode sets `completing-read-function' to
1604 `ivy-completing-read'.
1605
1606 Global bindings:
1607 \\{ivy-mode-map}
1608
1609 Minibuffer bindings:
1610 \\{ivy-minibuffer-map}"
1611 :group 'ivy
1612 :global t
1613 :keymap ivy-mode-map
1614 :lighter " ivy"
1615 (if ivy-mode
1616 (progn
1617 (setq completing-read-function 'ivy-completing-read)
1618 (when ivy-do-completion-in-region
1619 (setq completion-in-region-function 'ivy-completion-in-region)))
1620 (setq completing-read-function 'completing-read-default)
1621 (setq completion-in-region-function 'completion--in-region)))
1622
1623 (defun ivy--preselect-index (preselect candidates)
1624 "Return the index of PRESELECT in CANDIDATES."
1625 (cond ((integerp preselect)
1626 preselect)
1627 ((cl-position preselect candidates :test #'equal))
1628 ((stringp preselect)
1629 (let ((re preselect))
1630 (cl-position-if
1631 (lambda (x)
1632 (string-match re x))
1633 candidates)))))
1634
1635 ;;* Implementation
1636 ;;** Regex
1637 (defvar ivy--regex-hash
1638 (make-hash-table :test #'equal)
1639 "Store pre-computed regex.")
1640
1641 (defun ivy--split (str)
1642 "Split STR into a list by single spaces.
1643 The remaining spaces stick to their left.
1644 This allows to \"quote\" N spaces by inputting N+1 spaces."
1645 (let ((len (length str))
1646 start0
1647 (start1 0)
1648 res s
1649 match-len)
1650 (while (and (string-match " +" str start1)
1651 (< start1 len))
1652 (setq match-len (- (match-end 0) (match-beginning 0)))
1653 (if (= match-len 1)
1654 (progn
1655 (when start0
1656 (setq start1 start0)
1657 (setq start0 nil))
1658 (push (substring str start1 (match-beginning 0)) res)
1659 (setq start1 (match-end 0)))
1660 (setq str (replace-match
1661 (make-string (1- match-len) ?\ )
1662 nil nil str))
1663 (setq start0 (or start0 start1))
1664 (setq start1 (1- (match-end 0)))))
1665 (if start0
1666 (push (substring str start0) res)
1667 (setq s (substring str start1))
1668 (unless (= (length s) 0)
1669 (push s res)))
1670 (nreverse res)))
1671
1672 (defun ivy--regex (str &optional greedy)
1673 "Re-build regex pattern from STR in case it has a space.
1674 When GREEDY is non-nil, join words in a greedy way."
1675 (let ((hashed (unless greedy
1676 (gethash str ivy--regex-hash))))
1677 (if hashed
1678 (prog1 (cdr hashed)
1679 (setq ivy--subexps (car hashed)))
1680 (when (string-match "\\([^\\]\\|^\\)\\\\$" str)
1681 (setq str (substring str 0 -1)))
1682 (cdr (puthash str
1683 (let ((subs (ivy--split str)))
1684 (if (= (length subs) 1)
1685 (cons
1686 (setq ivy--subexps 0)
1687 (car subs))
1688 (cons
1689 (setq ivy--subexps (length subs))
1690 (mapconcat
1691 (lambda (x)
1692 (if (string-match "\\`\\\\([^?].*\\\\)\\'" x)
1693 x
1694 (format "\\(%s\\)" x)))
1695 subs
1696 (if greedy
1697 ".*"
1698 ".*?")))))
1699 ivy--regex-hash)))))
1700
1701 (defun ivy--regex-ignore-order--part (str &optional discard)
1702 "Re-build regex from STR by splitting at spaces.
1703 Ignore the order of each group."
1704 (let* ((subs (split-string str " +" t))
1705 (len (length subs)))
1706 (cl-case len
1707 (0
1708 "")
1709 (t
1710 (mapcar (lambda (x) (cons x (not discard)))
1711 subs)))))
1712
1713 (defun ivy--regex-ignore-order (str)
1714 "Re-build regex from STR by splitting at spaces.
1715 Ignore the order of each group. Everything before \"!\" should
1716 match. Everything after \"!\" should not match."
1717 (let ((parts (split-string str "!" t)))
1718 (cl-case (length parts)
1719 (0
1720 "")
1721 (1
1722 (if (string= (substring str 0 1) "!")
1723 (list (cons "" t)
1724 (ivy--regex-ignore-order--part (car parts) t))
1725 (ivy--regex-ignore-order--part (car parts))))
1726 (2
1727 (append
1728 (ivy--regex-ignore-order--part (car parts))
1729 (ivy--regex-ignore-order--part (cadr parts) t)))
1730 (t (error "Unexpected: use only one !")))))
1731
1732 (defun ivy--regex-plus (str)
1733 "Build a regex sequence from STR.
1734 Spaces are wild card characters, everything before \"!\" should
1735 match. Everything after \"!\" should not match."
1736 (let ((parts (split-string str "!" t)))
1737 (cl-case (length parts)
1738 (0
1739 "")
1740 (1
1741 (if (string= (substring str 0 1) "!")
1742 (list (cons "" t)
1743 (list (ivy--regex (car parts))))
1744 (ivy--regex (car parts))))
1745 (2
1746 (cons
1747 (cons (ivy--regex (car parts)) t)
1748 (mapcar #'list (split-string (cadr parts) " " t))))
1749 (t (error "Unexpected: use only one !")))))
1750
1751 (defun ivy--regex-fuzzy (str)
1752 "Build a regex sequence from STR.
1753 Insert .* between each char."
1754 (if (string-match "\\`\\(\\^?\\)\\(.*?\\)\\(\\$?\\)\\'" str)
1755 (prog1
1756 (concat (match-string 1 str)
1757 (mapconcat
1758 (lambda (x)
1759 (format "\\(%c\\)" x))
1760 (string-to-list (match-string 2 str)) ".*")
1761 (match-string 3 str))
1762 (setq ivy--subexps (length (match-string 2 str))))
1763 str))
1764
1765 (defcustom ivy-fixed-height-minibuffer nil
1766 "When non nil, fix the height of the minibuffer during ivy
1767 completion at `ivy-height'. This effectively sets the minimum
1768 height at this level and tries to ensure that it does not change
1769 depending on the number of candidates."
1770 :group 'ivy
1771 :type 'boolean)
1772
1773 ;;** Rest
1774 (defun ivy--minibuffer-setup ()
1775 "Setup ivy completion in the minibuffer."
1776 (set (make-local-variable 'completion-show-inline-help) nil)
1777 (set (make-local-variable 'minibuffer-default-add-function)
1778 (lambda ()
1779 (list ivy--default)))
1780 (when (display-graphic-p)
1781 (setq truncate-lines t))
1782 (setq-local max-mini-window-height ivy-height)
1783 (when ivy-fixed-height-minibuffer
1784 (set-window-text-height (selected-window) ivy-height))
1785 (add-hook 'post-command-hook #'ivy--exhibit nil t)
1786 ;; show completions with empty input
1787 (ivy--exhibit))
1788
1789 (defun ivy--input ()
1790 "Return the current minibuffer input."
1791 ;; assume one-line minibuffer input
1792 (buffer-substring-no-properties
1793 (minibuffer-prompt-end)
1794 (line-end-position)))
1795
1796 (defun ivy--cleanup ()
1797 "Delete the displayed completion candidates."
1798 (save-excursion
1799 (goto-char (minibuffer-prompt-end))
1800 (delete-region (line-end-position) (point-max))))
1801
1802 (defun ivy--insert-prompt ()
1803 "Update the prompt according to `ivy--prompt'."
1804 (when ivy--prompt
1805 (unless (memq this-command '(ivy-done ivy-alt-done ivy-partial-or-done
1806 counsel-find-symbol))
1807 (setq ivy--prompt-extra ""))
1808 (let (head tail)
1809 (if (string-match "\\(.*\\): \\'" ivy--prompt)
1810 (progn
1811 (setq head (match-string 1 ivy--prompt))
1812 (setq tail ": "))
1813 (setq head (substring ivy--prompt 0 -1))
1814 (setq tail " "))
1815 (let ((inhibit-read-only t)
1816 (std-props '(front-sticky t rear-nonsticky t field t read-only t))
1817 (n-str
1818 (concat
1819 (if (and (bound-and-true-p minibuffer-depth-indicate-mode)
1820 (> (minibuffer-depth) 1))
1821 (format "[%d] " (minibuffer-depth))
1822 "")
1823 (concat
1824 (if (string-match "%d.*%d" ivy-count-format)
1825 (format head
1826 (1+ ivy--index)
1827 (or (and (ivy-state-dynamic-collection ivy-last)
1828 ivy--full-length)
1829 ivy--length))
1830 (format head
1831 (or (and (ivy-state-dynamic-collection ivy-last)
1832 ivy--full-length)
1833 ivy--length)))
1834 ivy--prompt-extra
1835 tail)))
1836 (d-str (if ivy--directory
1837 (abbreviate-file-name ivy--directory)
1838 "")))
1839 (save-excursion
1840 (goto-char (point-min))
1841 (delete-region (point-min) (minibuffer-prompt-end))
1842 (if (> (+ (mod (+ (length n-str) (length d-str)) (window-width))
1843 (length ivy-text))
1844 (window-width))
1845 (setq n-str (concat n-str "\n" d-str))
1846 (setq n-str (concat n-str d-str)))
1847 (let ((regex (format "\\([^\n]\\{%d\\}\\)[^\n]" (window-width))))
1848 (while (string-match regex n-str)
1849 (setq n-str (replace-match (concat (match-string 1 n-str) "\n") nil t n-str 1))))
1850 (set-text-properties 0 (length n-str)
1851 `(face minibuffer-prompt ,@std-props)
1852 n-str)
1853 (ivy--set-match-props n-str "confirm"
1854 `(face ivy-confirm-face ,@std-props))
1855 (ivy--set-match-props n-str "match required"
1856 `(face ivy-match-required-face ,@std-props))
1857 (insert n-str))
1858 ;; get out of the prompt area
1859 (constrain-to-field nil (point-max))))))
1860
1861 (defun ivy--set-match-props (str match props)
1862 "Set STR text properties that match MATCH to PROPS."
1863 (when (string-match match str)
1864 (set-text-properties
1865 (match-beginning 0)
1866 (match-end 0)
1867 props
1868 str)))
1869
1870 (defvar inhibit-message)
1871
1872 (defun ivy--sort-maybe (collection)
1873 "Sort COLLECTION if needed."
1874 (let ((sort (ivy-state-sort ivy-last))
1875 entry)
1876 (if (null sort)
1877 collection
1878 (let ((sort-fn (cond ((functionp sort)
1879 sort)
1880 ((setq entry (assoc (ivy-state-collection ivy-last)
1881 ivy-sort-functions-alist))
1882 (cdr entry))
1883 (t
1884 (cdr (assoc t ivy-sort-functions-alist))))))
1885 (if (functionp sort-fn)
1886 (cl-sort (copy-sequence collection) sort-fn)
1887 collection)))))
1888
1889 (defun ivy--exhibit ()
1890 "Insert Ivy completions display.
1891 Should be run via minibuffer `post-command-hook'."
1892 (when (memq 'ivy--exhibit post-command-hook)
1893 (let ((inhibit-field-text-motion nil))
1894 (constrain-to-field nil (point-max)))
1895 (setq ivy-text (ivy--input))
1896 (if (ivy-state-dynamic-collection ivy-last)
1897 ;; while-no-input would cause annoying
1898 ;; "Waiting for process to die...done" message interruptions
1899 (let ((inhibit-message t))
1900 (unless (equal ivy--old-text ivy-text)
1901 (while-no-input
1902 (setq ivy--all-candidates
1903 (ivy--sort-maybe
1904 (funcall (ivy-state-collection ivy-last) ivy-text)))
1905 (setq ivy--old-text ivy-text)))
1906 (when ivy--all-candidates
1907 (ivy--insert-minibuffer
1908 (ivy--format ivy--all-candidates))))
1909 (cond (ivy--directory
1910 (if (string-match "/\\'" ivy-text)
1911 (if (member ivy-text ivy--all-candidates)
1912 (ivy--cd (expand-file-name ivy-text ivy--directory))
1913 (when (string-match "//\\'" ivy-text)
1914 (if (and default-directory
1915 (string-match "\\`[[:alpha:]]:/" default-directory))
1916 (ivy--cd (match-string 0 default-directory))
1917 (ivy--cd "/")))
1918 (when (string-match "[[:alpha:]]:/$" ivy-text)
1919 (let ((drive-root (match-string 0 ivy-text)))
1920 (when (file-exists-p drive-root)
1921 (ivy--cd drive-root)))))
1922 (if (string-match "\\`~\\'" ivy-text)
1923 (ivy--cd (expand-file-name "~/")))))
1924 ((eq (ivy-state-collection ivy-last) 'internal-complete-buffer)
1925 (when (or (and (string-match "\\` " ivy-text)
1926 (not (string-match "\\` " ivy--old-text)))
1927 (and (string-match "\\` " ivy--old-text)
1928 (not (string-match "\\` " ivy-text))))
1929 (setq ivy--all-candidates
1930 (if (and (> (length ivy-text) 0)
1931 (eq (aref ivy-text 0)
1932 ?\ ))
1933 (ivy--buffer-list " ")
1934 (ivy--buffer-list "" ivy-use-virtual-buffers)))
1935 (setq ivy--old-re nil))))
1936 (ivy--insert-minibuffer
1937 (with-current-buffer (ivy-state-buffer ivy-last)
1938 (ivy--format
1939 (ivy--filter ivy-text ivy--all-candidates))))
1940 (setq ivy--old-text ivy-text))))
1941
1942 (defun ivy--insert-minibuffer (text)
1943 "Insert TEXT into minibuffer with appropriate cleanup."
1944 (let ((resize-mini-windows nil)
1945 (update-fn (ivy-state-update-fn ivy-last))
1946 deactivate-mark)
1947 (ivy--cleanup)
1948 (when update-fn
1949 (funcall update-fn))
1950 (ivy--insert-prompt)
1951 ;; Do nothing if while-no-input was aborted.
1952 (when (stringp text)
1953 (let ((buffer-undo-list t))
1954 (save-excursion
1955 (forward-line 1)
1956 (insert text))))
1957 (when (display-graphic-p)
1958 (ivy--resize-minibuffer-to-fit))))
1959
1960 (defun ivy--resize-minibuffer-to-fit ()
1961 "Resize the minibuffer window size to fit the text in the minibuffer."
1962 (unless (frame-root-window-p (minibuffer-window))
1963 (with-selected-window (minibuffer-window)
1964 (if (fboundp 'window-text-pixel-size)
1965 (let ((text-height (cdr (window-text-pixel-size)))
1966 (body-height (window-body-height nil t)))
1967 (when (> text-height body-height)
1968 ;; Note: the size increment needs to be at least frame-char-height,
1969 ;; otherwise resizing won't do anything.
1970 (let ((delta (max (- text-height body-height) (frame-char-height))))
1971 (window-resize nil delta nil t t))))
1972 (let ((text-height (count-screen-lines))
1973 (body-height (window-body-height)))
1974 (when (> text-height body-height)
1975 (window-resize nil (- text-height body-height) nil t)))))))
1976
1977 (declare-function colir-blend-face-background "ext:colir")
1978
1979 (defun ivy--add-face (str face)
1980 "Propertize STR with FACE.
1981 `font-lock-append-text-property' is used, since it's better than
1982 `propertize' or `add-face-text-property' in this case."
1983 (require 'colir)
1984 (condition-case nil
1985 (progn
1986 (colir-blend-face-background 0 (length str) face str)
1987 (let ((foreground (face-foreground face)))
1988 (when foreground
1989 (add-face-text-property
1990 0 (length str)
1991 `(:foreground ,foreground)
1992 nil
1993 str))))
1994 (error
1995 (ignore-errors
1996 (font-lock-append-text-property 0 (length str) 'face face str))))
1997 str)
1998
1999 (declare-function flx-make-string-cache "ext:flx")
2000 (declare-function flx-score "ext:flx")
2001
2002 (defvar ivy--flx-cache nil)
2003
2004 (eval-after-load 'flx
2005 '(setq ivy--flx-cache (flx-make-string-cache)))
2006
2007 (defun ivy-toggle-case-fold ()
2008 "Toggle the case folding between nil and auto.
2009 In any completion session, the case folding starts in auto:
2010
2011 - when the input is all lower case, `case-fold-search' is t
2012 - otherwise nil.
2013
2014 You can toggle this to make `case-fold-search' nil regardless of input."
2015 (interactive)
2016 (setq ivy-case-fold-search
2017 (if ivy-case-fold-search
2018 nil
2019 'auto))
2020 ;; reset cache so that the candidate list updates
2021 (setq ivy--old-re nil))
2022
2023 (defun ivy--re-filter (re candidates)
2024 "Return all RE matching CANDIDATES.
2025 RE is a list of cons cells, with a regexp car and a boolean cdr.
2026 When the cdr is t, the car must match.
2027 Otherwise, the car must not match."
2028 (let ((re-list (if (stringp re) (list (cons re t)) re))
2029 (res candidates))
2030 (dolist (re re-list)
2031 (setq res
2032 (ignore-errors
2033 (funcall
2034 (if (cdr re)
2035 #'cl-remove-if-not
2036 #'cl-remove-if)
2037 (let ((re-str (car re)))
2038 (lambda (x) (string-match re-str x)))
2039 res))))
2040 res))
2041
2042 (defun ivy--filter (name candidates)
2043 "Return all items that match NAME in CANDIDATES.
2044 CANDIDATES are assumed to be static."
2045 (let ((re (funcall ivy--regex-function name)))
2046 (if (and (equal re ivy--old-re)
2047 ivy--old-cands)
2048 ;; quick caching for "C-n", "C-p" etc.
2049 ivy--old-cands
2050 (let* ((re-str (if (listp re) (caar re) re))
2051 (matcher (ivy-state-matcher ivy-last))
2052 (case-fold-search
2053 (and ivy-case-fold-search
2054 (string= name (downcase name))))
2055 (cands (cond
2056 (matcher
2057 (funcall matcher re candidates))
2058 ((and ivy--old-re
2059 (stringp re)
2060 (stringp ivy--old-re)
2061 (not (string-match "\\\\" ivy--old-re))
2062 (not (equal ivy--old-re ""))
2063 (memq (cl-search
2064 (if (string-match "\\\\)\\'" ivy--old-re)
2065 (substring ivy--old-re 0 -2)
2066 ivy--old-re)
2067 re)
2068 '(0 2)))
2069 (ignore-errors
2070 (cl-remove-if-not
2071 (lambda (x) (string-match re x))
2072 ivy--old-cands)))
2073 (t
2074 (ivy--re-filter re candidates)))))
2075 (ivy--recompute-index name re-str cands)
2076 (setq ivy--old-re
2077 (if (eq ivy--regex-function 'ivy--regex-ignore-order)
2078 re
2079 (if cands
2080 re-str
2081 "")))
2082 (setq ivy--old-cands (ivy--sort name cands))))))
2083
2084 (defun ivy--set-candidates (x)
2085 "Update `ivy--all-candidates' with X."
2086 (let (res)
2087 (dolist (source ivy--extra-candidates)
2088 (if (equal source '(original-source))
2089 (if (null res)
2090 (setq res x)
2091 (setq res (append x res)))
2092 (setq ivy--old-re nil)
2093 (setq res (append
2094 (ivy--filter ivy-text (cadr source))
2095 res))))
2096 (setq ivy--all-candidates res)))
2097
2098 (defcustom ivy-sort-matches-functions-alist '((t . nil))
2099 "An alist of functions for sorting matching candidates.
2100
2101 Unlike `ivy-sort-functions-alist', which is used to sort the
2102 whole collection only once, this alist of functions are used to
2103 sort only matching candidates after each change in input.
2104
2105 The alist KEY is either a collection function or t to match
2106 previously unmatched collection functions.
2107
2108 The alist VAL is a sorting function with the signature of
2109 `ivy--prefix-sort'."
2110 :type '(alist
2111 :key-type (choice
2112 (const :tag "Fall-through" t)
2113 (symbol :tag "Collection"))
2114 :value-type
2115 (choice
2116 (const :tag "Don't sort" nil)
2117 (const :tag "Put prefix matches ahead" 'ivy--prefix-sort)
2118 (function :tag "Custom sort function"))))
2119
2120 (defun ivy--sort-files-by-date (_name candidates)
2121 "Re-soft CANDIDATES according to file modification date."
2122 (let ((default-directory ivy--directory))
2123 (cl-sort (copy-sequence candidates)
2124 (lambda (f1 f2)
2125 (time-less-p
2126 (nth 5 (file-attributes f2))
2127 (nth 5 (file-attributes f1)))))))
2128
2129 (defun ivy--sort (name candidates)
2130 "Re-sort CANDIDATES by NAME.
2131 All CANDIDATES are assumed to match NAME."
2132 (let ((key (or (ivy-state-caller ivy-last)
2133 (when (functionp (ivy-state-collection ivy-last))
2134 (ivy-state-collection ivy-last))))
2135 fun)
2136 (cond ((and (require 'flx nil 'noerror)
2137 (eq ivy--regex-function 'ivy--regex-fuzzy))
2138 (ivy--flx-sort name candidates))
2139 ((setq fun (cdr (or (assoc key ivy-sort-matches-functions-alist)
2140 (assoc t ivy-sort-matches-functions-alist))))
2141 (funcall fun name candidates))
2142 (t
2143 candidates))))
2144
2145 (defun ivy--prefix-sort (name candidates)
2146 "Re-sort CANDIDATES.
2147 Prefix matches to NAME are put ahead of the list."
2148 (if (or (string-match "^\\^" name) (string= name ""))
2149 candidates
2150 (let ((re-prefix (concat "^" (funcall ivy--regex-function name)))
2151 res-prefix
2152 res-noprefix)
2153 (dolist (s candidates)
2154 (if (string-match re-prefix s)
2155 (push s res-prefix)
2156 (push s res-noprefix)))
2157 (nconc
2158 (nreverse res-prefix)
2159 (nreverse res-noprefix)))))
2160
2161 (defun ivy--recompute-index (name re-str cands)
2162 (let* ((caller (ivy-state-caller ivy-last))
2163 (func (or (and caller (cdr (assoc caller ivy-index-functions-alist)))
2164 (cdr (assoc t ivy-index-functions-alist))
2165 #'ivy-recompute-index-zero)))
2166 (unless (eq this-command 'ivy-resume)
2167 (setq ivy--index
2168 (or
2169 (cl-position (if (and (> (length name) 0)
2170 (eq ?^ (aref name 0)))
2171 (substring name 1)
2172 name) cands
2173 :test #'equal)
2174 (and ivy--directory
2175 (cl-position
2176 (concat re-str "/") cands
2177 :test #'equal))
2178 (and (not (string= name ""))
2179 (not (and (require 'flx nil 'noerror)
2180 (eq ivy--regex-function 'ivy--regex-fuzzy)
2181 (< (length cands) 200)))
2182
2183 (cl-position (nth ivy--index ivy--old-cands)
2184 cands))
2185 (funcall func re-str cands))))
2186 (when (and (or (string= name "")
2187 (string= name "^"))
2188 (not (equal ivy--old-re "")))
2189 (setq ivy--index
2190 (or (ivy--preselect-index
2191 (ivy-state-preselect ivy-last)
2192 cands)
2193 ivy--index)))))
2194
2195 (defun ivy-recompute-index-swiper (_re-str cands)
2196 (let ((tail (nthcdr ivy--index ivy--old-cands))
2197 idx)
2198 (if (and tail ivy--old-cands (not (equal "^" ivy--old-re)))
2199 (progn
2200 (while (and tail (null idx))
2201 ;; Compare with eq to handle equal duplicates in cands
2202 (setq idx (cl-position (pop tail) cands)))
2203 (or
2204 idx
2205 (1- (length cands))))
2206 (if ivy--old-cands
2207 ivy--index
2208 ;; already in ivy-state-buffer
2209 (let ((n (line-number-at-pos))
2210 (res 0)
2211 (i 0))
2212 (dolist (c cands)
2213 (when (eq n (read (get-text-property 0 'display c)))
2214 (setq res i))
2215 (cl-incf i))
2216 res)))))
2217
2218 (defun ivy-recompute-index-swiper-async (_re-str cands)
2219 (let ((tail (nthcdr ivy--index ivy--old-cands))
2220 idx)
2221 (if (and tail ivy--old-cands (not (equal "^" ivy--old-re)))
2222 (progn
2223 (while (and tail (null idx))
2224 ;; Compare with `equal', since the collection is re-created
2225 ;; each time with `split-string'
2226 (setq idx (cl-position (pop tail) cands :test #'equal)))
2227 (or idx 0))
2228 ivy--index)))
2229
2230 (defun ivy-recompute-index-zero (_re-str _cands)
2231 0)
2232
2233 (defcustom ivy-minibuffer-faces
2234 '(ivy-minibuffer-match-face-1
2235 ivy-minibuffer-match-face-2
2236 ivy-minibuffer-match-face-3
2237 ivy-minibuffer-match-face-4)
2238 "List of `ivy' faces for minibuffer group matches."
2239 :type '(repeat :tag "Faces"
2240 (choice
2241 (const ivy-minibuffer-match-face-1)
2242 (const ivy-minibuffer-match-face-2)
2243 (const ivy-minibuffer-match-face-3)
2244 (const ivy-minibuffer-match-face-4)
2245 (face :tag "Other face"))))
2246
2247 (defvar ivy-flx-limit 200
2248 "Used to conditionally turn off flx sorting.
2249
2250 When the amount of matching candidates exceeds this limit, then
2251 no sorting is done.")
2252
2253 (defun ivy--flx-sort (name cands)
2254 "Sort according to closeness to string NAME the string list CANDS."
2255 (condition-case nil
2256 (if (and cands
2257 (< (length cands) ivy-flx-limit))
2258 (let* ((flx-name (if (string-match "^\\^" name)
2259 (substring name 1)
2260 name))
2261 (cands-with-score
2262 (delq nil
2263 (mapcar
2264 (lambda (x)
2265 (let ((score (flx-score x flx-name ivy--flx-cache)))
2266 (and score
2267 (cons score x))))
2268 cands))))
2269 (if cands-with-score
2270 (mapcar (lambda (x)
2271 (let ((str (copy-sequence (cdr x)))
2272 (i 0)
2273 (last-j -2))
2274 (dolist (j (cdar x))
2275 (unless (eq j (1+ last-j))
2276 (cl-incf i))
2277 (setq last-j j)
2278 (ivy-add-face-text-property
2279 j (1+ j)
2280 (nth (1+ (mod (+ i 2) (1- (length ivy-minibuffer-faces))))
2281 ivy-minibuffer-faces)
2282 str))
2283 str))
2284 (sort cands-with-score
2285 (lambda (x y)
2286 (> (caar x) (caar y)))))
2287 cands))
2288 cands)
2289 (error
2290 cands)))
2291
2292 (defcustom ivy-format-function 'ivy-format-function-default
2293 "Function to transform the list of candidates into a string.
2294 This string is inserted into the minibuffer."
2295 :type '(choice
2296 (const :tag "Default" ivy-format-function-default)
2297 (const :tag "Arrow prefix" ivy-format-function-arrow)
2298 (const :tag "Full line" ivy-format-function-line)))
2299
2300 (defun ivy--truncate-string (str width)
2301 "Truncate STR to WIDTH."
2302 (if (> (string-width str) width)
2303 (concat (substring str 0 (min (- width 3)
2304 (- (length str) 3))) "...")
2305 str))
2306
2307 (defun ivy--format-function-generic (selected-fn other-fn strs separator)
2308 "Transform CAND-PAIRS into a string for minibuffer.
2309 SELECTED-FN and OTHER-FN each take two string arguments.
2310 SEPARATOR is used to join the candidates."
2311 (let ((i -1))
2312 (mapconcat
2313 (lambda (str)
2314 (let ((curr (eq (cl-incf i) ivy--index)))
2315 (if curr
2316 (funcall selected-fn str)
2317 (funcall other-fn str))))
2318 strs
2319 separator)))
2320
2321 (defun ivy-format-function-default (cands)
2322 "Transform CAND-PAIRS into a string for minibuffer."
2323 (ivy--format-function-generic
2324 (lambda (str)
2325 (ivy--add-face str 'ivy-current-match))
2326 #'identity
2327 cands
2328 "\n"))
2329
2330 (defun ivy-format-function-arrow (cands)
2331 "Transform CAND-PAIRS into a string for minibuffer."
2332 (ivy--format-function-generic
2333 (lambda (str)
2334 (concat "> " (ivy--add-face str 'ivy-current-match)))
2335 (lambda (str)
2336 (concat " " str))
2337 cands
2338 "\n"))
2339
2340 (defun ivy-format-function-line (cands)
2341 "Transform CAND-PAIRS into a string for minibuffer."
2342 (ivy--format-function-generic
2343 (lambda (str)
2344 (ivy--add-face (concat str "\n") 'ivy-current-match))
2345 (lambda (str)
2346 (concat str "\n"))
2347 cands
2348 ""))
2349
2350 (defun ivy-add-face-text-property (start end face str)
2351 (if (fboundp 'add-face-text-property)
2352 (add-face-text-property
2353 start end face nil str)
2354 (font-lock-append-text-property
2355 start end 'face face str)))
2356
2357 (defun ivy--format-minibuffer-line (str)
2358 (let ((start 0)
2359 (str (copy-sequence str)))
2360 (cond ((eq ivy--regex-function 'ivy--regex-ignore-order)
2361 (when (consp ivy--old-re)
2362 (let ((i 1))
2363 (dolist (re ivy--old-re)
2364 (when (string-match (car re) str)
2365 (ivy-add-face-text-property
2366 (match-beginning 0) (match-end 0)
2367 (nth (1+ (mod (+ i 2) (1- (length ivy-minibuffer-faces))))
2368 ivy-minibuffer-faces)
2369 str))
2370 (cl-incf i)))))
2371 ((and (eq ivy-display-style 'fancy)
2372 (not (eq ivy--regex-function 'ivy--regex-fuzzy)))
2373 (unless ivy--old-re
2374 (setq ivy--old-re (funcall ivy--regex-function ivy-text)))
2375 (while (and (string-match ivy--old-re str start)
2376 (> (- (match-end 0) (match-beginning 0)) 0))
2377 (setq start (match-end 0))
2378 (let ((i 0))
2379 (while (<= i ivy--subexps)
2380 (let ((face
2381 (cond ((zerop ivy--subexps)
2382 (cadr ivy-minibuffer-faces))
2383 ((zerop i)
2384 (car ivy-minibuffer-faces))
2385 (t
2386 (nth (1+ (mod (+ i 2) (1- (length ivy-minibuffer-faces))))
2387 ivy-minibuffer-faces)))))
2388 (ivy-add-face-text-property
2389 (match-beginning i) (match-end i)
2390 face str))
2391 (cl-incf i))))))
2392 str))
2393
2394 (ivy-set-display-transformer
2395 'read-file-name-internal 'ivy-read-file-transformer)
2396
2397 (defun ivy-read-file-transformer (str)
2398 (if (string-match-p "/\\'" str)
2399 (propertize str 'face 'ivy-subdir)
2400 str))
2401
2402 (defun ivy--format (cands)
2403 "Return a string for CANDS suitable for display in the minibuffer.
2404 CANDS is a list of strings."
2405 (setq ivy--length (length cands))
2406 (when (>= ivy--index ivy--length)
2407 (setq ivy--index (max (1- ivy--length) 0)))
2408 (if (null cands)
2409 (setq ivy--current "")
2410 (let* ((half-height (/ ivy-height 2))
2411 (start (max 0 (- ivy--index half-height)))
2412 (end (min (+ start (1- ivy-height)) ivy--length))
2413 (start (max 0 (min start (- end (1- ivy-height)))))
2414 (cands (cl-subseq cands start end))
2415 (index (- ivy--index start))
2416 transformer-fn)
2417 (setq ivy--current (copy-sequence (nth index cands)))
2418 (when (setq transformer-fn (ivy-state-display-transformer-fn ivy-last))
2419 (with-ivy-window
2420 (setq cands (mapcar transformer-fn cands))))
2421 (let* ((ivy--index index)
2422 (cands (mapcar
2423 #'ivy--format-minibuffer-line
2424 cands))
2425 (res (concat "\n" (funcall ivy-format-function cands))))
2426 (put-text-property 0 (length res) 'read-only nil res)
2427 res))))
2428
2429 (defvar ivy--virtual-buffers nil
2430 "Store the virtual buffers alist.")
2431
2432 (defvar recentf-list)
2433
2434 (defcustom ivy-virtual-abbreviate 'name
2435 "The mode of abbreviation for virtual buffer names."
2436 :type '(choice
2437 (const :tag "Only name" name)
2438 (const :tag "Full path" full)
2439 ;; eventually, uniquify
2440 ))
2441
2442 (defun ivy--virtual-buffers ()
2443 "Adapted from `ido-add-virtual-buffers-to-list'."
2444 (unless recentf-mode
2445 (recentf-mode 1))
2446 (let ((bookmarks (and (boundp 'bookmark-alist)
2447 bookmark-alist))
2448 virtual-buffers name)
2449 (dolist (head (append
2450 recentf-list
2451 (delete " - no file -"
2452 (delq nil (mapcar (lambda (bookmark)
2453 (cdr (assoc 'filename bookmark)))
2454 bookmarks)))))
2455 (setq name
2456 (if (eq ivy-virtual-abbreviate 'name)
2457 (file-name-nondirectory head)
2458 (expand-file-name head)))
2459 (when (equal name "")
2460 (setq name (file-name-nondirectory (directory-file-name head))))
2461 (when (equal name "")
2462 (setq name head))
2463 (and (not (equal name ""))
2464 (null (get-file-buffer head))
2465 (not (assoc name virtual-buffers))
2466 (push (cons name head) virtual-buffers)))
2467 (when virtual-buffers
2468 (dolist (comp virtual-buffers)
2469 (put-text-property 0 (length (car comp))
2470 'face 'ivy-virtual
2471 (car comp)))
2472 (setq ivy--virtual-buffers (nreverse virtual-buffers))
2473 (mapcar #'car ivy--virtual-buffers))))
2474
2475 (defcustom ivy-ignore-buffers nil
2476 "List of regexps matching buffer names to ignore."
2477 :type '(repeat regexp))
2478
2479 (defun ivy--buffer-list (str &optional virtual)
2480 "Return the buffers that match STR.
2481 When VIRTUAL is non-nil, add virtual buffers."
2482 (delete-dups
2483 (append
2484 (mapcar
2485 (lambda (x)
2486 (if (with-current-buffer x
2487 (file-remote-p
2488 (abbreviate-file-name default-directory)))
2489 (propertize x 'face 'ivy-remote)
2490 x))
2491 (all-completions str 'internal-complete-buffer))
2492 (and virtual
2493 (ivy--virtual-buffers)))))
2494
2495 (defun ivy--switch-buffer-action (buffer)
2496 "Switch to BUFFER.
2497 BUFFER may be a string or nil."
2498 (with-ivy-window
2499 (if (zerop (length buffer))
2500 (switch-to-buffer
2501 ivy-text nil 'force-same-window)
2502 (let ((virtual (assoc buffer ivy--virtual-buffers)))
2503 (if (and virtual
2504 (not (get-buffer buffer)))
2505 (find-file (cdr virtual))
2506 (switch-to-buffer
2507 buffer nil 'force-same-window))))))
2508
2509 (defun ivy--switch-buffer-other-window-action (buffer)
2510 "Switch to BUFFER in other window.
2511 BUFFER may be a string or nil."
2512 (if (zerop (length buffer))
2513 (switch-to-buffer-other-window ivy-text)
2514 (let ((virtual (assoc buffer ivy--virtual-buffers)))
2515 (if (and virtual
2516 (not (get-buffer buffer)))
2517 (find-file-other-window (cdr virtual))
2518 (switch-to-buffer-other-window buffer)))))
2519
2520 (defun ivy--rename-buffer-action (buffer)
2521 "Rename BUFFER."
2522 (let ((new-name (read-string "Rename buffer (to new name): ")))
2523 (with-current-buffer buffer
2524 (rename-buffer new-name))))
2525
2526 (defvar ivy-switch-buffer-map (make-sparse-keymap))
2527
2528 (ivy-set-actions
2529 'ivy-switch-buffer
2530 '(("k"
2531 (lambda (x)
2532 (kill-buffer x)
2533 (ivy--reset-state ivy-last))
2534 "kill")
2535 ("j"
2536 ivy--switch-buffer-other-window-action
2537 "other")
2538 ("r"
2539 ivy--rename-buffer-action
2540 "rename")))
2541
2542 (defun ivy--switch-buffer-matcher (regexp candidates)
2543 "Return REGEXP-matching CANDIDATES.
2544 Skip buffers that match `ivy-ignore-buffers'."
2545 (let ((res (ivy--re-filter regexp candidates)))
2546 (if (or (null ivy-use-ignore)
2547 (null ivy-ignore-buffers))
2548 res
2549 (or (cl-remove-if
2550 (lambda (buf)
2551 (cl-find-if
2552 (lambda (regexp)
2553 (string-match regexp buf))
2554 ivy-ignore-buffers))
2555 res)
2556 res))))
2557
2558 (ivy-set-display-transformer
2559 'ivy-switch-buffer 'ivy-switch-buffer-transformer)
2560 (ivy-set-display-transformer
2561 'internal-complete-buffer 'ivy-switch-buffer-transformer)
2562
2563 (defun ivy-switch-buffer-transformer (str)
2564 (let ((b (get-buffer str)))
2565 (if (and b
2566 (buffer-file-name b)
2567 (buffer-modified-p b))
2568 (propertize str 'face 'ivy-modified-buffer)
2569 str)))
2570
2571 ;;;###autoload
2572 (defun ivy-switch-buffer ()
2573 "Switch to another buffer."
2574 (interactive)
2575 (let ((this-command 'ivy-switch-buffer))
2576 (ivy-read "Switch to buffer: " 'internal-complete-buffer
2577 :matcher #'ivy--switch-buffer-matcher
2578 :preselect (buffer-name (other-buffer (current-buffer)))
2579 :action #'ivy--switch-buffer-action
2580 :keymap ivy-switch-buffer-map
2581 :caller 'ivy-switch-buffer)))
2582
2583 ;;;###autoload
2584 (defun ivy-switch-buffer-other-window ()
2585 "Switch to another buffer in another window."
2586 (interactive)
2587 (ivy-read "Switch to buffer in other window: " 'internal-complete-buffer
2588 :preselect (buffer-name (other-buffer (current-buffer)))
2589 :action #'ivy--switch-buffer-other-window-action
2590 :keymap ivy-switch-buffer-map
2591 :caller 'ivy-switch-buffer-other-window))
2592
2593 ;;;###autoload
2594 (defun ivy-recentf ()
2595 "Find a file on `recentf-list'."
2596 (interactive)
2597 (ivy-read "Recentf: " recentf-list
2598 :action
2599 (lambda (f)
2600 (with-ivy-window
2601 (find-file f)))
2602 :caller 'ivy-recentf))
2603
2604 (defun ivy-yank-word ()
2605 "Pull next word from buffer into search string."
2606 (interactive)
2607 (let (amend)
2608 (with-ivy-window
2609 (let ((pt (point))
2610 (le (line-end-position)))
2611 (forward-word 1)
2612 (if (> (point) le)
2613 (goto-char pt)
2614 (setq amend (buffer-substring-no-properties pt (point))))))
2615 (when amend
2616 (insert (replace-regexp-in-string " +" " " amend)))))
2617
2618 (defun ivy-kill-ring-save ()
2619 "Store the current candidates into the kill ring.
2620 If the region is active, forward to `kill-ring-save' instead."
2621 (interactive)
2622 (if (region-active-p)
2623 (call-interactively 'kill-ring-save)
2624 (kill-new
2625 (mapconcat
2626 #'identity
2627 ivy--old-cands
2628 "\n"))))
2629
2630 (defun ivy-insert-current ()
2631 "Make the current candidate into current input.
2632 Don't finish completion."
2633 (interactive)
2634 (delete-minibuffer-contents)
2635 (if (and ivy--directory
2636 (string-match "/$" ivy--current))
2637 (insert (substring ivy--current 0 -1))
2638 (insert ivy--current)))
2639
2640 (defun ivy-toggle-fuzzy ()
2641 "Toggle the re builder between `ivy--regex-fuzzy' and `ivy--regex-plus'."
2642 (interactive)
2643 (setq ivy--old-re nil)
2644 (if (eq ivy--regex-function 'ivy--regex-fuzzy)
2645 (setq ivy--regex-function 'ivy--regex-plus)
2646 (setq ivy--regex-function 'ivy--regex-fuzzy)))
2647
2648 (defun ivy-reverse-i-search ()
2649 "Enter a recursive `ivy-read' session using the current history.
2650 The selected history element will be inserted into the minibuffer."
2651 (interactive)
2652 (let ((enable-recursive-minibuffers t)
2653 (history (symbol-value (ivy-state-history ivy-last)))
2654 (old-last ivy-last)
2655 (ivy-recursive-restore nil))
2656 (ivy-read "Reverse-i-search: "
2657 history
2658 :action (lambda (x)
2659 (ivy--reset-state
2660 (setq ivy-last old-last))
2661 (delete-minibuffer-contents)
2662 (insert (substring-no-properties x))
2663 (ivy--cd-maybe)))))
2664
2665 (defun ivy-restrict-to-matches ()
2666 "Restrict candidates to current matches and erase input."
2667 (interactive)
2668 (delete-minibuffer-contents)
2669 (setq ivy--all-candidates
2670 (ivy--filter ivy-text ivy--all-candidates)))
2671
2672 ;;* Occur
2673 (defvar-local ivy-occur-last nil
2674 "Buffer-local value of `ivy-last'.
2675 Can't re-use `ivy-last' because using e.g. `swiper' in the same
2676 buffer would modify `ivy-last'.")
2677
2678 (defvar ivy-occur-mode-map
2679 (let ((map (make-sparse-keymap)))
2680 (define-key map [mouse-1] 'ivy-occur-click)
2681 (define-key map (kbd "RET") 'ivy-occur-press)
2682 (define-key map (kbd "j") 'ivy-occur-next-line)
2683 (define-key map (kbd "k") 'ivy-occur-previous-line)
2684 (define-key map (kbd "h") 'backward-char)
2685 (define-key map (kbd "l") 'forward-char)
2686 (define-key map (kbd "g") 'ivy-occur-press)
2687 (define-key map (kbd "a") 'ivy-occur-read-action)
2688 (define-key map (kbd "o") 'ivy-occur-dispatch)
2689 (define-key map (kbd "c") 'ivy-occur-toggle-calling)
2690 (define-key map (kbd "q") 'quit-window)
2691 map)
2692 "Keymap for Ivy Occur mode.")
2693
2694 (defun ivy-occur-toggle-calling ()
2695 "Toggle `ivy-calling'."
2696 (interactive)
2697 (if (setq ivy-calling (not ivy-calling))
2698 (progn
2699 (setq mode-name "Ivy-Occur [calling]")
2700 (ivy-occur-press))
2701 (setq mode-name "Ivy-Occur"))
2702 (force-mode-line-update))
2703
2704 (defun ivy-occur-next-line (&optional arg)
2705 "Move the cursor down ARG lines.
2706 When `ivy-calling' isn't nil, call `ivy-occur-press'."
2707 (interactive "p")
2708 (forward-line arg)
2709 (when ivy-calling
2710 (ivy-occur-press)))
2711
2712 (defun ivy-occur-previous-line (&optional arg)
2713 "Move the cursor up ARG lines.
2714 When `ivy-calling' isn't nil, call `ivy-occur-press'."
2715 (interactive "p")
2716 (forward-line (- arg))
2717 (when ivy-calling
2718 (ivy-occur-press)))
2719
2720 (define-derived-mode ivy-occur-mode fundamental-mode "Ivy-Occur"
2721 "Major mode for output from \\[ivy-occur].
2722
2723 \\{ivy-occur-mode-map}")
2724
2725 (defvar ivy-occur-grep-mode-map
2726 (let ((map (copy-keymap ivy-occur-mode-map)))
2727 (define-key map (kbd "C-x C-q") 'ivy-wgrep-change-to-wgrep-mode)
2728 map)
2729 "Keymap for Ivy Occur Grep mode.")
2730
2731 (define-derived-mode ivy-occur-grep-mode grep-mode "Ivy-Occur"
2732 "Major mode for output from \\[ivy-occur].
2733
2734 \\{ivy-occur-grep-mode-map}")
2735
2736 (defvar ivy--occurs-list nil
2737 "A list of custom occur generators per command.")
2738
2739 (defun ivy-set-occur (cmd occur)
2740 "Assign CMD a custom OCCUR function."
2741 (setq ivy--occurs-list
2742 (plist-put ivy--occurs-list cmd occur)))
2743
2744 (defun ivy--occur-insert-lines (cands)
2745 (dolist (str cands)
2746 (add-text-properties
2747 0 (length str)
2748 `(mouse-face
2749 highlight
2750 help-echo "mouse-1: call ivy-action")
2751 str)
2752 (insert str "\n")))
2753
2754 (defun ivy-occur ()
2755 "Stop completion and put the current matches into a new buffer.
2756
2757 The new buffer remembers current action(s).
2758
2759 While in the *ivy-occur* buffer, selecting a candidate with RET or
2760 a mouse click will call the appropriate action for that candidate.
2761
2762 There is no limit on the number of *ivy-occur* buffers."
2763 (interactive)
2764 (if (not (window-minibuffer-p))
2765 (user-error "No completion session is active")
2766 (let* ((caller (ivy-state-caller ivy-last))
2767 (occur-fn (plist-get ivy--occurs-list caller))
2768 (buffer
2769 (generate-new-buffer
2770 (format "*ivy-occur%s \"%s\"*"
2771 (if caller
2772 (concat " " (prin1-to-string caller))
2773 "")
2774 ivy-text))))
2775 (with-current-buffer buffer
2776 (let ((inhibit-read-only t))
2777 (erase-buffer)
2778 (if occur-fn
2779 (funcall occur-fn)
2780 (ivy-occur-mode)
2781 (insert (format "%d candidates:\n" (length ivy--old-cands)))
2782 (ivy--occur-insert-lines
2783 (mapcar
2784 (lambda (cand) (concat " " cand))
2785 ivy--old-cands))))
2786 (setf (ivy-state-text ivy-last) ivy-text)
2787 (setq ivy-occur-last ivy-last)
2788 (setq-local ivy--directory ivy--directory))
2789 (ivy-exit-with-action
2790 `(lambda (_) (pop-to-buffer ,buffer))))))
2791
2792 (declare-function wgrep-change-to-wgrep-mode "ext:wgrep")
2793
2794 (defun ivy-wgrep-change-to-wgrep-mode ()
2795 "Forward to `wgrep-change-to-wgrep-mode'."
2796 (interactive)
2797 (if (require 'wgrep nil 'noerror)
2798 (wgrep-change-to-wgrep-mode)
2799 (error "Package wgrep isn't installed")))
2800
2801 (defun ivy-occur-read-action ()
2802 "Select one of the available actions as the current one."
2803 (interactive)
2804 (let ((ivy-last ivy-occur-last))
2805 (ivy-read-action)))
2806
2807 (defun ivy-occur-dispatch ()
2808 "Call one of the available actions on the current item."
2809 (interactive)
2810 (let* ((state-action (ivy-state-action ivy-occur-last))
2811 (actions (if (symbolp state-action)
2812 state-action
2813 (copy-sequence state-action))))
2814 (unwind-protect
2815 (progn
2816 (ivy-occur-read-action)
2817 (ivy-occur-press))
2818 (setf (ivy-state-action ivy-occur-last) actions))))
2819
2820 (defun ivy-occur-click (event)
2821 "Execute action for the current candidate.
2822 EVENT gives the mouse position."
2823 (interactive "e")
2824 (let ((window (posn-window (event-end event)))
2825 (pos (posn-point (event-end event))))
2826 (with-current-buffer (window-buffer window)
2827 (goto-char pos)
2828 (ivy-occur-press))))
2829
2830 (declare-function swiper--cleanup "swiper")
2831 (declare-function swiper--add-overlays "swiper")
2832
2833 (defun ivy-occur-press ()
2834 "Execute action for the current candidate."
2835 (interactive)
2836 (when (save-excursion
2837 (beginning-of-line)
2838 (looking-at "\\(?:./\\| \\)\\(.*\\)$"))
2839 (let* ((ivy-last ivy-occur-last)
2840 (ivy-text (ivy-state-text ivy-last))
2841 (str (buffer-substring
2842 (match-beginning 1)
2843 (match-end 1)))
2844 (coll (ivy-state-collection ivy-last))
2845 (action (ivy--get-action ivy-last))
2846 (ivy-exit 'done))
2847 (with-ivy-window
2848 (funcall action
2849 (if (and (consp coll)
2850 (consp (car coll)))
2851 (cdr (assoc str coll))
2852 str))
2853 (if (memq (ivy-state-caller ivy-last)
2854 '(swiper counsel-git-grep))
2855 (with-current-buffer (window-buffer (selected-window))
2856 (swiper--cleanup)
2857 (swiper--add-overlays
2858 (ivy--regex ivy-text)
2859 (line-beginning-position)
2860 (line-end-position)
2861 (selected-window))
2862 (run-at-time 0.5 nil 'swiper--cleanup)))))))
2863
2864 (defvar ivy-help-file (let ((default-directory
2865 (if load-file-name
2866 (file-name-directory load-file-name)
2867 default-directory)))
2868 (if (file-exists-p "ivy-help.org")
2869 (expand-file-name "ivy-help.org")
2870 (if (file-exists-p "doc/ivy-help.org")
2871 (expand-file-name "doc/ivy-help.org"))))
2872 "The file for `ivy-help'.")
2873
2874 (defun ivy-help ()
2875 "Help for `ivy'."
2876 (interactive)
2877 (let ((buf (get-buffer "*Ivy Help*")))
2878 (unless buf
2879 (setq buf (get-buffer-create "*Ivy Help*"))
2880 (with-current-buffer buf
2881 (insert-file-contents ivy-help-file)
2882 (org-mode)
2883 (view-mode)
2884 (goto-char (point-min))))
2885 (if (eq this-command 'ivy-help)
2886 (switch-to-buffer buf)
2887 (with-ivy-window
2888 (pop-to-buffer buf)))
2889 (view-mode)
2890 (goto-char (point-min))))
2891
2892 (provide 'ivy)
2893
2894 ;;; ivy.el ends here