(ivy-mode 1)
(setq ivy-use-virtual-buffers t)
(global-set-key "\C-s" 'swiper)
- (global-set-key "\C-r" 'swiper)
(global-set-key (kbd "C-c C-r") 'ivy-resume)
- (global-set-key [f6] 'ivy-resume)
+ (global-set-key (kbd "<f6>") 'ivy-resume)
+ (global-set-key (kbd "M-x") 'counsel-M-x)
+ (global-set-key (kbd "C-x C-f") 'counsel-find-file)
+ (global-set-key (kbd "<f1> f") 'counsel-describe-function)
+ (global-set-key (kbd "<f1> v") 'counsel-describe-variable)
+ (global-set-key (kbd "<f1> l") 'counsel-load-library)
+ (global-set-key (kbd "<f2> i") 'counsel-info-lookup-symbol)
+ (global-set-key (kbd "<f2> u") 'counsel-unicode-char)
+ (global-set-key (kbd "C-c g") 'counsel-git)
+ (global-set-key (kbd "C-c j") 'counsel-git-grep)
+ (global-set-key (kbd "C-c k") 'counsel-ag)
+ (global-set-key (kbd "C-x l") 'counsel-locate)
+ (global-set-key (kbd "C-S-o") 'counsel-rhythmbox)
```
-
- ## Issues
-
- Recently, the `ivy` package that provided `ivy.el` was removed from MELPA. Now, the `swiper` package provides `ivy.el`. You should remove the outdated `ivy` package from your system.
C1 and C2 are triples of floats in [0.0 1.0] range."
(apply #'color-rgb-to-hex
(cl-mapcar
- colir-compose-method
+ (if (eq (frame-parameter nil 'background-mode) 'dark)
+ ;; this method works nicely for dark themes
+ 'colir-compose-soft-light
+ colir-compose-method)
c1 c2)))
(defun colir-blend-face-background (start end face &optional object)
(defun counsel-find-symbol ()
"Jump to the definition of the current symbol."
(interactive)
- (ivy-set-action #'counsel--find-symbol)
- (ivy-done))
+ (ivy-exit-with-action #'counsel--find-symbol))
(defun counsel--info-lookup-symbol ()
"Lookup the current symbol in the info docs."
(interactive)
- (ivy-set-action #'counsel-info-lookup-symbol)
- (ivy-done))
+ (ivy-exit-with-action #'counsel-info-lookup-symbol))
(defun counsel--find-symbol (x)
"Find symbol definition that corresponds to string X."
- (ring-insert find-tag-marker-ring (point-marker))
+ (with-no-warnings
+ (ring-insert find-tag-marker-ring (point-marker)))
(let ((full-name (get-text-property 0 'full-name x)))
(if full-name
(find-library full-name)
(let ((sym (read x)))
- (cond ((boundp sym)
+ (cond ((and (eq (ivy-state-caller ivy-last)
+ 'counsel-describe-variable)
+ (boundp sym))
(find-variable sym))
((fboundp sym)
(find-function sym))
+ ((boundp sym)
+ (find-variable sym))
((or (featurep sym)
(locate-library
(prin1-to-string sym)))
:sort t
:action (lambda (x)
(describe-variable
- (intern x))))))
+ (intern x)))
+ :caller 'counsel-describe-variable)))
(ivy-set-actions
'counsel-describe-variable
'(("i" counsel-info-lookup-symbol "info")
("d" counsel--find-symbol "definition")))
+ (ivy-set-actions
+ 'counsel-M-x
+ '(("d" counsel--find-symbol "definition")))
+
;;;###autoload
(defun counsel-describe-function ()
"Forward to `describe-function'."
:sort t
:action (lambda (x)
(describe-function
- (intern x))))))
+ (intern x)))
+ :caller 'counsel-describe-function)))
(defvar info-lookup-mode)
(declare-function info-lookup->completions "info-look")
"git ls-files --full-name --")
"\n"
t))
- (action (lambda (x) (find-file x))))
+ (action `(lambda (x)
+ (let ((default-directory ,default-directory))
+ (find-file x)))))
(ivy-read "Find file: " cands
:action action)))
(list ""
(format "%d chars more" (- n (length ivy-text)))))
+ (defvar counsel-git-grep-cmd "git --no-pager grep --full-name -n --no-color -i -e %S"
+ "Store the command for `counsel-git-grep'.")
+
(defun counsel-git-grep-function (string &optional _pred &rest _unused)
"Grep in the current git repository for STRING."
(if (and (> counsel--git-grep-count 20000)
(< (length string) 3))
(counsel-more-chars 3)
(let* ((default-directory counsel--git-grep-dir)
- (cmd (format "git --no-pager grep --full-name -n --no-color -i -e %S"
+ (cmd (format counsel-git-grep-cmd
(setq ivy--old-re (ivy--regex string t)))))
(if (<= counsel--git-grep-count 20000)
(split-string (shell-command-to-string cmd) "\n" t)
(defvar counsel-git-grep-map
(let ((map (make-sparse-keymap)))
(define-key map (kbd "C-l") 'counsel-git-grep-recenter)
+ (define-key map (kbd "M-q") 'counsel-git-grep-query-replace)
map))
+ (defun counsel-git-grep-query-replace ()
+ "Start `query-replace' with string to replace from last search string."
+ (interactive)
+ (if (null (window-minibuffer-p))
+ (user-error
+ "Should only be called in the minibuffer through `counsel-git-grep-map'")
+ (let* ((enable-recursive-minibuffers t)
+ (from (ivy--regex ivy-text))
+ (to (query-replace-read-to from "Query replace" t)))
+ (ivy-exit-with-action
+ (lambda (_)
+ (let (done-buffers)
+ (dolist (cand ivy--old-cands)
+ (when (string-match "\\`\\(.*?\\):\\([0-9]+\\):\\(.*\\)\\'" cand)
+ (with-ivy-window
+ (let ((file-name (match-string-no-properties 1 cand)))
+ (setq file-name (expand-file-name file-name counsel--git-grep-dir))
+ (unless (member file-name done-buffers)
+ (push file-name done-buffers)
+ (find-file file-name)
+ (goto-char (point-min)))
+ (perform-replace from to t t nil)))))))))))
+
(defun counsel-git-grep-recenter ()
(interactive)
(with-ivy-window
(defvar counsel-git-grep-history nil
"History for `counsel-git-grep'.")
+ (defvar counsel-git-grep-cmd-history
+ '("git --no-pager grep --full-name -n --no-color -i -e %S")
+ "History for `counsel-git-grep' shell commands.")
+
;;;###autoload
- (defun counsel-git-grep (&optional initial-input)
+ (defun counsel-git-grep (&optional cmd initial-input)
"Grep for a string in the current git repository.
+ When CMD is a string, use it as a \"git grep\" command.
+ When CMD is non-nil, prompt for a specific \"git grep\" command.
INITIAL-INPUT can be given as the initial minibuffer input."
- (interactive)
+ (interactive "P")
+ (cond
+ ((stringp cmd)
+ (setq counsel-git-grep-cmd cmd))
+ (cmd
+ (setq counsel-git-grep-cmd
+ (ivy-read "cmd: " counsel-git-grep-cmd-history
+ :history 'counsel-git-grep-cmd-history))
+ (setq counsel-git-grep-cmd-history
+ (delete-dups counsel-git-grep-cmd-history)))
+ (t
+ (setq counsel-git-grep-cmd "git --no-pager grep --full-name -n --no-color -i -e %S")))
(setq counsel--git-grep-dir
(locate-dominating-file default-directory ".git"))
(if (null counsel--git-grep-dir)
:keymap counsel-git-grep-map
:action #'counsel-git-grep-action
:unwind #'swiper--cleanup
- :history 'counsel-git-grep-history)))
+ :history 'counsel-git-grep-history
+ :caller 'counsel-git-grep)))
(defcustom counsel-find-file-at-point nil
"When non-nil, add file-at-point to the list of candidates."
candidates))
(setq ivy--old-re regexp))))
+ (defvar counsel--async-time nil
+ "Store the time when a new process was started.
+ Or the time of the last minibuffer update.")
+
(defun counsel--async-command (cmd)
(let* ((counsel--process " *counsel*")
(proc (get-process counsel--process))
counsel--process
counsel--process
cmd))
- (set-process-sentinel proc #'counsel--async-sentinel)))
+ (setq counsel--async-time (current-time))
+ (set-process-sentinel proc #'counsel--async-sentinel)
+ (set-process-filter proc #'counsel--async-filter)))
(defun counsel--async-sentinel (process event)
(if (string= event "finished\n")
(setq ivy--all-candidates
(ivy--sort-maybe
(split-string (buffer-string) "\n" t)))
+ (if (null ivy--old-cands)
+ (setq ivy--index
+ (or (ivy--preselect-index
+ (ivy-state-preselect ivy-last)
+ ivy--all-candidates)
+ 0))
+ (ivy--recompute-index
+ ivy-text
+ (funcall ivy--regex-function ivy-text)
+ ivy--all-candidates))
(setq ivy--old-cands ivy--all-candidates))
(ivy--exhibit))
(if (string= event "exited abnormally with code 1\n")
(setq ivy--old-cands ivy--all-candidates)
(ivy--exhibit)))))
+ (defun counsel--async-filter (process str)
+ "Receive from PROCESS the output STR.
+ Update the minibuffer with the amount of lines collected every
+ 0.5 seconds since the last update."
+ (with-current-buffer (process-buffer process)
+ (insert str))
+ (let (size)
+ (when (time-less-p
+ ;; 0.5s
+ '(0 0 500000 0)
+ (time-since counsel--async-time))
+ (with-current-buffer (process-buffer process)
+ (goto-char (point-min))
+ (setq size (- (buffer-size) (forward-line (buffer-size)))))
+ (ivy--insert-minibuffer
+ (format "\ncollected: %d" size))
+ (setq counsel--async-time (current-time)))))
+
(defun counsel-locate-action-extern (x)
"Use xdg-open shell command on X."
(call-process shell-file-name nil
(ivy--regex str))))
'("" "working...")))
+ (defun counsel-delete-process ()
+ (let ((process (get-process " *counsel*")))
+ (when process
+ (delete-process process))))
+
;;;###autoload
- (defun counsel-locate ()
- "Call locate shell command."
+ (defun counsel-locate (&optional initial-input)
+ "Call the \"locate\" shell command.
+ INITIAL-INPUT can be given as the initial minibuffer input."
(interactive)
(ivy-read "Locate: " #'counsel-locate-function
+ :initial-input initial-input
:dynamic-collection t
:history 'counsel-locate-history
:action (lambda (file)
- (when file
- (find-file file)))))
+ (with-ivy-window
+ (when file
+ (find-file file))))
+ :unwind #'counsel-delete-process))
(defun counsel--generic (completion-fn)
"Complete thing at point with COMPLETION-FN."
(setq proc (start-process-shell-command
counsel-gg-process
counsel-gg-process
- (format "git --no-pager grep --full-name -n --no-color -i -e %S | head -n 200"
- regex)))
+ (concat
+ (format counsel-git-grep-cmd regex)
+ " | head -n 200")))
(set-process-sentinel
proc
#'counsel--gg-sentinel)))
(if (string= event "finished\n")
(progn
(with-current-buffer (process-buffer process)
- (setq ivy--all-candidates (split-string (buffer-string) "\n" t))
+ (setq ivy--all-candidates
+ (or (split-string (buffer-string) "\n" t)
+ '("")))
(setq ivy--old-cands ivy--all-candidates))
(when (= 0 (cl-incf counsel-gg-state))
(ivy--exhibit)))
"Quickly and asynchronously count the amount of git grep REGEX matches.
When NO-ASYNC is non-nil, do it synchronously."
(let ((default-directory counsel--git-grep-dir)
- (cmd (format "git grep -i -c '%s' | sed 's/.*:\\(.*\\)/\\1/g' | awk '{s+=$1} END {print s}'"
- regex))
+ (cmd
+ (concat
+ (format
+ (replace-regexp-in-string
+ "--full-name" "-c"
+ counsel-git-grep-cmd)
+ ;; "git grep -i -c '%s'"
+ (replace-regexp-in-string
+ "-" "\\\\-"
+ (replace-regexp-in-string "'" "''" regex)))
+ " | sed 's/.*:\\(.*\\)/\\1/g' | awk '{s+=$1} END {print s}'"))
(counsel-ggc-process " *counsel-gg-count*"))
(if no-async
(string-to-number (shell-command-to-string cmd))
(when (= 0 (cl-incf counsel-gg-state))
(ivy--exhibit)))))))))
- (defun counsel--M-x-transformer (cmd)
- "Add a binding to CMD if it's bound in the current window.
- CMD is a command name."
- (let ((binding (substitute-command-keys (format "\\[%s]" cmd))))
+ (defun counsel--M-x-transformer (cand-pair)
+ "Add a binding to CAND-PAIR cdr if the car is bound in the current window.
+ CAND-PAIR is (command-name . extra-info)."
+ (let* ((command-name (car cand-pair))
+ (extra-info (cdr cand-pair))
+ (binding (substitute-command-keys (format "\\[%s]" command-name))))
(setq binding (replace-regexp-in-string "C-x 6" "<f2>" binding))
(if (string-match "^M-x" binding)
- cmd
- (format "%s (%s)" cmd
- (propertize binding 'face 'font-lock-keyword-face)))))
+ cand-pair
+ (cons command-name
+ (if extra-info
+ (format " %s (%s)" extra-info (propertize binding 'face 'font-lock-keyword-face))
+ (format " (%s)" (propertize binding 'face 'font-lock-keyword-face)))))))
(defvar smex-initialized-p)
(defvar smex-ido-cache)
(declare-function smex-update "ext:smex")
(declare-function smex-rank "ext:smex")
+ (defun counsel--M-x-prompt ()
+ "M-x plus the string representation of `current-prefix-arg'."
+ (if (not current-prefix-arg)
+ "M-x "
+ (concat
+ (if (eq current-prefix-arg '-)
+ "- "
+ (if (integerp current-prefix-arg)
+ (format "%d " current-prefix-arg)
+ (if (= (car current-prefix-arg) 4)
+ "C-u "
+ (format "%d " (car current-prefix-arg)))))
+ "M-x ")))
+
;;;###autoload
(defun counsel-M-x (&optional initial-input)
"Ivy version of `execute-extended-command'.
ivy-initial-inputs-alist))))
(let* ((store ivy-format-function)
(ivy-format-function
- (lambda (cands)
+ (lambda (cand-pairs)
(funcall
store
(with-ivy-window
- (mapcar #'counsel--M-x-transformer cands)))))
+ (mapcar #'counsel--M-x-transformer cand-pairs)))))
(cands obarray)
(pred 'commandp)
(sort t))
(setq cands smex-ido-cache)
(setq pred nil)
(setq sort nil))
- (ivy-read "M-x " cands
+ (ivy-read (counsel--M-x-prompt) cands
:predicate pred
:require-match t
:history 'extended-command-history
(lambda (cmd)
(when (featurep 'smex)
(smex-rank (intern cmd)))
- (let ((prefix-arg current-prefix-arg))
+ (let ((prefix-arg current-prefix-arg)
+ (ivy-format-function store))
(command-execute (intern cmd) 'record)))
:sort sort
:keymap counsel-describe-map
- :initial-input initial-input)))
+ :initial-input initial-input
+ :caller 'counsel-M-x)))
(declare-function powerline-reset "ext:powerline")
:action
'(1
("p" helm-rhythmbox-play-song "Play song")
- ("e" counsel-rhythmbox-enqueue-song "Enqueue song"))))
+ ("e" counsel-rhythmbox-enqueue-song "Enqueue song"))
+ :caller 'counsel-rhythmbox))
(defvar counsel-org-tags nil
"Store the current list of tags.")
(defvar org-indent-indentation-per-level)
(defvar org-tags-column)
(declare-function org-get-tags-string "org")
- (declare-function org-move-to-column "org")
+ (declare-function org-move-to-column "org-compat")
(defun counsel-org-change-tags (tags)
(let ((current (org-get-tags-string))
"Grep in the current directory for STRING."
(if (< (length string) 3)
(counsel-more-chars 3)
- (let ((regex (counsel-unquote-regex-parens
+ (let ((default-directory counsel--git-grep-dir)
+ (regex (counsel-unquote-regex-parens
(setq ivy--old-re
(ivy--regex string)))))
(counsel--async-command
- (format "ag --noheading --nocolor %S" regex))
+ (format "ag --vimgrep %S" regex))
nil)))
- (defun counsel-ag (&optional initial-input)
+ ;;;###autoload
+ (defun counsel-ag (&optional initial-input initial-directory)
"Grep for a string in the current directory using ag.
INITIAL-INPUT can be given as the initial minibuffer input."
(interactive)
- (setq counsel--git-grep-dir default-directory)
+ (setq counsel--git-grep-dir (or initial-directory default-directory))
(ivy-read "ag: " 'counsel-ag-function
:initial-input initial-input
:dynamic-collection t
:history 'counsel-git-grep-history
:action #'counsel-git-grep-action
- :unwind #'swiper--cleanup))
+ :unwind (lambda ()
+ (counsel-delete-process)
+ (swiper--cleanup))))
+
+ ;;;###autoload
+ (defun counsel-grep ()
+ "Grep for a string in the current file."
+ (interactive)
+ (setq counsel--git-grep-dir (buffer-file-name))
+ (ivy-read "grep: " 'counsel-grep-function
+ :dynamic-collection t
+ :preselect (format "%d:%s"
+ (line-number-at-pos)
+ (buffer-substring-no-properties
+ (line-beginning-position)
+ (line-end-position)))
+ :history 'counsel-git-grep-history
+ :update-fn (lambda ()
+ (counsel-grep-action ivy--current))
+ :action #'counsel-grep-action
+ :unwind (lambda ()
+ (counsel-delete-process)
+ (swiper--cleanup))
+ :caller 'counsel-grep))
+
+ (defun counsel-grep-function (string &optional _pred &rest _unused)
+ "Grep in the current directory for STRING."
+ (if (< (length string) 3)
+ (counsel-more-chars 3)
+ (let ((regex (counsel-unquote-regex-parens
+ (setq ivy--old-re
+ (ivy--regex string)))))
+ (counsel--async-command
+ (format "grep -nP --ignore-case '%s' %s" regex counsel--git-grep-dir))
+ nil)))
+
+ (defun counsel-grep-action (x)
+ (when (string-match "\\`\\([0-9]+\\):\\(.*\\)\\'" x)
+ (with-ivy-window
+ (let ((file-name counsel--git-grep-dir)
+ (line-number (match-string-no-properties 1 x)))
+ (find-file file-name)
+ (goto-char (point-min))
+ (forward-line (1- (string-to-number line-number)))
+ (re-search-forward (ivy--regex ivy-text t) (line-end-position) t)
+ (unless (eq ivy-exit 'done)
+ (swiper--cleanup)
+ (swiper--add-overlays (ivy--regex ivy-text)))))))
(defun counsel-recoll-function (string &optional _pred &rest _unused)
"Grep in the current directory for STRING."
(unless (string-match "pdf$" x)
(swiper ivy-text)))))))
+ (defvar tmm-km-list nil)
+ (declare-function tmm-get-keymap "tmm")
+ (declare-function tmm--completion-table "tmm")
+ (declare-function tmm-get-keybind "tmm")
+
+ (defun counsel-tmm-prompt (menu)
+ "Select and call an item from the MENU keymap."
+ (let (out
+ choice
+ chosen-string)
+ (setq tmm-km-list nil)
+ (map-keymap (lambda (k v) (tmm-get-keymap (cons k v))) menu)
+ (setq tmm-km-list (nreverse tmm-km-list))
+ (setq out (ivy-read "Menu bar: " (tmm--completion-table tmm-km-list)
+ :require-match t
+ :sort nil))
+ (setq choice (cdr (assoc out tmm-km-list)))
+ (setq chosen-string (car choice))
+ (setq choice (cdr choice))
+ (cond ((keymapp choice)
+ (counsel-tmm-prompt choice))
+ ((and choice chosen-string)
+ (setq last-command-event chosen-string)
+ (call-interactively choice)))))
+
+ (defun counsel-tmm ()
+ "Text-mode emulation of looking and choosing from a menubar."
+ (interactive)
+ (require 'tmm)
+ (run-hooks 'menu-bar-update-hook)
+ (counsel-tmm-prompt (tmm-get-keybind [menu-bar])))
+
(defcustom counsel-yank-pop-truncate nil
"When non-nil, truncate the display of long strings."
:group 'ivy)
#+end_src
See [[https://github.com/abo-abo/swiper/pull/167][#167]].
- You can also set this to nil, if you don't want any count, see [[https://github.com/abo-abo/swiper/pull/188][#188]].
+ You can also set this to "", if you don't want any count, see [[https://github.com/abo-abo/swiper/pull/188][#188]].
**** Allow to add additional exit points for any command
Example for =ivy-switch-to-buffer=:
#+begin_src elisp
candidate, but the current text. Bound to ~C-M-j~ or ~C-u C-j~.
See [[https://github.com/abo-abo/swiper/pull/183][#183]].
+
+ * 0.7.0
+ ** Fixes
+ *** Fix :dynamic-collection not being sorted
+ *** When :initial-input contains a plus, escape it
+ See [[https://github.com/abo-abo/swiper/issues/195][#195]].
+ *** Set line-spacing to 0 in the minibuffer
+ See [[https://github.com/abo-abo/swiper/issues/198][#198]].
+ *** Enlarge the minibuffer window if the candidate list doesn't fit
+ See [[https://github.com/abo-abo/swiper/issues/198][#198]] and [[https://github.com/abo-abo/swiper/issues/161][#161]] and [[https://github.com/abo-abo/swiper/issues/220][#220]].
+ *** Fix minibuffer collapsing to one line
+ See [[https://github.com/abo-abo/swiper/issues/237][#237]], [[https://github.com/abo-abo/swiper/issues/229][#229]] and [[https://github.com/abo-abo/swiper/issues/77][#77]].
+ *** Use minibuffer-allow-text-properties
+ Allows =ivy-read= to return a propertized string.
+ *** Improve ~C-g~ out of a long-running async process
+ Use =counsel-delete-process= as =:unwind=.
+ *** Don't regexp-quote :preselect
+ See [[https://github.com/abo-abo/swiper/issues/245][#245]].
+ *** Fix ivy-partial for fuzzy completion
+ See [[https://github.com/abo-abo/swiper/issues/266][#266]].
+ *** ivy-resume should pass :caller
+ See [[https://github.com/abo-abo/swiper/issues/245][#245]].
+ *** Fix the regression in perfect match logic
+ See [[https://github.com/abo-abo/swiper/issues/270][#270]].
+ *** Fix pasting file paths on Windows
+ *** ~C-j~ should no stop completion for a pasted file path
+ *** ~C-M-j~ should use =ivy--directory=
+ When completing file names, expand the file name properly.
+ See [[https://github.com/abo-abo/swiper/issues/275][#275]].
+ *** Use a specific blend method for dark themes
+ See [[https://github.com/abo-abo/swiper/issues/278][#278]].
+ *** Fix one-off bug in =ivy-scroll-up-command= and =ivy-scroll-down-command=
+ *** ~M-o~ shouldn't set the action permanently
+ So now it's possible to e.g. =counsel-describe-function= -> ~M-o d~ ->
+ =ivy-resume= -> ~M-o o~ -> =ivy-resume= -> ~M-o i~.
+ *** Fix swiper preselect issue with similar or identical lines
+ See [[https://github.com/abo-abo/swiper/issues/290][#290]].
+ *** Make ivy-completing-read handle history as cons
+ See [[https://github.com/abo-abo/swiper/issues/295][#295]].
+ *** Perform string-match in the original buffer
+ The syntax for whitespace, separators etc. is different for modes. See [[https://github.com/abo-abo/swiper/issues/298][#298]].
+ ** New Features
+ *** =swiper=
+ **** Make line numbers into display properties
+ Each candidate is now a single space plus the original string. The
+ display property of the single space holds the line number. This means
+ that it's no longer possible to match line numbers in queries, which
+ is a good thing if you're searching for numbers.
+ **** Extend =swiper-font-lock-ensure=
+ Add =mu4e-view-mode=, =mu4e-headers-mode=, =help-mode=,
+ =elfeed-show-mode=, =emms-stream-mode=, =debbugs-gnu-mode=,
+ =occur-mode=, =occur-edit-mode=, =bongo-mode=, =eww-mode=, =vc-dir-mode=.
+ **** Add support for =evil-jumper/backward=
+ See [[https://github.com/abo-abo/swiper/issues/268][#268]].
+ **** Make compatible with =visual-line-mode=
+ =swiper= will split the lines when =visual-line-mode= is on. This is
+ convenient for small buffers. For large buffers, it can be very slow,
+ since =visual-line-mode= is slow.
+ See [[https://github.com/abo-abo/swiper/issues/227][#227]].
+ **** Add =swiper-toggle-face-matching=
+ Bound to ~C-c C-f~.
+ At each start of =swiper=, the face at point will be stored.
+ Use this command to toggle matching only the candidates with that face.
+ See [[https://github.com/abo-abo/swiper/issues/288][#288]].
+ **** =push-mark= only if exited the minibuffer
+ ~C-M-n~ and ~C-M-p~ will no longer push mark and annoy with messages.
+ **** =ivy-resume= should restore the buffer for =swiper=
+ See [[https://github.com/abo-abo/swiper/issues/302][#302]].
+ **** Enable recursive =swiper= calls
+ While you =swiper= buffer-1, you can switch out of the minibuffer into
+ buffer-2 and call =swiper= again. Exiting the second minibuffer will
+ restore the first minibuffer.
+
+ To use this, you need to enable recursive minibuffers.
+ #+begin_src elisp
+ (setq enable-recursive-minibuffers t)
+ #+end_src
+
+ It's also useful to indicate the current depth:
+
+ #+begin_src elisp
+ (minibuffer-depth-indicate-mode 1)
+ #+end_src
+
+ See [[https://github.com/abo-abo/swiper/issues/309][#309]].
+ **** Fix for =twittering-mode=
+ The =field= text property is now removed before inserting text into
+ the minibuffer. This fixes the =swiper= problems with
+ =twittering-mode=. See [[https://github.com/abo-abo/swiper/issues/310][#310]].
+
+
+
+
+ *** =ivy=
+ **** Add manual
+ In the current state, the manual covers the most basic topics, like
+ the minibuffer key bindings and the regexp builders.
+ **** Make <left> and <right> behave as in fundamental-mode
+ **** Truncate minibuffer prompts longer than window-width
+ See [[https://github.com/abo-abo/swiper/issues/240][#240]].
+ **** ~C-M-n~ should not leave the minibuffer
+ Make sure that the minibuffer window remains selected as long as the
+ completion hasn't finished. For example, ~<f1> f~ to call
+ =counsel-describe-function=, input "forward" and spam ~C-M-n~ to read
+ the doc for each function that starts with "forward". The =*Help*=
+ window popup would move the window focus, but this change moves it
+ back to the minibuffer.
+ **** Add =flx= sorting
+ See [[https://github.com/abo-abo/swiper/issues/207][#207]].
+ Since flx is costly, move the caching to an earlier point. This means
+ immediate return for when the input hasn't changed, i.e. for ~C-n~ or
+ ~C-p~. When =flx= is installed, and =(eq ivy--regex-function 'ivy--regex-fuzzy)=
+ for current function (through =ivy-re-builders-alist=), then sort the final candidates with
+ =ivy--flx-sort=.
+
+ In the worst case, when some error pops up, return the same list. In
+ the best case sort the =cands= that all match =name= by closeness to
+ =name=.
+
+ How to use:
+ 1. Have =flx= installed - =(require 'flx)= should succeed.
+ 2. Configure =ivy-re-builders-alist= appropriately to use =ivy--regex-fuzzy=.
+
+ For example:
+
+ #+begin_src elisp
+ (setq ivy-re-builders-alist
+ '((t . ivy--regex-fuzzy)))
+ #+end_src
+ **** Support hash tables
+ Since =all-completions= also works for hash tables, no reason not to support them.
+ **** Improve documentation of =ivy-count-format=
+ Now possible to set it with Customize.
+ **** Add =ivy-index-functions-alist=
+ Customize this to decide how the index, i.e. the currently selected
+ candidate, is updated with new input.
+ For example, one strategy is not reset it to 0 after each change.
+
+ Another strategy, used for =swiper=, is to try to select the first
+ appropriate candidate after (inclusive) the first previously selected
+ candidate. This way, if you're typing something that matches what is
+ currently selected, the selection won't change.
+
+ See [[https://github.com/abo-abo/swiper/issues/253][#253]].
+ **** Add =ivy-virtual-abbreviate=
+ The mode of abbreviation for virtual buffer names.
+ **** Add =ivy-case-fold-search=
+ Used to override =case-fold-search=. See [[https://github.com/abo-abo/swiper/issues/259][#259]].
+ **** Add feedback for long-running async processes
+ Each time 0.5s pass after the last input, if the external process
+ hasn't finished yet, update minibuffer with the amount of candidates
+ collected so far. This is useful to see that long running commands
+ like =counsel-locate= or =counsel-ag= (when in a very large directory)
+ aren't stuck.
+ **** Promote =ivy-extra-directories= to defcustom
+ **** Promote =ivy-sort-function-alist= to defcustom
+ **** ~M-n~ should prefer url at point to symbol at point
+ **** ~C-x C-f M-n~ calls =ffap-url-fetcher= when at URL
+ **** Highlight modified file buffers with =ivy-modified-buffer= face
+ This new face is blank by default, but you can use e.g.:
+ #+begin_src elisp
+ (custom-set-faces
+ '(ivy-modified-buffer ((t (:background "#ff7777")))))
+ #+end_src
+ **** Work with =enable-recursive-minibuffers=
+ Store the old =ivy-last= in case =ivy-read= is called while inside the
+ minibuffer. Restore it after =ivy-call=.
+ **** Allow user-specified matched candidate sorting
+ New defcustom =ivy-sort-matches-functions-alist=.
+ See [[https://github.com/abo-abo/swiper/issues/269][#269]] [[https://github.com/abo-abo/swiper/issues/265][#265]] [[https://github.com/abo-abo/swiper/issues/213][#213]].
+
+ By default, Ivy doesn't sort the matched candidates, they remain in
+ the same order as in the original collection. This option is the
+ default, since it's fast and simple.
+
+ A small problem with this approach is that we usually want prefix
+ matches to be displayed first. One solution to this is to input "^" to
+ see only the prefix matches.
+
+ Now, another solution is to can set:
+ #+begin_src elisp
+ (setq ivy-sort-matches-functions-alist
+ '((t . ivy--prefix-sort)))
+ #+end_src
+
+ Here's another example of using this defcustom:
+ #+begin_src elisp
+ (add-to-list
+ 'ivy-sort-matches-functions-alist
+ '(read-file-name-internal . ivy--sort-files-by-date))
+ #+end_src
+
+ After this, during file name completion, most recently changed files
+ will be ahead.
+ **** =ivy-display-style=
+ Adds fancy highlighting to the minibuffer.
+ See [[https://github.com/abo-abo/swiper/issues/212][#212]], [[https://github.com/abo-abo/swiper/issues/217][#217]], .
+ *** =ivy-hydra=
+ **** Bind ~t~ to =toggle-truncate-lines=
+ See [[https://github.com/abo-abo/swiper/issues/214][#214]].
+ **** Bind ~a~ to =ivy-read-action=
+ *** =ivy-switch-buffer=
+ **** Make ~M-o r~ rename the buffer instead of switching.
+ See [[https://github.com/abo-abo/swiper/issues/233][#233]].
+ *** =counsel-locate=
+ **** Allow customizing locate options
+ See =counsel-locate-options=.
+ The current setting is:
+ #+begin_src elisp
+ (setq counsel-locate-options '("-i" "--regex"))
+ #+end_src
+ **** Support OSX
+ Use =open= instead of =xdg-open=. Modify =counsel-locate-options= for
+ OSX, since there =locate= doesn't support =--regex=.
+ **** Use single quotes for the regex
+ See [[https://github.com/abo-abo/swiper/issues/194][#194]].
+ **** Add initial-input argument
+ See [[https://github.com/abo-abo/swiper/issues/289][#289]].
+ *** =counsel-org-tag=
+ **** Now works in agenda
+ See [[https://github.com/abo-abo/swiper/issues/200][#200]].
+ *** =counsel-unicode-char=
+ **** Add own history
+ *** =counsel-M-x=
+ **** Add "definition" action
+ Use ~M-o d~ to jump to definition.
+ **** Show =current-prefix-arg= in the prompt
+ See [[https://github.com/abo-abo/swiper/issues/287][#287]].
+ *** =counsel-find-file=
+ **** Input '/sudo::' goes to current directory instead of root's home
+ See [[https://github.com/abo-abo/swiper/issues/283][#283]].
+ **** Fix directory validity check
+ See [[https://github.com/abo-abo/swiper/issues/283][#283]] [[https://github.com/abo-abo/swiper/issues/284][#284]].
+ **** Improve TRAMP support
+ Selecting items after ~//~ now works properly.
+ *** =counsel-git-grep=
+ **** Use prefix arg to specify the shell command.
+ Remember to use ~M-i~ to insert the current candidate into the
+ minibuffer.
+
+ See [[https://github.com/abo-abo/swiper/issues/244][#244]].
+ **** Allow =counsel-git-grep= -> =ivy-occur= -> =wgrep=
+ Using ~C-c C-o~ (=ivy-occur=) while in =counsel-git-grep= will produce
+ a =wgrep=-compatible buffer.
+ **** =ivy-occur= gives full candidates
+ This means that the =" | head -n 200"= speed-up isn't used and full
+ candidates are returned.
+ *** =counsel--find-symbol=
+ **** Allow to jump back with pop-tag-mark
+ Using ~C-.~ in:
+
+ - =counsel-describe-function=
+ - =counsel-describe-variable=
+ - =counsel-load-library=
+
+ will change the current buffer. The buffer and point can be restored
+ with ~M-*~ (=pop-tag-mark=).
+
+ I also recommend this binding:
+
+ #+begin_src elisp
+ (global-set-key (kbd "M-,") 'pop-tag-mark)
+ #+end_src
+ **** Resolve the name clash better
+ When the symbol is both bound and fbound, prefer the fbound one,
+ unless the =:caller= is =counsel-describe-variable=.
+ *** =counsel-ag=
+ **** Add =initial-directory=
+ Support alternative initial directory which helps other packages call
+ this function with their unique starting directory.
+ **** Fix on Windows
+ Using the "--vimgrep" argument improves things.
+ ** New Commands
+ *** =ivy-occur=
+ Bound to ~C-c C-o~. Store the current completion session to its own
+ buffer. You can have an unlimited amount of these buffers.
+ *** =ivy-avy=
+ Bound to ~C-'~.
+
+ Speeds up selecting a candidate that's currently visible in the minibuffer.
+ *** =ivy-kill-ring-save=
+ Bound to ~M-w~.
+
+ When the region is active, call =kill-ring-save=. Otherwise, store
+ all selected candidates to the kill ring.
+ *** =ivy-dispatching-call=
+ Bound to ~C-M-o~.
+
+ This is a non-exiting version of ~M-o~ (=ivy-dispatching-done=).
+ *** =ivy-read-action=
+ Bound to ~C-M-a~. Select the current action. Don't call it yet.
+ *** =swiper-multi=
+ Use =swiper= in multiple buffers.
+ See [[https://github.com/abo-abo/swiper/issues/182][#182]].
+
+ Basic usage tips for selecting multiple buffers:
+
+ - Use ~C-M-m~ (=ivy-call=) to add or remove one more buffer without exiting.
+ - Use ~C-m~ (=ivy-done=) to add one last buffer.
+ - Or use ~C-M-j~ (=ivy-immediate-done=) to finish without adding more buffers.
+ - Hold ~C-M-n~ (=ivy-next-line-and-call=) to add a lot of buffers at once.
+ *** =swiper-mc=
+ Open multiple cursors at all selected candidates.
+ *** =swiper-all=
+ New command to launch =swiper= for all open file buffers. Note that
+ this can be excruciatingly slow if you don't clean up your buffer list
+ often.
+ *** =counsel-grep=
+ This is essentially =swiper= for huge files. It's not as smooth as
+ =swiper= for small files, but has a faster startup and faster matching
+ for files that measure in megabytes.
+ *** =counsel-git-grep-query-replace=
+ Bound to ~M-q~. Perform =query-replace= on all matches in all buffers.
+ *** =counsel-jedi=
+ Complete Python symbols using Jedi.
+ *** =counsel-cl=
+ Complete Common Lisp symbols using SLIME.
+ *** =counsel-yank-pop=
+ Give completion for inserting from the kill ring.
+ See =counsel-yank-pop-truncate= defcustom and [[https://github.com/abo-abo/swiper/issues/218][#218]].
--- /dev/null
+ #+TITLE: Ivy User Manual
+ #+AUTHOR: Oleh Krehel
+ #+EMAIL: ohwoeowho@gmail.com
+ #+DATE: 2015
+ #+LANGUAGE: en
+
+ #+TEXINFO_DIR_CATEGORY: Emacs
+ #+TEXINFO_DIR_TITLE: Ivy: (ivy).
+ #+TEXINFO_DIR_DESC: Using Ivy for completion.
+ #+HTML_HEAD: <link rel="stylesheet" type="text/css" href="style.css"/>
+
+ #+OPTIONS: H:6 num:6 toc:4
+ #+STARTUP: indent
+ * Macros :noexport:
+ #+MACRO: defopt #+TEXINFO: @defopt $1
+ #+MACRO: endopt #+TEXINFO: @end defopt
+ * Copying
+ :PROPERTIES:
+ :COPYING: t
+ :END:
+
+ #+BEGIN_TEXINFO
+ @ifnottex
+ Ivy manual, version 0.7.0
+
+ Ivy is an interactive interface for completion in Emacs. Emacs uses
+ completion mechanism in a variety of contexts: code, menus, commands,
+ variables, functions, etc. Completion entails listing, sorting,
+ filtering, previewing, and applying actions on selected items. When
+ active, @code{ivy-mode} completes the selection process by narrowing
+ available choices while previewing in the minibuffer. Selecting the
+ final candidate is either through simple keyboard character inputs or
+ through powerful regular expressions. @end ifnottex
+
+ Copyright @copyright{} 2015 Free Software Foundation, Inc.
+
+ @quotation
+ Permission is granted to copy, distribute and/or modify this document
+ under the terms of the GNU Free Documentation License, Version 1.3 or
+ any later version published by the Free Software Foundation; with no
+ Invariant Sections, with the Front-Cover Texts being ``A GNU Manual,''
+ and with the Back-Cover Texts as in (a) below. A copy of the license
+ is included in the section entitled ``GNU Free Documentation License.''
+
+ (a) The FSF's Back-Cover Text is: ``You have the freedom to copy and
+ modify this GNU manual.''
+ @end quotation
+ #+END_TEXINFO
+
+ * Introduction
+ Ivy is for quick and easy selection from a list. When Emacs prompts
+ for a string from a list of several possible choices, Ivy springs into
+ action to assist in narrowing and picking the right string from a vast
+ number of choices.
+
+ Ivy strives for minimalism, simplicity, customizability and
+ discoverability.
+
+ #+BEGIN_TEXINFO
+ @subsubheading Minimalism
+ #+END_TEXINFO
+ Uncluttered minibuffer is minimalism. Ivy shows the completion
+ defaults, the number of matches, and 10 candidate matches below the
+ input line. Customize =ivy-length= to adjust the number of candidate
+ matches displayed in the minibuffer.
+
+ #+BEGIN_TEXINFO
+ @subsubheading Simplicity
+ #+END_TEXINFO
+ Simplicity is about Ivy's behavior in the minibuffer. It is also about
+ the code interface to extend Ivy's functionality. The minibuffer area
+ behaves as close to =fundamental-mode= as possible. ~SPC~ inserts a
+ space, for example, instead of being bound to the more complex
+ =minibuffer-complete-word=. Ivy's code uses easy-to-examine global
+ variables; avoids needless complications with branch-introducing
+ custom macros.
+
+ #+BEGIN_TEXINFO
+ @subsubheading Customizability
+ #+END_TEXINFO
+ Customizability is about being able to use different methods and
+ interfaces of completion to tailor the selection process. For example,
+ adding a custom display function that points to a selected candidate
+ with =->=, instead of highlighting the selected candidate with the
+ =ivy-current-match= face. Or take the customization of actions, say
+ after the candidate function is selected. ~RET~ uses
+ =counsel-describe-function= to describe the function, whereas ~M-o d~
+ jumps to that function's definition in the code. The ~M-o~ prefix can
+ be uniformly used with characters like ~d~ to group similar actions.
+
+ #+BEGIN_TEXINFO
+ @subsubheading Discoverability
+ #+END_TEXINFO
+ Ivy displays easily discoverable commands through the hydra facility.
+ ~C-o~ in the minibuffer displays a hydra menu. It opens up within an
+ expanded minibuffer area. Each menu item comes with short
+ documentation strings and highlighted one-key completions. So
+ discovering even seldom used keys is simply a matter of ~C-o~ in the
+ minibuffer while in the midst of the Ivy interaction. This
+ discoverability minimizes exiting Ivy interface for documentation
+ look-ups.
+
+ * Installation
+
+ Install Ivy automatically through Emacs's package manager, or manually
+ from Ivy's development repository.
+
+ ** Installing from Emacs Package Manager
+
+ ~M-x~ =package-install= ~RET~ =swiper= ~RET~
+
+ Ivy is installed as part of =swiper= package. =swiper= is available
+ from two different package archives, GNU ELPA and MELPA. For the
+ latest stable version, use the GNU ELPA archives using the above M-x
+ command.
+
+ For current hourly builds, use the MELPA archives. See the code below
+ for adding MELPA to the list of package archives:
+
+ #+begin_src elisp
+ (require 'package)
+ (add-to-list 'package-archives
+ '("melpa" . "http://melpa.org/packages/"))
+ #+end_src
+
+ After this do ~M-x~ =package-refresh-contents= ~RET~, followed by
+ ~M-x~ =package-install= ~RET~ =swiper= ~RET~.
+
+ For package manager details, see [[info:emacs#Packages]].
+
+ ** Installing from the Git repository
+
+ Why install from Git?
+
+ - No need to wait for MELPA's hourly builds
+ - Easy to revert to previous versions
+ - Contribute to Ivy's development; send patches; pull requests
+
+ *Configuration steps*
+
+ First clone the Swiper repository:
+ #+begin_src sh
+ cd ~/git && git clone https://github.com/abo-abo/swiper
+ cd swiper && make compile
+ #+end_src
+
+ Then add this to Emacs init:
+ #+begin_src elisp
+ (add-to-list 'load-path "~/git/swiper/")
+ (require 'ivy)
+ #+end_src
+
+ To update the code:
+ #+begin_src sh
+ git pull
+ make
+ #+end_src
+
+ * Getting started
+
+ First enable Ivy completion everywhere:
+
+ #+begin_src elisp
+ (ivy-mode 1)
+ #+end_src
+
+ Note: =ivy-mode= can be toggled on and off with ~M-x~ =ivy-mode=.
+ ** Basic customization
+ Here are some basic settings particularly useful for new Ivy
+ users:
+ #+begin_src elisp
+ (setq ivy-use-virtual-buffers t)
+ (setq ivy-height 10)
+ (setq ivy-display-style 'fancy)
+ (setq ivy-count-format "(%d/%d) ")
+ #+end_src
+
+ For additional customizations, refer to =M-x describe-variable=
+ documentation.
+
+ * Key bindings
+ ** Global key bindings
+
+ Recommended key bindings are:
+ #+BEGIN_TEXINFO
+ @subsubheading Ivy-based interface to standard commands
+ #+END_TEXINFO
+ #+begin_src elisp
+ (global-set-key (kbd "C-s") 'swiper)
+ (global-set-key (kbd "M-x") 'counsel-M-x)
+ (global-set-key (kbd "C-x C-f") 'counsel-find-file)
+ (global-set-key (kbd "<f1> f") 'counsel-describe-function)
+ (global-set-key (kbd "<f1> v") 'counsel-describe-variable)
+ (global-set-key (kbd "<f1> l") 'counsel-load-library)
+ (global-set-key (kbd "<f2> i") 'counsel-info-lookup-symbol)
+ (global-set-key (kbd "<f2> u") 'counsel-unicode-char)
+ #+end_src
+ #+BEGIN_TEXINFO
+ @subsubheading Ivy-based interface to shell and system tools
+ #+END_TEXINFO
+ #+begin_src elisp
+ (global-set-key (kbd "C-c g") 'counsel-git)
+ (global-set-key (kbd "C-c j") 'counsel-git-grep)
+ (global-set-key (kbd "C-c k") 'counsel-ag)
+ (global-set-key (kbd "C-x l") 'counsel-locate)
+ (global-set-key (kbd "C-S-o") 'counsel-rhythmbox)
+ #+end_src
+ #+BEGIN_TEXINFO
+ @subsubheading Ivy-resume and other commands
+ #+END_TEXINFO
+ =ivy-resume= resumes the last Ivy-based completion.
+ #+begin_src elisp
+ (global-set-key (kbd "C-c C-r") 'ivy-resume)
+ #+end_src
+
+ ** Minibuffer key bindings
+
+ Ivy includes several minibuffer bindings, which are defined in the
+ =ivy-minibuffer-map= keymap variable. The most frequently used ones
+ are described here.
+
+ =swiper= or =counsel-M-x= add more through the =keymap= argument to
+ =ivy-read=. These keys, also active in the minibuffer, are described
+ under their respective commands.
+
+ *** Key bindings for navigation
+
+ - ~C-n~ (=ivy-next-line=) selects the next candidate
+ - ~C-p~ (=ivy-previous-line=) selects the previous candidate
+ - ~M-<~ (=ivy-beginning-of-buffer=) selects the first candidate
+ - ~M->~ (=ivy-end-of-buffer=) selects the last candidate
+ - ~C-v~ (=ivy-scroll-up-command=) scrolls up by =ivy-height= lines
+ - ~M-v~ (=ivy-scroll-down-command=) scrolls down by =ivy-height= lines
+
+ {{{defopt(ivy-wrap)}}}
+ This user option allows to get the wrap-around behavior for ~C-n~ and
+ ~C-p~. When set to =t=, =ivy-next-line= and =ivy-previous-line= will
+ cycle past the last and the first candidates respectively.
+
+ This behavior is off by default.
+ {{{endopt}}}
+
+ {{{defopt(ivy-height)}}}
+ Use this variable to adjust the minibuffer height, and therefore the
+ scroll size for ~C-v~ and ~M-v~.
+ {{{endopt}}}
+
+ *** Key bindings for single selection, action, then exit minibuffer
+
+ Ivy can offer several actions from which to choose which action to
+ run. This "calling an action" operates on the selected candidate. For
+ example, when viewing a list of files, one action could open it for
+ editing, one to view it, another to invoke a special function, and so
+ on. Custom actions can be added to this interface. The precise action
+ to call on the selected candidate can be delayed until after the
+ narrowing is completed. No need to exit the interface if unsure which
+ action to run. This delayed flexibility and customization of actions
+ extends usability of lists in Emacs.
+
+ ~C-m~ or ~RET~ (=ivy-done=) calls the default action and exits the
+ minibuffer.
+
+ ~M-o~ (=ivy-dispatching-done=) presents all available valid actions
+ from which to choose. When there is only one action available, there
+ is no difference between ~M-o~ and ~C-m~.
+
+ ~C-j~ (=ivy-alt-done=) calls the alternate action, such as completing
+ a directory name in a file list whereas ~C-m~ will select that directory
+ and exit the minibuffer.
+
+ Exiting the minibuffer also closes the Ivy window (as specified by
+ =ivy-height=). This closing and exiting sequence is conveniently off
+ when applying multiple actions. Multiple actions and multiple
+ selections as covered in the next section of this manual.
+
+ ~TAB~ (=ivy-partial-or-done=) attempts partial completion, extending
+ current input as much as possible.
+
+ ~TAB TAB~ is the same as ~C-j~.
+
+ ~C-M-j~ (=ivy-immediate-done=) is useful when there is no match for
+ the given input. Or there is an incorrect partial match. ~C-M-j~ with
+ =find-file= lists ignores the partial match and instead takes the
+ current input to create a new directory with =dired-create-directory=.
+
+ =ivy-immediate-done= illustrates how Ivy distinguishes between calling
+ an action on the /currently selected/ candidate and calling an action
+ on the /current input/.
+
+ #+BEGIN_TEXINFO
+ Invoking avy completion with @kbd{C-'} (@code{ivy-avy}).
+ #+END_TEXINFO
+ ~C-`~ uses avy's visible jump mechanism, which can further reduce
+ Ivy's line-by-line scrolling that requires multiple ~C-n~ or ~C-p~
+ keystrokes.
+
+ *** Key bindings for multiple selections and actions, keep minibuffer open
+
+ For repeatedly applying multiple actions or acting on multiple
+ candidates, Ivy does not close the minibuffer between commands. It
+ keeps the minibuffer open for applying subsequent actions.
+
+ Adding an extra meta key to the normal key chord invokes the special
+ version of the regular commands that enables applying multiple
+ actions.
+
+ ~C-M-m~ (=ivy-call=) is the non-exiting version of the default action,
+ ~C-m~ (=ivy-done=). Instead of closing the minibuffer, ~C-M-m~ allows
+ selecting another candidate or another action. For example, ~C-M-m~ on
+ functions list invokes =describe-function=. When combined with ~C-n~,
+ function descriptions can be invoked quickly in succession.
+
+ ~RET~ exits the minibuffer.
+
+ =ivy-resume= recalls the state of the completion session just before
+ its last exit. Useful after an accidental ~C-m~ (=ivy-done=).
+
+ ~C-M-o~ (=ivy-dispatching-call=) is a non-exiting version of ~M-o~
+ (=ivy-dispatching-done=) that can accumulate candidates into a queue.
+ For example, for playback in =counsel-rhythmbox=, ~C-M-o e~ en-queues
+ the selected candidate, and ~C-n C-m~ plays the next one in the queue.
+
+ ~C-M-n~ (=ivy-next-line-and-call=) combines ~C-n~ and ~C-M-m~. Applies
+ an action and moves to next line. Comes in handy when opening multiple
+ files from =counsel-find-file=, =counsel-git-grep=, =counsel-ag=, or
+ =counsel-locate= lists. Just hold ~C-M-n~ for rapid-fire default
+ action on each successive element of the list.
+
+ ~C-M-p~ (=ivy-previous-line-and-call=) combines ~C-p~ and ~C-M-m~. Is
+ the same as above except that it moves through the list in the other
+ direction.
+
+ *** Key bindings that alter minibuffer input
+
+ ~M-n~ (=ivy-next-history-element=) and ~M-p~
+ (=ivy-previous-history-element=) cycle through the Ivy command
+ history. Ivy updates an internal history list after each action. When
+ this history list is empty, ~M-n~ inserts symbol (or URL) at point
+ into the minibuffer.
+
+ ~M-i~ (=ivy-insert-current=) inserts the current candidate into the
+ minibuffer. Useful for copying and renaming files, for example: ~M-i~
+ to insert the original file name string, edit it, and then ~C-m~ to
+ complete the renaming.
+
+ ~M-j~ (=ivy-yank-word=) inserts sub-word at point into minibuffer. This
+ is similar to ~C-s C-w~ with =isearch=. Ivy reserves ~C-w~ for
+ =kill-region=.
+
+ ~S-SPC~ (=ivy-restrict-to-matches=) deletes the current input, and
+ resets the candidates list to the currently restricted matches. This
+ is how Ivy provides narrowing in successive tiers.
+
+ ~C-r~ (=ivy-reverse-i-search=) works just like ~C-r~ at bash command
+ prompt, where the completion candidates are the history items. Upon
+ completion, the selected candidate string is inserted into the
+ minibuffer.
+
+ *** Other key bindings
+
+ ~M-w~ (=ivy-kill-ring-save=) copies selected candidates to the kill
+ ring; when the region is active, copies active region.
+
+ *** Hydra in the minibuffer
+
+ ~C-o~ (=hydra-ivy/body=) invokes Hydra menus with key shortcuts.
+
+ ~C-o~ or ~i~ resumes editing.
+
+ Hydra reduces key strokes, for example: ~C-n C-n C-n C-n~ is ~C-o
+ jjjj~ in Hydra. Hydra has other benefits besides certain shorter key
+ bindings:
+ - ~<~ and ~>~ to adjust height of minibuffer,
+ - describes the current completion state, such as case folding and the
+ current action.
+
+ Minibuffer editing is disabled when Hydra is active.
+
+ *** Saving the current completion session to a buffer
+
+ ~C-c C-o~ (=ivy-occur=) saves the current candidates to a new buffer;
+ the list is active in the new buffer.
+
+ ~RET~ or ~mouse-1~ in the new buffer calls the appropriate action on
+ the selected candidate.
+
+ Ivy has no limit on the number of active buffers like these.
+
+ Ivy takes care of making these buffer names unique. It applies
+ descriptive names, for example: =*ivy-occur counsel-describe-variable
+ "function$*=.
+
+ * Completion styles
+
+ Ivy's completion functions rely on the highly configurable regex
+ builder.
+
+ The default is:
+ #+begin_src elisp
+ (setq ivy-re-builders-alist
+ '((t . ivy--regex-plus)))
+ #+end_src
+
+ The default =ivy--regex-plus= narrowing is always invoked unless
+ specified otherwise. For example, file name completion may have a
+ custom completion function:
+ #+begin_src elisp
+ (setq ivy-re-builders-alist
+ '((read-file-name-internal . ivy--regex-fuzzy)
+ (t . ivy--regex-plus)))
+ #+end_src
+
+ Ivy's flexibility extends to using different styles of completion
+ mechanics (regex-builders) for different types of lists. Despite this
+ flexibility, Ivy operates within a consistent and uniform interface.
+ The main regex-builders currently in Ivy are:
+
+ ** ivy--regex-plus
+
+ =ivy--regex-plus= is Ivy's default completion method.
+
+ =ivy--regex-plus= matches by splitting the input by spaces and
+ rebuilding it into a regex.
+
+ As the search string is typed in Ivy's minibuffer, it is transformed
+ into proper regex syntax. If the string is "for example", it is
+ transformed into
+
+ #+BEGIN_EXAMPLE
+ "\\(for\\).*\\(example\\)"
+ #+END_EXAMPLE
+
+ which in regex terminology matches "for" followed by a wild card and
+ then "example". Note how Ivy uses the space character to build
+ wild cards. For literal white space matching in Ivy, use an extra space:
+ to match one space type two spaces, to match two spaces type three
+ spaces, and so on.
+
+ As Ivy transforms typed characters into regex strings, it provides an
+ intuitive feedback through font highlights.
+
+ Ivy supports regexp negation with "!". For example, "define key ! ivy
+ quit" first selects everything matching "define.*key", then removes
+ everything matching "ivy", and finally removes everything matching
+ "quit". What remains is the final result set of the negation regexp.
+
+ #+BEGIN_EXAMPLE
+ Standard regexp identifiers work:
+
+ "^", "$", "\b" or "[a-z]"
+ #+END_EXAMPLE
+
+ Since Ivy treats minibuffer input as a regexp, standard regexp
+ identifiers work as usual. The exceptions are spaces, which
+ translate to ".*", and "!" that signal the beginning of a negation
+ group.
+
+ ** ivy--regex-ignore-order
+
+ =ivy--regex-ignore-order= ignores the order of regexp tokens when
+ searching for matching candidates. For instance, the input "for
+ example" will match "example test for". Otherwise =ivy--regex-plus=
+ normal behavior is to honor the order of regexp tokens.
+
+ ** ivy--regex-fuzzy
+
+ =ivy--regex-fuzzy= splits each character with a wild card. Searching
+ for "for" returns all "f.*o.*r" matches, resulting in a large number
+ of hits. Yet some searches need these extra hits. Ivy sorts such
+ large lists using =flx= package's scoring mechanism, if it's
+ installed.
+
+ * Variable Index
+ #+BEGIN_TEXINFO
+ @printindex vr
+ #+END_TEXINFO
--- /dev/null
+ \input texinfo @c -*- texinfo -*-
+ @c %**start of header
+ @setfilename ./ivy.info
+ @settitle Ivy User Manual
+ @documentencoding UTF-8
+ @documentlanguage en
+ @c %**end of header
+
+ @copying
+ @ifnottex
+ Ivy manual, version 0.7.0
+
+ Ivy is an interactive interface for completion in Emacs. Emacs uses
+ completion mechanism in a variety of contexts: code, menus, commands,
+ variables, functions, etc. Completion entails listing, sorting,
+ filtering, previewing, and applying actions on selected items. When
+ active, @code{ivy-mode} completes the selection process by narrowing
+ available choices while previewing in the minibuffer. Selecting the
+ final candidate is either through simple keyboard character inputs or
+ through powerful regular expressions. @end ifnottex
+
+ Copyright @copyright{} 2015 Free Software Foundation, Inc.
+
+ @quotation
+ Permission is granted to copy, distribute and/or modify this document
+ under the terms of the GNU Free Documentation License, Version 1.3 or
+ any later version published by the Free Software Foundation; with no
+ Invariant Sections, with the Front-Cover Texts being ``A GNU Manual,''
+ and with the Back-Cover Texts as in (a) below. A copy of the license
+ is included in the section entitled ``GNU Free Documentation License.''
+
+ (a) The FSF's Back-Cover Text is: ``You have the freedom to copy and
+ modify this GNU manual.''
+ @end quotation
+ @end copying
+
+ @dircategory Emacs
+ @direntry
+ * Ivy: (ivy). Using Ivy for completion.
+ @end direntry
+
+ @finalout
+ @titlepage
+ @title Ivy User Manual
+ @author Oleh Krehel
+ @page
+ @vskip 0pt plus 1filll
+ @insertcopying
+ @end titlepage
+
+ @contents
+
+ @ifnottex
+ @node Top
+ @top Ivy User Manual
+ @insertcopying
+ @end ifnottex
+
+ @menu
+ * Introduction::
+ * Installation::
+ * Getting started::
+ * Key bindings::
+ * Completion styles::
+ * Variable Index::
+
+ @detailmenu
+ --- The Detailed Node Listing ---
+
+ Installation
+
+ * Installing from Emacs Package Manager::
+ * Installing from the Git repository::
+
+ Getting started
+
+ * Basic customization::
+
+ Key bindings
+
+ * Global key bindings::
+ * Minibuffer key bindings::
+
+ Minibuffer key bindings
+
+ * Key bindings for navigation::
+ * Key bindings for single selection, action, then exit minibuffer: Key bindings for single selection action then exit minibuffer.
+ * Key bindings for multiple selections and actions, keep minibuffer open: Key bindings for multiple selections and actions keep minibuffer open.
+ * Key bindings that alter minibuffer input::
+ * Other key bindings::
+ * Hydra in the minibuffer::
+ * Saving the current completion session to a buffer::
+ Completion styles
+
+ * ivy--regex-plus::
+ * ivy--regex-ignore-order::
+ * ivy--regex-fuzzy::
+ @end detailmenu
+ @end menu
+
+ @node Introduction
+ @chapter Introduction
+
+ Ivy is for quick and easy selection from a list. When Emacs prompts
+ for a string from a list of several possible choices, Ivy springs into
+ action to assist in narrowing and picking the right string from a vast
+ number of choices.
+
+ Ivy strives for minimalism, simplicity, customizability and
+ discoverability.
+
+ @subsubheading Minimalism
+ Uncluttered minibuffer is minimalism. Ivy shows the completion
+ defaults, the number of matches, and 10 candidate matches below the
+ input line. Customize @code{ivy-length} to adjust the number of candidate
+ matches displayed in the minibuffer.
+
+ @subsubheading Simplicity
+ Simplicity is about Ivy's behavior in the minibuffer. It is also about
+ the code interface to extend Ivy's functionality. The minibuffer area
+ behaves as close to @code{fundamental-mode} as possible. @kbd{SPC} inserts a
+ space, for example, instead of being bound to the more complex
+ @code{minibuffer-complete-word}. Ivy's code uses easy-to-examine global
+ variables; avoids needless complications with branch-introducing
+ custom macros.
+
+ @subsubheading Customizability
+ Customizability is about being able to use different methods and
+ interfaces of completion to tailor the selection process. For example,
+ adding a custom display function that points to a selected candidate
+ with @code{->}, instead of highlighting the selected candidate with the
+ @code{ivy-current-match} face. Or take the customization of actions, say
+ after the candidate function is selected. @kbd{RET} uses
+ @code{counsel-describe-function} to describe the function, whereas @kbd{M-o d}
+ jumps to that function's definition in the code. The @kbd{M-o} prefix can
+ be uniformly used with characters like @kbd{d} to group similar actions.
+
+ @subsubheading Discoverability
+ Ivy displays easily discoverable commands through the hydra facility.
+ @kbd{C-o} in the minibuffer displays a hydra menu. It opens up within an
+ expanded minibuffer area. Each menu item comes with short
+ documentation strings and highlighted one-key completions. So
+ discovering even seldom used keys is simply a matter of @kbd{C-o} in the
+ minibuffer while in the midst of the Ivy interaction. This
+ discoverability minimizes exiting Ivy interface for documentation
+ look-ups.
+
+ @node Installation
+ @chapter Installation
+
+ Install Ivy automatically through Emacs's package manager, or manually
+ from Ivy's development repository.
+ @menu
+ * Installing from Emacs Package Manager::
+ * Installing from the Git repository::
+ @end menu
+
+ @node Installing from Emacs Package Manager
+ @section Installing from Emacs Package Manager
+
+ @kbd{M-x} @code{package-install} @kbd{RET} @code{swiper} @kbd{RET}
+
+ Ivy is installed as part of @code{swiper} package. @code{swiper} is available
+ from two different package archives, GNU ELPA and MELPA. For the
+ latest stable version, use the GNU ELPA archives using the above M-x
+ command.
+
+ For current hourly builds, use the MELPA archives. See the code below
+ for adding MELPA to the list of package archives:
+
+
+ @lisp
+ (require 'package)
+ (add-to-list 'package-archives
+ '("melpa" . "http://melpa.org/packages/"))
+ @end lisp
+
+ After this do @kbd{M-x} @code{package-refresh-contents} @kbd{RET}, followed by
+ @kbd{M-x} @code{package-install} @kbd{RET} @code{swiper} @kbd{RET}.
+
+ For package manager details, see @ref{Packages,,,emacs,}.
+
+ @node Installing from the Git repository
+ @section Installing from the Git repository
+
+ Why install from Git?
+
+ @itemize
+ @item
+ No need to wait for MELPA's hourly builds
+ @item
+ Easy to revert to previous versions
+ @item
+ Contribute to Ivy's development; send patches; pull requests
+ @end itemize
+
+ @strong{Configuration steps}
+
+ First clone the Swiper repository:
+
+ @example
+ cd ~/git && git clone https://github.com/abo-abo/swiper
+ cd swiper && make compile
+ @end example
+
+ Then add this to Emacs init:
+
+ @lisp
+ (add-to-list 'load-path "~/git/swiper/")
+ (require 'ivy)
+ @end lisp
+
+ To update the code:
+
+ @example
+ git pull
+ make
+ @end example
+
+ @node Getting started
+ @chapter Getting started
+
+ First enable Ivy completion everywhere:
+
+
+ @lisp
+ (ivy-mode 1)
+ @end lisp
+
+ Note: @code{ivy-mode} can be toggled on and off with @kbd{M-x} @code{ivy-mode}.
+ @menu
+ * Basic customization::
+ @end menu
+
+ @node Basic customization
+ @section Basic customization
+
+ Here are some basic settings particularly useful for new Ivy
+ users:
+
+ @lisp
+ (setq ivy-use-virtual-buffers t)
+ (setq ivy-height 10)
+ (setq ivy-display-style 'fancy)
+ (setq ivy-count-format "(%d/%d) ")
+ @end lisp
+
+ For additional customizations, refer to @code{M-x describe-variable}
+ documentation.
+
+ @node Key bindings
+ @chapter Key bindings
+
+ @menu
+ * Global key bindings::
+ * Minibuffer key bindings::
+ @end menu
+
+ @node Global key bindings
+ @section Global key bindings
+
+ Recommended key bindings are:
+ @subsubheading Ivy-based interface to standard commands
+
+ @lisp
+ (global-set-key (kbd "C-s") 'swiper)
+ (global-set-key (kbd "M-x") 'counsel-M-x)
+ (global-set-key (kbd "C-x C-f") 'counsel-find-file)
+ (global-set-key (kbd "<f1> f") 'counsel-describe-function)
+ (global-set-key (kbd "<f1> v") 'counsel-describe-variable)
+ (global-set-key (kbd "<f1> l") 'counsel-load-library)
+ (global-set-key (kbd "<f2> i") 'counsel-info-lookup-symbol)
+ (global-set-key (kbd "<f2> u") 'counsel-unicode-char)
+ @end lisp
+ @subsubheading Ivy-based interface to shell and system tools
+
+ @lisp
+ (global-set-key (kbd "C-c g") 'counsel-git)
+ (global-set-key (kbd "C-c j") 'counsel-git-grep)
+ (global-set-key (kbd "C-c k") 'counsel-ag)
+ (global-set-key (kbd "C-x l") 'counsel-locate)
+ (global-set-key (kbd "C-S-o") 'counsel-rhythmbox)
+ @end lisp
+ @subsubheading Ivy-resume and other commands
+ @code{ivy-resume} resumes the last Ivy-based completion.
+
+ @lisp
+ (global-set-key (kbd "C-c C-r") 'ivy-resume)
+ @end lisp
+
+ @node Minibuffer key bindings
+ @section Minibuffer key bindings
+
+ Ivy includes several minibuffer bindings, which are defined in the
+ @code{ivy-minibuffer-map} keymap variable. The most frequently used ones
+ are described here.
+
+ @code{swiper} or @code{counsel-M-x} add more through the @code{keymap} argument to
+ @code{ivy-read}. These keys, also active in the minibuffer, are described
+ under their respective commands.
+ @menu
+ * Key bindings for navigation::
+ * Key bindings for single selection, action, then exit minibuffer: Key bindings for single selection action then exit minibuffer.
+ * Key bindings for multiple selections and actions, keep minibuffer open: Key bindings for multiple selections and actions keep minibuffer open.
+ * Key bindings that alter minibuffer input::
+ * Other key bindings::
+ * Hydra in the minibuffer::
+ * Saving the current completion session to a buffer::
+ @end menu
+
+ @node Key bindings for navigation
+ @subsection Key bindings for navigation
+
+ @itemize
+ @item
+ @kbd{C-n} (@code{ivy-next-line}) selects the next candidate
+ @item
+ @kbd{C-p} (@code{ivy-previous-line}) selects the previous candidate
+ @item
+ @kbd{M-<} (@code{ivy-beginning-of-buffer}) selects the first candidate
+ @item
+ @kbd{M->} (@code{ivy-end-of-buffer}) selects the last candidate
+ @item
+ @kbd{C-v} (@code{ivy-scroll-up-command}) scrolls up by @code{ivy-height} lines
+ @item
+ @kbd{M-v} (@code{ivy-scroll-down-command}) scrolls down by @code{ivy-height} lines
+ @end itemize
+
+ @defopt ivy-wrap
+ This user option allows to get the wrap-around behavior for @kbd{C-n} and
+ @kbd{C-p}. When set to @code{t}, @code{ivy-next-line} and @code{ivy-previous-line} will
+ cycle past the last and the first candidates respectively.
+
+ This behavior is off by default.
+ @end defopt
+
+ @defopt ivy-height
+ Use this variable to adjust the minibuffer height, and therefore the
+ scroll size for @kbd{C-v} and @kbd{M-v}.
+ @end defopt
+
+ @node Key bindings for single selection action then exit minibuffer
+ @subsection Key bindings for single selection, action, then exit minibuffer
+
+ Ivy can offer several actions from which to choose which action to
+ run. This "calling an action" operates on the selected candidate. For
+ example, when viewing a list of files, one action could open it for
+ editing, one to view it, another to invoke a special function, and so
+ on. Custom actions can be added to this interface. The precise action
+ to call on the selected candidate can be delayed until after the
+ narrowing is completed. No need to exit the interface if unsure which
+ action to run. This delayed flexibility and customization of actions
+ extends usability of lists in Emacs.
+
+ @kbd{C-m} or @kbd{RET} (@code{ivy-done}) calls the default action and exits the
+ minibuffer.
+
+ @kbd{M-o} (@code{ivy-dispatching-done}) presents all available valid actions
+ from which to choose. When there is only one action available, there
+ is no difference between @kbd{M-o} and @kbd{C-m}.
+
+ @kbd{C-j} (@code{ivy-alt-done}) calls the alternate action, such as completing
+ a directory name in a file list whereas @kbd{C-m} will select that directory
+ and exit the minibuffer.
+
+ Exiting the minibuffer also closes the Ivy window (as specified by
+ @code{ivy-height}). This closing and exiting sequence is conveniently off
+ when applying multiple actions. Multiple actions and multiple
+ selections as covered in the next section of this manual.
+
+ @kbd{TAB} (@code{ivy-partial-or-done}) attempts partial completion, extending
+ current input as much as possible.
+
+ @kbd{TAB TAB} is the same as @kbd{C-j}.
+
+ @kbd{C-M-j} (@code{ivy-immediate-done}) is useful when there is no match for
+ the given input. Or there is an incorrect partial match. @kbd{C-M-j} with
+ @code{find-file} lists ignores the partial match and instead takes the
+ current input to create a new directory with @code{dired-create-directory}.
+
+ @code{ivy-immediate-done} illustrates how Ivy distinguishes between calling
+ an action on the @emph{currently selected} candidate and calling an action
+ on the @emph{current input}.
+
+ Invoking avy completion with @kbd{C-'} (@code{ivy-avy}).
+ @kbd{C-`} uses avy's visible jump mechanism, which can further reduce
+ Ivy's line-by-line scrolling that requires multiple @kbd{C-n} or @kbd{C-p}
+ keystrokes.
+
+ @node Key bindings for multiple selections and actions keep minibuffer open
+ @subsection Key bindings for multiple selections and actions, keep minibuffer open
+
+ For repeatedly applying multiple actions or acting on multiple
+ candidates, Ivy does not close the minibuffer between commands. It
+ keeps the minibuffer open for applying subsequent actions.
+
+ Adding an extra meta key to the normal key chord invokes the special
+ version of the regular commands that enables applying multiple
+ actions.
+
+ @kbd{C-M-m} (@code{ivy-call}) is the non-exiting version of the default action,
+ @kbd{C-m} (@code{ivy-done}). Instead of closing the minibuffer, @kbd{C-M-m} allows
+ selecting another candidate or another action. For example, @kbd{C-M-m} on
+ functions list invokes @code{describe-function}. When combined with @kbd{C-n},
+ function descriptions can be invoked quickly in succession.
+
+ @kbd{RET} exits the minibuffer.
+
+ @code{ivy-resume} recalls the state of the completion session just before
+ its last exit. Useful after an accidental @kbd{C-m} (@code{ivy-done}).
+
+ @kbd{C-M-o} (@code{ivy-dispatching-call}) is a non-exiting version of @kbd{M-o}
+ (@code{ivy-dispatching-done}) that can accumulate candidates into a queue.
+ For example, for playback in @code{counsel-rhythmbox}, @kbd{C-M-o e} en-queues
+ the selected candidate, and @kbd{C-n C-m} plays the next one in the queue.
+
+ @kbd{C-M-n} (@code{ivy-next-line-and-call}) combines @kbd{C-n} and @kbd{C-M-m}. Applies
+ an action and moves to next line. Comes in handy when opening multiple
+ files from @code{counsel-find-file}, @code{counsel-git-grep}, @code{counsel-ag}, or
+ @code{counsel-locate} lists. Just hold @kbd{C-M-n} for rapid-fire default
+ action on each successive element of the list.
+
+ @kbd{C-M-p} (@code{ivy-previous-line-and-call}) combines @kbd{C-p} and @kbd{C-M-m}. Is
+ the same as above except that it moves through the list in the other
+ direction.
+
+ @node Key bindings that alter minibuffer input
+ @subsection Key bindings that alter minibuffer input
+
+ @kbd{M-n} (@code{ivy-next-history-element}) and @kbd{M-p}
+ (@code{ivy-previous-history-element}) cycle through the Ivy command
+ history. Ivy updates an internal history list after each action. When
+ this history list is empty, @kbd{M-n} inserts symbol (or URL) at point
+ into the minibuffer.
+
+ @kbd{M-i} (@code{ivy-insert-current}) inserts the current candidate into the
+ minibuffer. Useful for copying and renaming files, for example: @kbd{M-i}
+ to insert the original file name string, edit it, and then @kbd{C-m} to
+ complete the renaming.
+
+ @kbd{M-j} (@code{ivy-yank-word}) inserts sub-word at point into minibuffer. This
+ is similar to @kbd{C-s C-w} with @code{isearch}. Ivy reserves @kbd{C-w} for
+ @code{kill-region}.
+
+ @kbd{S-SPC} (@code{ivy-restrict-to-matches}) deletes the current input, and
+ resets the candidates list to the currently restricted matches. This
+ is how Ivy provides narrowing in successive tiers.
+
+ @kbd{C-r} (@code{ivy-reverse-i-search}) works just like @kbd{C-r} at bash command
+ prompt, where the completion candidates are the history items. Upon
+ completion, the selected candidate string is inserted into the
+ minibuffer.
+
+ @node Other key bindings
+ @subsection Other key bindings
+
+ @kbd{M-w} (@code{ivy-kill-ring-save}) copies selected candidates to the kill
+ ring; when the region is active, copies active region.
+
+ @node Hydra in the minibuffer
+ @subsection Hydra in the minibuffer
+
+ @kbd{C-o} (@code{hydra-ivy/body}) invokes Hydra menus with key shortcuts.
+
+ @kbd{C-o} or @kbd{i} resumes editing.
+
+ Hydra reduces key strokes, for example: @kbd{C-n C-n C-n C-n} is @kbd{C-o
+ jjjj} in Hydra. Hydra has other benefits besides certain shorter key
+ bindings:
+ @itemize
+ @item
+ @kbd{<} and @kbd{>} to adjust height of minibuffer,
+ @item
+ describes the current completion state, such as case folding and the
+ current action.
+ @end itemize
+
+ Minibuffer editing is disabled when Hydra is active.
+
+ @node Saving the current completion session to a buffer
+ @subsection Saving the current completion session to a buffer
+
+ @kbd{C-c C-o} (@code{ivy-occur}) saves the current candidates to a new buffer;
+ the list is active in the new buffer.
+
+ @kbd{RET} or @kbd{mouse-1} in the new buffer calls the appropriate action on
+ the selected candidate.
+
+ Ivy has no limit on the number of active buffers like these.
+
+ Ivy takes care of making these buffer names unique. It applies
+ descriptive names, for example: @code{*ivy-occur counsel-describe-variable
+ "function$*}.
+
+ @node Completion styles
+ @chapter Completion styles
+
+ Ivy's completion functions rely on the highly configurable regex
+ builder.
+
+ The default is:
+
+ @lisp
+ (setq ivy-re-builders-alist
+ '((t . ivy--regex-plus)))
+ @end lisp
+
+ The default @code{ivy--regex-plus} narrowing is always invoked unless
+ specified otherwise. For example, file name completion may have a
+ custom completion function:
+
+ @lisp
+ (setq ivy-re-builders-alist
+ '((read-file-name-internal . ivy--regex-fuzzy)
+ (t . ivy--regex-plus)))
+ @end lisp
+
+ Ivy's flexibility extends to using different styles of completion
+ mechanics (regex-builders) for different types of lists. Despite this
+ flexibility, Ivy operates within a consistent and uniform interface.
+ The main regex-builders currently in Ivy are:
+ @menu
+ * ivy--regex-plus::
+ * ivy--regex-ignore-order::
+ * ivy--regex-fuzzy::
+ @end menu
+
+ @node ivy--regex-plus
+ @section ivy--regex-plus
+
+ @code{ivy--regex-plus} is Ivy's default completion method.
+
+ @code{ivy--regex-plus} matches by splitting the input by spaces and
+ rebuilding it into a regex.
+
+ As the search string is typed in Ivy's minibuffer, it is transformed
+ into proper regex syntax. If the string is "for example", it is
+ transformed into
+
+ @verbatim
+ "\\(for\\).*\\(example\\)"
+ @end verbatim
+
+ which in regex terminology matches "for" followed by a wild card and
+ then "example". Note how Ivy uses the space character to build
+ wild cards. For literal white space matching in Ivy, use an extra space:
+ to match one space type two spaces, to match two spaces type three
+ spaces, and so on.
+
+ As Ivy transforms typed characters into regex strings, it provides an
+ intuitive feedback through font highlights.
+
+ Ivy supports regexp negation with "!". For example, "define key ! ivy
+ quit" first selects everything matching "define.*key", then removes
+ everything matching "ivy", and finally removes everything matching
+ "quit". What remains is the final result set of the negation regexp.
+
+ @verbatim
+ Standard regexp identifiers work:
+
+ "^", "$", "\b" or "[a-z]"
+ @end verbatim
+
+ Since Ivy treats minibuffer input as a regexp, standard regexp
+ identifiers work as usual. The exceptions are spaces, which
+ translate to ".*", and "!" that signal the beginning of a negation
+ group.
+
+ @node ivy--regex-ignore-order
+ @section ivy--regex-ignore-order
+
+ @code{ivy--regex-ignore-order} ignores the order of regexp tokens when
+ searching for matching candidates. For instance, the input "for
+ example" will match "example test for". Otherwise @code{ivy--regex-plus}
+ normal behavior is to honor the order of regexp tokens.
+
+ @node ivy--regex-fuzzy
+ @section ivy--regex-fuzzy
+
+ @code{ivy--regex-fuzzy} splits each character with a wild card. Searching
+ for "for" returns all "f.*o.*r" matches, resulting in a large number
+ of hits. Yet some searches need these extra hits. Ivy sorts such
+ large lists using @code{flx} package's scoring mechanism, if it's
+ installed.
+
+ @node Variable Index
+ @chapter Variable Index
+
+ @printindex vr
+
+ @bye
--- /dev/null
+ body {
+ color: #333;
+ background-color: #ffffff;
+ margin-left: 1em;
+ margin-right: auto;
+ font-family: 'Ubuntu Mono', sans-serif;
+ max-width: 50em;
+ }
+
+ body a {
+ color: blue;
+ }
+
+ h2 {
+ font-weight: normal;
+ text-indent: 0;
+ border-radius: 15px;
+ background-color: #d6d8ec;
+ text-align: left;
+ padding: 3px 3px 3px 3px;
+ }
+
+ h2 a[id^="unnumbered"] {
+ background-color: #d6d8ec;
+ }
+
+ h2 a {
+ color: white;
+ background-color:#777777;
+ font-size:18px;
+ border-radius:3px;
+ padding: 0px 5px 0px 5px;
+ }
+
+ kbd {
+ padding:0.1em 0.6em;
+ border:1px solid #ccc;
+ font-size:13px;
+ font-weight:bold;
+ font-family:monospace;
+ background-color:#d6d8ec;
+ color:#333;
+ -moz-box-shadow:0 1px 0px rgba(0, 0, 0, 0.2),0 0 0 2px #ffffff inset;
+ -webkit-box-shadow:0 1px 0px rgba(0, 0, 0, 0.2),0 0 0 2px #ffffff inset;
+ box-shadow:0 1px 0px rgba(0, 0, 0, 0.2),0 0 0 2px #ffffff inset;
+ -moz-border-radius:3px;
+ -webkit-border-radius:3px;
+ border-radius:3px;
+ display:inline-block;
+ margin:0 0.1em;
+ text-shadow:0 1px 0 #fff;
+ line-height:1.4;
+ white-space:nowrap;
+ }
+
+ body a code {
+ color: black;
+ border: 1px solid Blue;
+ border-radius:3px;
+ }
+
+ code {
+ font-size:13px;
+ border: 1px solid Silver;
+ background-color: #e3e4ec;
+ }
+
+ pre {
+ border: 1px solid Silver;
+ background-color: #eeeeee;
+ padding: 3px;
+ margin-left: 1em;
+ }
+
+ cursor {
+ color: #fff;
+ background-color: #000;
+ overflow: hidden;
+ }
+
+ h3 {
+ counter-reset: chapter;
+ }
+
+ h4 {
+ margin-left: auto;
+ }
+
+ table, td, th {
+ border: 0px;
+ }
+
+ th {
+ background-color:#d6d8ec;
+ }
+
+ tr:nth-child(odd) {
+ background-color:#fff;
+ }
+ tr:nth-child(even) {
+ background-color:#d6d8ec;
+ }
+
+ .region {
+ color: #ffffff;
+ background-color: #f9b593;
+ }
(byte-compile-file (buffer-file-name) t)))
(error "Please install `hydra' and recompile/reinstall `ivy-hydra'")))))))
+ (defun ivy--matcher-desc ()
+ (if (eq ivy--regex-function
+ 'ivy--regex-fuzzy)
+ "fuzzy"
+ "ivy"))
+
(defhydra hydra-ivy (:hint nil
:color pink)
"
- ^^^^^^ ^Yes^ ^No^ ^Maybe^ ^Action^
- ^^^^^^^^^^^^^^---------------------------------------------------
- ^ ^ _k_ ^ ^ _f_ollow _i_nsert _c_: calling %s(if ivy-calling \"on\" \"off\") _w_/_s_: %s(ivy-action-name)
- _h_ ^+^ _l_ _d_one _o_ops _m_: matcher %s(if (eq ivy--regex-function 'ivy--regex-fuzzy) \"fuzzy\" \"ivy\")
- ^ ^ _j_ ^ ^ _g_o ^ ^ _<_/_>_: shrink/grow window
+ ^^^^^^ ^Yes^ ^^ ^No^ ^Maybe^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^Action^ ^
+ ^^^^^^^^^^^^^^^----------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------
+ ^ ^ _k_ ^ ^ _f_ollow occ_u_r _i_nsert _c_: calling %-5s(if ivy-calling \"on\" \"off\") _w_/_s_/_a_: %-14s(ivy-action-name)
+ _h_ ^+^ _l_ _d_one ^ ^ _o_ops _m_: matcher %-5s(ivy--matcher-desc)^^^^^^^^^^^^ _C_ase-fold: %-10`ivy-case-fold-search
+ ^ ^ _j_ ^ ^ _g_o ^ ^ ^ ^ _<_/_>_: shrink/grow^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _t_runcate: %-11`truncate-lines
"
;; arrows
("h" ivy-beginning-of-buffer)
(">" ivy-minibuffer-grow)
("<" ivy-minibuffer-shrink)
("w" ivy-prev-action)
- ("s" ivy-next-action))
+ ("s" ivy-next-action)
+ ("a" ivy-read-action)
+ ("t" (setq truncate-lines (not truncate-lines)))
+ ("C" ivy-toggle-case-fold)
+ ("u" ivy-occur :exit t))
(provide 'ivy-hydra)
(should (equal
(ivy-with '(ivy-read "pattern: " '("blue" "yellow"))
"z C-m")
- "z")))
+ "z"))
+ (should (equal
+ (ivy-with '(ivy-read "pattern: " '("blue" "yellow"))
+ "y <backspace> C-m")
+ "blue"))
+ (should (equal
+ (ivy-with '(let ((ivy-re-builders-alist '((t . ivy--regex-fuzzy))))
+ (ivy-read "pattern: " '("package-list-packages" "something-else")))
+ "plp C-m")
+ "package-list-packages"))
+ (should (equal
+ (ivy-with '(ivy-read "test" '("aaab" "aaac"))
+ "a C-n <tab> C-m")
+ "aaac"))
+ (should (equal
+ (ivy-with '(ivy-read "pattern: " '("can do" "can" "can't do"))
+ "can C-m")
+ "can")))
(ert-deftest swiper--re-builder ()
(setq swiper--width 4)
(should (string= (swiper--re-builder "^")
"."))
(should (string= (swiper--re-builder "^a")
- "^[0-9][0-9 ]\\{4\\}\\(a\\)"))
+ "^ ?\\(a\\)"))
(should (string= (swiper--re-builder "^a b")
- "^[0-9][0-9 ]\\{4\\}\\(a\\).*?\\(b\\)")))
+ "^ \\(a\\).*?\\(b\\)")))
(ert-deftest ivy--split ()
(should (equal (ivy--split "King of the who?")
(ert-deftest ivy--regex-fuzzy ()
(should (string= (ivy--regex-fuzzy "tmux")
- "t.*m.*u.*x"))
+ "\\(t\\).*\\(m\\).*\\(u\\).*\\(x\\)"))
(should (string= (ivy--regex-fuzzy "^tmux")
- "^t.*m.*u.*x"))
+ "^\\(t\\).*\\(m\\).*\\(u\\).*\\(x\\)"))
(should (string= (ivy--regex-fuzzy "^tmux$")
- "^t.*m.*u.*x$"))
+ "^\\(t\\).*\\(m\\).*\\(u\\).*\\(x\\)$"))
(should (string= (ivy--regex-fuzzy "")
""))
(should (string= (ivy--regex-fuzzy "^")
(ert-deftest ivy--format ()
(should (string= (let ((ivy--index 10)
- (ivy-format-function (lambda (x) (mapconcat #'identity x "\n")))
+ (ivy-format-function (lambda (x) (mapconcat (lambda (y) (car y)) x "\n")))
(cands '("NAME"
"SYNOPSIS"
"DESCRIPTION"
'("the" "The")))
(should (equal (ivy--filter "The" '("foo" "the" "The"))
'("The"))))
-
;;; Code:
(require 'cl-lib)
+ (require 'ffap)
;;* Customization
(defgroup ivy nil
"Incremental vertical completion."
:group 'convenience)
+ (defgroup ivy-faces nil
+ "Font-lock faces for `ivy'."
+ :group 'ivy)
+
(defface ivy-current-match
'((((class color) (background light))
:background "#1a4b77" :foreground "white")
(((class color) (background dark))
:background "#65a7e2" :foreground "black"))
- "Face used by Ivy for highlighting first match.")
+ "Face used by Ivy for highlighting the current match.")
+
+ (defface ivy-minibuffer-match-face-1
+ '((((class color) (background light))
+ :background "#d3d3d3")
+ (((class color) (background dark))
+ :background "#555555"))
+ "The background face for `ivy' minibuffer matches.")
+
+ (defface ivy-minibuffer-match-face-2
+ '((((class color) (background light))
+ :background "#e99ce8" :weight bold)
+ (((class color) (background dark))
+ :background "#777777" :weight bold))
+ "Face for `ivy' minibuffer matches modulo 1.")
+
+ (defface ivy-minibuffer-match-face-3
+ '((((class color) (background light))
+ :background "#bbbbff" :weight bold)
+ (((class color) (background dark))
+ :background "#7777ff" :weight bold))
+ "Face for `ivy' minibuffer matches modulo 2.")
+
+ (defface ivy-minibuffer-match-face-4
+ '((((class color) (background light))
+ :background "#ffbbff" :weight bold)
+ (((class color) (background dark))
+ :background "#8a498a" :weight bold))
+ "Face for `ivy' minibuffer matches modulo 3.")
(defface ivy-confirm-face
'((t :foreground "ForestGreen" :inherit minibuffer-prompt))
- "Face used by Ivy to issue a confirmation prompt.")
+ "Face used by Ivy for a confirmation prompt.")
(defface ivy-match-required-face
'((t :foreground "red" :inherit minibuffer-prompt))
- "Face used by Ivy to issue a match required prompt.")
+ "Face used by Ivy for a match required prompt.")
+
+ (setcdr (assoc load-file-name custom-current-group-alist) 'ivy)
(defface ivy-subdir
'((t (:inherit 'dired-directory)))
"Face used by Ivy for highlighting subdirs in the alternatives.")
+ (defface ivy-modified-buffer
+ '((t :inherit 'default))
+ "Face used by Ivy for highlighting modified file visiting buffers.")
+
(defface ivy-remote
'((t (:foreground "#110099")))
"Face used by Ivy for highlighting remotes in the alternatives.")
+ (defface ivy-virtual
+ '((t :inherit font-lock-builtin-face))
+ "Face used by Ivy for matching virtual buffer names.")
+
(defcustom ivy-height 10
"Number of lines for the minibuffer window."
:type 'integer)
(defcustom ivy-count-format "%-4d "
- "The style of showing the current candidate count for `ivy-read'.
- Set this to nil if you don't want the count. You can also set it
- to e.g. \"(%d/%d) \" if you want to see both the candidate index
- and the candidate count."
- :type '(choice (const :tag "Count disabled" nil) string))
+ "The style to use for displaying the current candidate count for `ivy-read'.
+ Set this to \"\" to suppress the count visibility.
+ Set this to \"(%d/%d) \" to display both the index and the count."
+ :type '(choice
+ (const :tag "Count disabled" "")
+ (const :tag "Count matches" "%-4d ")
+ (const :tag "Count matches and show current match" "(%d/%d) ")
+ string))
(defcustom ivy-wrap nil
- "Whether to wrap around after the first and last candidate."
+ "When non-nil, wrap around after the first and the last candidate."
:type 'boolean)
- (defcustom ivy-display-style nil
+ (defcustom ivy-display-style (unless (version< emacs-version "24.5") 'fancy)
"The style for formatting the minibuffer.
- By default, the matched strings will be copied as they are.
+ By default, the matched strings are copied as is.
- With the fancy method, the matching parts of the regexp will be
- additionally highlighted, just like `swiper' does it."
+ The fancy display style highlights matching parts of the regexp,
+ a behavior similar to `swiper'.
+
+ This setting depends on `add-face-text-property' - a C function
+ available as of Emacs 24.5. Fancy style will render poorly in
+ earlier versions of Emacs."
:type '(choice
(const :tag "Plain" nil)
(const :tag "Fancy" fancy)))
(defcustom ivy-on-del-error-function 'minibuffer-keyboard-quit
"The handler for when `ivy-backward-delete-char' throws.
- This is usually meant as a quick exit out of the minibuffer."
+ Usually a quick exit out of the minibuffer."
:type 'function)
(defcustom ivy-extra-directories '("../" "./")
"Add this to the front of the list when completing file names.
Only \"./\" and \"../\" apply here. They appear in reverse order."
- :type 'list)
+ :type '(repeat :tag "Dirs"
+ (choice
+ (const :tag "Parent Directory" "../")
+ (const :tag "Current Directory" "./"))))
(defcustom ivy-use-virtual-buffers nil
- "When non-nil, add `recentf-mode' and bookmarks to the list of buffers."
+ "When non-nil, add `recentf-mode' and bookmarks to `ivy-switch-buffer'."
:type 'boolean)
(defvar ivy--actions-list nil
(define-key map (kbd "M-i") 'ivy-insert-current)
(define-key map (kbd "C-o") 'hydra-ivy/body)
(define-key map (kbd "M-o") 'ivy-dispatching-done)
+ (define-key map (kbd "C-M-o") 'ivy-dispatching-call)
(define-key map (kbd "C-k") 'ivy-kill-line)
(define-key map (kbd "S-SPC") 'ivy-restrict-to-matches)
(define-key map (kbd "M-w") 'ivy-kill-ring-save)
+ (define-key map (kbd "C-'") 'ivy-avy)
+ (define-key map (kbd "C-M-a") 'ivy-read-action)
+ (define-key map (kbd "C-c C-o") 'ivy-occur)
map)
"Keymap used in the minibuffer.")
(autoload 'hydra-ivy/body "ivy-hydra" "" t)
history preselect keymap update-fn sort
;; The window in which `ivy-read' was called
window
+ ;; The buffer in which `ivy-read' was called
+ buffer
+ ;; The value of `ivy-text' to be used by `ivy-occur'
+ text
action
unwind
re-builder
matcher
;; When this is non-nil, call it for each input change to get new candidates
- dynamic-collection)
+ dynamic-collection
+ caller)
(defvar ivy-last nil
- "The last parameters passed to `ivy-read'.")
+ "The last parameters passed to `ivy-read'.
+
+ This should eventually become a stack so that you could use
+ `ivy-read' recursively.")
(defsubst ivy-set-action (action)
(setf (ivy-state-action ivy-last) action))
"History list of candidates entered in the minibuffer.
Maximum length of the history list is determined by the value
- of `history-length', which see.")
+ of `history-length'.")
(defvar ivy--directory nil
"Current directory when completing file names.")
(defvar ivy--prompt nil
"Store the format-style prompt.
- When non-nil, it should contain one %d.")
+ When non-nil, it should contain at least one %d.")
(defvar ivy--prompt-extra ""
"Temporary modifications to the prompt.")
(defvar ivy--old-text ""
"Store old `ivy-text' for dynamic completion.")
+ (defvar ivy-case-fold-search 'auto
+ "Store the current overriding `case-fold-search'.")
+
(defvar Info-current-file)
(defmacro ivy-quit-and-run (&rest body)
,@body))
(minibuffer-keyboard-quit)))
+ (defun ivy-exit-with-action (action)
+ "Quit the minibuffer and call ACTION afterwards."
+ (ivy-set-action
+ `(lambda (x)
+ (funcall ',action x)
+ (ivy-set-action ',(ivy-state-action ivy-last))))
+ (setq ivy-exit 'done)
+ (exit-minibuffer))
+
(defmacro with-ivy-window (&rest body)
"Execute BODY in the window from which `ivy-read' was called."
(declare (indent 0)
(debug t))
- `(with-selected-window (ivy-state-window ivy-last)
+ `(with-selected-window (ivy--get-window ivy-last)
,@body))
(defun ivy--done (text)
(insert ivy-text)
(ivy--exhibit))))
- (defun ivy-dispatching-done ()
- "Select one of the available actions and call `ivy-done'."
+ (defun ivy-read-action ()
+ "Change the action to one of the available ones."
(interactive)
(let ((actions (ivy-state-action ivy-last)))
- (if (null (ivy--actionp actions))
- (ivy-done)
+ (unless (null (ivy--actionp actions))
(let* ((hint (concat ivy--current
"\n"
(mapconcat
"\n")
"\n"))
(key (string (read-key hint)))
- (action (assoc key (cdr actions))))
+ (action-idx (cl-position-if
+ (lambda (x) (equal (car x) key))
+ (cdr actions))))
(cond ((string= key "\a"))
- ((null action)
+ ((null action-idx)
(error "%s is not bound" key))
(t
(message "")
- (ivy-set-action (nth 1 action))
- (ivy-done)))))))
+ (setcar actions (1+ action-idx))
+ (ivy-set-action actions)))))))
+
+ (defun ivy-dispatching-done ()
+ "Select one of the available actions and call `ivy-done'."
+ (interactive)
+ (ivy-read-action)
+ (ivy-done))
+
+ (defun ivy-dispatching-call ()
+ "Select one of the available actions and call `ivy-call'."
+ (interactive)
+ (let ((actions (copy-sequence (ivy-state-action ivy-last))))
+ (unwind-protect
+ (when (ivy-read-action)
+ (ivy-call))
+ (ivy-set-action actions))))
(defun ivy-build-tramp-name (x)
"Reconstruct X into a path.
"Exit the minibuffer with the selected candidate.
When ARG is t, exit with current text, ignoring the candidates."
(interactive "P")
+ (cond (arg
+ (ivy-immediate-done))
+ (ivy--directory
+ (ivy--directory-done))
+ ((eq (ivy-state-collection ivy-last) 'Info-read-node-name-1)
+ (if (or (equal ivy--current "(./)")
+ (equal ivy--current "(../)"))
+ (ivy-quit-and-run
+ (ivy-read "Go to file: " 'read-file-name-internal
+ :action (lambda (x)
+ (Info-find-node
+ (expand-file-name x ivy--directory)
+ "Top"))))
+ (ivy-done)))
+ (t
+ (ivy-done))))
+
+ (defun ivy--directory-done ()
+ "Handle exit from the minibuffer when completing file names."
(let (dir)
- (cond (arg
- (ivy-immediate-done))
- ((and ivy--directory
- (or
- (and
- (not (string= ivy--current "./"))
- (cl-plusp ivy--length)
- (file-directory-p
- (setq dir (expand-file-name
- ivy--current ivy--directory))))))
- (ivy--cd dir)
- (ivy--exhibit))
- ((eq (ivy-state-collection ivy-last) 'Info-read-node-name-1)
- (if (or (equal ivy--current "(./)")
- (equal ivy--current "(../)"))
- (ivy-quit-and-run
- (ivy-read "Go to file: " 'read-file-name-internal
- :action (lambda (x)
- (Info-find-node
- (expand-file-name x ivy--directory)
- "Top"))))
- (ivy-done)))
- ((and ivy--directory
- (string-match "\\`/[^/]+:.*:.*\\'" ivy-text))
- (ivy-done))
- ((and ivy--directory
- (string-match
- "\\`/\\([^/]+?\\):\\(?:\\(.*\\)@\\)?\\(.*\\)\\'"
- ivy-text))
- (let ((method (match-string 1 ivy-text))
- (user (match-string 2 ivy-text))
- (rest (match-string 3 ivy-text))
- res)
- (require 'tramp)
- (dolist (x (tramp-get-completion-function method))
- (setq res (append res (funcall (car x) (cadr x)))))
- (setq res (delq nil res))
- (when user
- (dolist (x res)
- (setcar x user)))
- (setq res (cl-delete-duplicates res :test #'equal))
- (let* ((old-ivy-last ivy-last)
- (enable-recursive-minibuffers t)
- (host (ivy-read "Find File: "
- (mapcar #'ivy-build-tramp-name res)
- :initial-input rest)))
- (setq ivy-last old-ivy-last)
- (when host
- (setq ivy--directory "/")
- (ivy--cd (concat "/" method ":" host ":"))))))
- (t
- (ivy-done)))))
+ (cond
+ ((equal ivy-text "/sudo::")
+ (setq dir (concat ivy-text ivy--directory))
+ (ivy--cd dir)
+ (ivy--exhibit))
+ ((or
+ (and
+ (not (equal ivy-text ""))
+ (ignore-errors
+ (file-directory-p
+ (setq dir
+ (file-name-as-directory
+ (expand-file-name
+ ivy-text ivy--directory))))))
+ (and
+ (not (string= ivy--current "./"))
+ (cl-plusp ivy--length)
+ (ignore-errors
+ (file-directory-p
+ (setq dir (file-name-as-directory
+ (expand-file-name
+ ivy--current ivy--directory)))))))
+ (ivy--cd dir)
+ (ivy--exhibit))
+ ((or (and (equal ivy--directory "/")
+ (string-match "\\`[^/]+:.*:.*\\'" ivy-text))
+ (string-match "\\`/[^/]+:.*:.*\\'" ivy-text))
+ (ivy-done))
+ ((or (and (equal ivy--directory "/")
+ (cond ((string-match
+ "\\`\\([^/]+?\\):\\(?:\\(.*\\)@\\)?\\(.*\\)\\'"
+ ivy-text))
+ ((string-match
+ "\\`\\([^/]+?\\):\\(?:\\(.*\\)@\\)?\\(.*\\)\\'"
+ ivy--current)
+ (setq ivy-text ivy--current))))
+ (string-match
+ "\\`/\\([^/]+?\\):\\(?:\\(.*\\)@\\)?\\(.*\\)\\'"
+ ivy-text))
+ (let ((method (match-string 1 ivy-text))
+ (user (match-string 2 ivy-text))
+ (rest (match-string 3 ivy-text))
+ res)
+ (require 'tramp)
+ (dolist (x (tramp-get-completion-function method))
+ (setq res (append res (funcall (car x) (cadr x)))))
+ (setq res (delq nil res))
+ (when user
+ (dolist (x res)
+ (setcar x user)))
+ (setq res (cl-delete-duplicates res :test #'equal))
+ (let* ((old-ivy-last ivy-last)
+ (enable-recursive-minibuffers t)
+ (host (ivy-read "Find File: "
+ (mapcar #'ivy-build-tramp-name res)
+ :initial-input rest)))
+ (setq ivy-last old-ivy-last)
+ (when host
+ (setq ivy--directory "/")
+ (ivy--cd (concat "/" method ":" host ":"))))))
+ (t
+ (ivy-done)))))
(defcustom ivy-tab-space nil
"When non-nil, `ivy-partial-or-done' should insert a space."
If the text hasn't changed as a result, forward to `ivy-alt-done'."
(interactive)
(if (and (eq (ivy-state-collection ivy-last) #'read-file-name-internal)
- (string-match "\\`/" ivy-text))
+ (or (and (equal ivy--directory "/")
+ (string-match "\\`[^/]+:.*\\'" ivy-text))
+ (string-match "\\`/" ivy-text)))
(let ((default-directory ivy--directory))
(minibuffer-complete)
(setq ivy-text (ivy--input))
- (when (and (file-directory-p ivy-text)
- (= ivy--length 1))
- (ivy--cd (expand-file-name ivy-text))))
+ (when (file-directory-p
+ (expand-file-name ivy-text ivy--directory))
+ (ivy--cd (file-name-as-directory
+ (expand-file-name ivy-text ivy--directory)))))
(or (ivy-partial)
(when (or (eq this-command last-command)
(eq ivy--length 1))
(new (try-completion (if startp
(substring postfix 1)
postfix)
- (mapcar (lambda (str) (substring str (string-match postfix str)))
+ (mapcar (lambda (str)
+ (let ((i (string-match postfix str)))
+ (when i
+ (substring str i))))
ivy--old-cands))))
(cond ((eq new t) nil)
((string= new ivy-text) nil)
"Exit the minibuffer with the current input."
(interactive)
(delete-minibuffer-contents)
- (insert (setq ivy--current ivy-text))
+ (insert (setq ivy--current
+ (if ivy--directory
+ (expand-file-name ivy-text ivy--directory)
+ ivy-text)))
(setq ivy-exit 'done)
(exit-minibuffer))
(defun ivy-resume ()
"Resume the last completion session."
(interactive)
- (ivy-read
- (ivy-state-prompt ivy-last)
- (ivy-state-collection ivy-last)
- :predicate (ivy-state-predicate ivy-last)
- :require-match (ivy-state-require-match ivy-last)
- :initial-input ivy-text
- :history (ivy-state-history ivy-last)
- :preselect (unless (eq (ivy-state-collection ivy-last)
- 'read-file-name-internal)
- (regexp-quote ivy--current))
- :keymap (ivy-state-keymap ivy-last)
- :update-fn (ivy-state-update-fn ivy-last)
- :sort (ivy-state-sort ivy-last)
- :action (ivy-state-action ivy-last)
- :unwind (ivy-state-unwind ivy-last)
- :re-builder (ivy-state-re-builder ivy-last)
- :matcher (ivy-state-matcher ivy-last)
- :dynamic-collection (ivy-state-dynamic-collection ivy-last)))
+ (when (eq (ivy-state-caller ivy-last) 'swiper)
+ (switch-to-buffer (ivy-state-buffer ivy-last)))
+ (with-current-buffer (ivy-state-buffer ivy-last)
+ (ivy-read
+ (ivy-state-prompt ivy-last)
+ (ivy-state-collection ivy-last)
+ :predicate (ivy-state-predicate ivy-last)
+ :require-match (ivy-state-require-match ivy-last)
+ :initial-input ivy-text
+ :history (ivy-state-history ivy-last)
+ :preselect (unless (eq (ivy-state-collection ivy-last)
+ 'read-file-name-internal)
+ ivy--current)
+ :keymap (ivy-state-keymap ivy-last)
+ :update-fn (ivy-state-update-fn ivy-last)
+ :sort (ivy-state-sort ivy-last)
+ :action (ivy-state-action ivy-last)
+ :unwind (ivy-state-unwind ivy-last)
+ :re-builder (ivy-state-re-builder ivy-last)
+ :matcher (ivy-state-matcher ivy-last)
+ :dynamic-collection (ivy-state-dynamic-collection ivy-last)
+ :caller (ivy-state-caller ivy-last))))
(defvar ivy-calling nil
"When non-nil, call the current action when `ivy--index' changes.")
(defun ivy-scroll-up-command ()
"Scroll the candidates upward by the minibuffer height."
(interactive)
- (ivy-set-index (min (+ ivy--index ivy-height)
+ (ivy-set-index (min (1- (+ ivy--index ivy-height))
(1- ivy--length))))
(defun ivy-scroll-down-command ()
"Scroll the candidates downward by the minibuffer height."
(interactive)
- (ivy-set-index (max (- ivy--index ivy-height)
+ (ivy-set-index (max (1+ (- ivy--index ivy-height))
0)))
(defun ivy-minibuffer-grow ()
action
(cadr (nth (car action) action))))))
+ (defun ivy--get-window (state)
+ "Get the window from STATE."
+ (let ((window (ivy-state-window state)))
+ (if (window-live-p window)
+ window
+ (if (= (length (window-list)) 1)
+ (selected-window)
+ (next-window)))))
+
(defun ivy--actionp (x)
"Return non-nil when X is a list of actions."
(and x (listp x) (not (eq (car x) 'closure))))
(if (equal ivy--current "")
ivy-text
ivy--current))))
- (funcall action x)))))
+ (prog1 (funcall action x)
+ (unless (or (eq ivy-exit 'done)
+ (equal (selected-window)
+ (active-minibuffer-window))
+ (null (active-minibuffer-window)))
+ (select-window (active-minibuffer-window))))))))
(defun ivy-next-line-and-call (&optional arg)
"Move cursor vertically down ARG candidates.
"Check if the current input points to a different directory.
If so, move to that directory, while keeping only the file name."
(when ivy--directory
- (let* ((input (expand-file-name (ivy--input)))
- (file (file-name-nondirectory input))
- (dir (expand-file-name (file-name-directory input))))
- (if (string= dir ivy--directory)
- (progn
- (delete-minibuffer-contents)
- (insert file))
- (ivy--cd dir)
- (insert file)))))
+ (let ((input (ivy--input))
+ url)
+ (if (setq url (ffap-url-p input))
+ (ivy-exit-with-action
+ (lambda (_)
+ (funcall ffap-url-fetcher url)))
+ (setq input (expand-file-name input))
+ (let ((file (file-name-nondirectory input))
+ (dir (expand-file-name (file-name-directory input))))
+ (if (string= dir ivy--directory)
+ (progn
+ (delete-minibuffer-contents)
+ (insert file))
+ (ivy--cd dir)
+ (insert file)))))))
(defun ivy--maybe-scroll-history ()
"If the selected history element has an index, scroll there."
(setq ivy--old-re nil)
(cl-rotatef ivy--regex-function ivy--regexp-quote))
+ (defvar avy-all-windows)
+ (defvar avy-action)
+ (defvar avy-keys)
+ (defvar avy-keys-alist)
+ (defvar avy-style)
+ (defvar avy-styles-alist)
+ (declare-function avy--process "ext:avy")
+ (declare-function avy--style-fn "ext:avy")
+
+ (eval-after-load 'avy
+ '(add-to-list 'avy-styles-alist '(ivy-avy . pre)))
+
+ (defun ivy-avy ()
+ "Jump to one of the current ivy candidates."
+ (interactive)
+ (unless (require 'avy nil 'noerror)
+ (error "Package avy isn't installed"))
+ (let* ((avy-all-windows nil)
+ (avy-keys (or (cdr (assq 'ivy-avy avy-keys-alist))
+ avy-keys))
+ (avy-style (or (cdr (assq 'ivy-avy
+ avy-styles-alist))
+ avy-style))
+ (candidate
+ (let ((candidates))
+ (save-excursion
+ (save-restriction
+ (narrow-to-region
+ (window-start)
+ (window-end))
+ (goto-char (point-min))
+ (forward-line)
+ (while (< (point) (point-max))
+ (push
+ (cons (point)
+ (selected-window))
+ candidates)
+ (forward-line))))
+ (setq avy-action #'identity)
+ (avy--process
+ (nreverse candidates)
+ (avy--style-fn avy-style)))))
+ (ivy-set-index (- (line-number-at-pos candidate) 2))
+ (ivy--exhibit)
+ (ivy-done)))
+
(defun ivy-sort-file-function-default (x y)
"Compare two files X and Y.
Prioritize directories."
nil
(string< x y))))
- (defvar ivy-sort-functions-alist
+ (defcustom ivy-sort-functions-alist
'((read-file-name-internal . ivy-sort-file-function-default)
(internal-complete-buffer . nil)
(counsel-git-grep-function . nil)
"An alist of sorting functions for each collection function.
Interactive functions that call completion fit in here as well.
- For each entry, nil means no sorting. It's very useful to turn
- off the sorting for functions that have candidates in the natural
- buffer order, like `org-refile' or `Man-goto-section'.
-
- The entry associated to t is used for all fall-through cases.")
+ Nil means no sorting, which is useful to turn off the sorting for
+ functions that have candidates in the natural buffer order, like
+ `org-refile' or `Man-goto-section'.
+
+ The entry associated with t is used for all fall-through cases.
+
+ See also `ivy-sort-max-size'."
+ :type
+ '(alist
+ :key-type (choice
+ (const :tag "All other functions" t)
+ (symbol :tag "Function"))
+ :value-type (choice
+ (const :tag "plain sort" string-lessp)
+ (const :tag "file sort" ivy-sort-file-function-default)
+ (const :tag "no sort" nil)))
+ :group 'ivy)
+
+ (defvar ivy-index-functions-alist
+ '((swiper . ivy-recompute-index-swiper)
+ (swiper-multi . ivy-recompute-index-swiper)
+ (counsel-git-grep . ivy-recompute-index-swiper)
+ (counsel-grep . ivy-recompute-index-swiper-async)
+ (t . ivy-recompute-index-zero))
+ "An alist of index recomputing functions for each collection function.
+ When the input changes, the appropriate function returns an
+ integer - the index of the matched candidate that should be
+ selected.")
(defvar ivy-re-builders-alist
'((t . ivy--regex-plus))
Each function should take a string and return a valid regex or a
regex sequence (see below).
- The entry associated to t is used for all fall-through cases.
+ The entry associated with t is used for all fall-through cases.
Possible choices: `ivy--regex', `regexp-quote', `ivy--regex-plus'.
- In case a function returns a list, it should look like this:
+ If a function returns a list, it should format like this:
'((\"matching-regexp\" . t) (\"non-matching-regexp\") ...).
The matches will be filtered in a sequence, you can mix the
;;** Entry Point
(cl-defun ivy-read (prompt collection
- &key predicate require-match initial-input
- history preselect keymap update-fn sort
- action unwind re-builder matcher dynamic-collection)
+ &key predicate require-match initial-input
+ history preselect keymap update-fn sort
+ action unwind re-builder matcher dynamic-collection caller)
"Read a string in the minibuffer, with completion.
- PROMPT is a string to prompt with; normally it ends in a colon
- and a space. When PROMPT contains %d, it will be updated with
- the current number of matching candidates. If % appears elsewhere
- in the PROMPT it should be quoted as %%.
- See also `ivy-count-format'.
+ PROMPT is a format string, normally ending in a colon and a
+ space; %d anywhere in the string is replaced by the current
+ number of matching candidates. For the literal % character,
+ escape it with %%. See also `ivy-count-format'.
- COLLECTION is a list of strings.
+ COLLECTION is either a list of strings, a function, an alist, or
+ a hash table.
- If INITIAL-INPUT is non-nil, insert it in the minibuffer initially.
+ If INITIAL-INPUT is not nil, then insert that input in the
+ minibuffer initially.
- KEYMAP is composed together with `ivy-minibuffer-map'.
+ KEYMAP is composed with `ivy-minibuffer-map'.
- If PRESELECT is non-nil select the corresponding candidate out of
- the ones that match INITIAL-INPUT.
+ If PRESELECT is not nil, then select the corresponding candidate
+ out of the ones that match the INITIAL-INPUT.
UPDATE-FN is called each time the current candidate(s) is changed.
- When SORT is t, refer to `ivy-sort-functions-alist' for sorting.
+ When SORT is t, use `ivy-sort-functions-alist' for sorting.
- ACTION is a lambda to call after a result was selected. It should
- take a single argument, usually a string.
+ ACTION is a lambda function to call after selecting a result. It
+ takes a single string argument.
- UNWIND is a lambda to call before exiting.
+ UNWIND is a lambda function to call before exiting.
- RE-BUILDER is a lambda that transforms text into a regex.
+ RE-BUILDER is a lambda function to call to transform text into a
+ regex pattern.
- MATCHER can completely override matching.
+ MATCHER is to override matching.
- DYNAMIC-COLLECTION is a function to call to update the list of
- candidates with each input."
+ DYNAMIC-COLLECTION is a boolean to specify if the list of
+ candidates is updated after each input by calling COLLECTION.
+
+ CALLER is a symbol to uniquely identify the caller to `ivy-read'.
+ It is used, along with COLLECTION, to determine which
+ customizations apply to the current completion session."
(let ((extra-actions (plist-get ivy--actions-list this-command)))
(when extra-actions
(setq action
("o" ,action "default")
,@extra-actions)
(delete-dups (append action extra-actions))))))
- (setq ivy-last
- (make-ivy-state
- :prompt prompt
- :collection collection
- :predicate predicate
- :require-match require-match
- :initial-input initial-input
- :history history
- :preselect preselect
- :keymap keymap
- :update-fn update-fn
- :sort sort
- :action action
- :window (selected-window)
- :unwind unwind
- :re-builder re-builder
- :matcher matcher
- :dynamic-collection dynamic-collection))
- (ivy--reset-state ivy-last)
- (prog1
- (unwind-protect
- (minibuffer-with-setup-hook
- #'ivy--minibuffer-setup
- (let* ((hist (or history 'ivy-history))
- (minibuffer-completion-table collection)
- (minibuffer-completion-predicate predicate)
- (resize-mini-windows (cond
- ((display-graphic-p) nil)
- ((null resize-mini-windows) 'grow-only)
- (t resize-mini-windows)))
- (res (read-from-minibuffer
- prompt
- (ivy-state-initial-input ivy-last)
- (make-composed-keymap keymap ivy-minibuffer-map)
- nil
- hist)))
- (when (eq ivy-exit 'done)
- (let ((item (if ivy--directory
- ivy--current
- ivy-text)))
- (unless (equal item "")
- (set hist (cons (propertize item 'ivy-index ivy--index)
- (delete item
- (cdr (symbol-value hist)))))))
- res)))
- (remove-hook 'post-command-hook #'ivy--exhibit)
- (when (setq unwind (ivy-state-unwind ivy-last))
- (funcall unwind)))
- (ivy-call)))
+ (let ((recursive-ivy-last (and (active-minibuffer-window) ivy-last)))
+ (setq ivy-last
+ (make-ivy-state
+ :prompt prompt
+ :collection collection
+ :predicate predicate
+ :require-match require-match
+ :initial-input initial-input
+ :history history
+ :preselect preselect
+ :keymap keymap
+ :update-fn update-fn
+ :sort sort
+ :action action
+ :window (selected-window)
+ :buffer (current-buffer)
+ :unwind unwind
+ :re-builder re-builder
+ :matcher matcher
+ :dynamic-collection dynamic-collection
+ :caller caller))
+ (ivy--reset-state ivy-last)
+ (prog1
+ (unwind-protect
+ (minibuffer-with-setup-hook
+ #'ivy--minibuffer-setup
+ (let* ((hist (or history 'ivy-history))
+ (minibuffer-completion-table collection)
+ (minibuffer-completion-predicate predicate)
+ (resize-mini-windows (cond
+ ((display-graphic-p) nil)
+ ((null resize-mini-windows) 'grow-only)
+ (t resize-mini-windows)))
+ (res (read-from-minibuffer
+ prompt
+ (ivy-state-initial-input ivy-last)
+ (make-composed-keymap keymap ivy-minibuffer-map)
+ nil
+ hist)))
+ (when (eq ivy-exit 'done)
+ (let ((item (if ivy--directory
+ ivy--current
+ ivy-text)))
+ (unless (equal item "")
+ (set hist (cons (propertize item 'ivy-index ivy--index)
+ (delete item
+ (cdr (symbol-value hist)))))))
+ res)))
+ (remove-hook 'post-command-hook #'ivy--exhibit)
+ (when (setq unwind (ivy-state-unwind ivy-last))
+ (funcall unwind)))
+ (ivy-call)
+ (when recursive-ivy-last
+ (ivy--reset-state (setq ivy-last recursive-ivy-last))))))
(defun ivy--reset-state (state)
"Reset the ivy to STATE.
This is useful for recursive `ivy-read'."
- (let ((prompt (ivy-state-prompt state))
+ (let ((prompt (or (ivy-state-prompt state) ""))
(collection (ivy-state-collection state))
(predicate (ivy-state-predicate state))
(history (ivy-state-history state))
(dynamic-collection (ivy-state-dynamic-collection state))
(initial-input (ivy-state-initial-input state))
(require-match (ivy-state-require-match state))
- (matcher (ivy-state-matcher state)))
+ (caller (ivy-state-caller state)))
(unless initial-input
(setq initial-input (cdr (assoc this-command
ivy-initial-inputs-alist))))
(setq ivy--directory nil)
+ (setq ivy-case-fold-search 'auto)
(setq ivy--regex-function
(or re-builder
(and (functionp collection)
(cdr (assoc collection ivy-re-builders-alist)))
+ (and caller
+ (cdr (assoc caller ivy-re-builders-alist)))
(cdr (assoc t ivy-re-builders-alist))
'ivy--regex))
(setq ivy--subexps 0)
(string= preselect-directory
default-directory))
(setq ivy--directory preselect-directory))
- (setq preselect (file-name-nondirectory preselect))))
+ (setf
+ (ivy-state-preselect state)
+ (setq preselect (file-name-nondirectory preselect)))))
(setq coll (ivy--sorted-files ivy--directory))
(when initial-input
(unless (or require-match
((or (functionp collection)
(byte-code-function-p collection)
(vectorp collection)
- (listp (car collection)))
+ (and (consp collection) (listp (car collection)))
+ (hash-table-p collection))
(setq coll (all-completions "" collection predicate)))
- ((hash-table-p collection)
- (error "Hash table as a collection unsupported"))
(t
(setq coll collection)))
(when sort
(when preselect
(unless (or (and require-match
(not (eq collection 'internal-complete-buffer)))
- (let ((re (format "\\`%s" (regexp-quote preselect))))
+ dynamic-collection
+ (let ((re (regexp-quote preselect)))
(cl-find-if (lambda (x) (string-match re x))
coll)))
(setq coll (cons preselect coll))))
- (setq ivy--index (or
- (and dynamic-collection
- ivy--index)
- (and preselect
- (ivy--preselect-index
- coll initial-input preselect matcher))
- 0))
(setq ivy--old-re nil)
(setq ivy--old-cands nil)
- (setq ivy--all-candidates coll))
+ (when (integerp preselect)
+ (setq ivy--old-re "")
+ (setq ivy--index preselect))
+ (when initial-input
+ ;; Needed for anchor to work
+ (setq ivy--old-cands coll)
+ (setq ivy--old-cands (ivy--filter initial-input coll)))
+ (setq ivy--all-candidates coll)
+ (unless (integerp preselect)
+ (setq ivy--index (or
+ (and dynamic-collection
+ ivy--index)
+ (and preselect
+ (ivy--preselect-index
+ preselect
+ (if initial-input
+ ivy--old-cands
+ coll)))
+ 0))))
(setq ivy-exit nil)
- (setq ivy--default (or (thing-at-point 'symbol) ""))
+ (setq ivy--default (or
+ (thing-at-point 'url)
+ (thing-at-point 'symbol)
+ ""))
(setq ivy--prompt
(cond ((string-match "%.*d" prompt)
prompt)
((null ivy-count-format)
- nil)
+ (error
+ "`ivy-count-format' can't be nil. Set it to an empty string instead"))
((string-match "%d.*%d" ivy-count-format)
(let ((w (length (number-to-string
(length ivy--all-candidates))))
;;;###autoload
(defun ivy-completing-read (prompt collection
&optional predicate require-match initial-input
- history def _inherit-input-method)
+ history def inherit-input-method)
"Read a string in the minibuffer, with completion.
- This is an interface that conforms to `completing-read', so that
- it can be used for `completing-read-function'.
+ This interface conforms to `completing-read' and can be used for
+ `completing-read-function'.
PROMPT is a string to prompt with; normally it ends in a colon and a space.
COLLECTION can be a list of strings, an alist, an obarray or a hash table.
PREDICATE limits completion to a subset of COLLECTION.
- REQUIRE-MATCH is considered boolean. See `completing-read'.
+ REQUIRE-MATCH is specified with a boolean value. See `completing-read'.
INITIAL-INPUT is a string that can be inserted into the minibuffer initially.
- _HISTORY is ignored for now.
+ HISTORY is a list of previously selected inputs.
DEF is the default value.
- _INHERIT-INPUT-METHOD is ignored for now.
-
- The history, defaults and input-method arguments are ignored for now."
- (ivy-read (replace-regexp-in-string "%" "%%" prompt)
- collection
- :predicate predicate
- :require-match require-match
- :initial-input (if (consp initial-input)
- (car initial-input)
- (if (and (stringp initial-input)
- (string-match "\\+" initial-input))
- (replace-regexp-in-string
- "\\+" "\\\\+" initial-input)
- initial-input))
- :preselect (if (listp def) (car def) def)
- :history history
- :keymap nil
- :sort
- (let ((sort (assoc this-command ivy-sort-functions-alist)))
- (if sort
- (cdr sort)
- t))))
+ INHERIT-INPUT-METHOD is currently ignored."
+ (if (memq this-command '(tmm-menubar tmm-shortcut))
+ (completing-read-default prompt collection
+ predicate require-match
+ initial-input history
+ def inherit-input-method)
+ ;; See the doc of `completing-read'.
+ (when (consp history)
+ (when (numberp (cdr history))
+ (setq initial-input (nth (1- (cdr history))
+ (symbol-value (car history)))))
+ (setq history (car history)))
+ (ivy-read (replace-regexp-in-string "%" "%%" prompt)
+ collection
+ :predicate predicate
+ :require-match require-match
+ :initial-input (if (consp initial-input)
+ (car initial-input)
+ (if (and (stringp initial-input)
+ (string-match "\\+" initial-input))
+ (replace-regexp-in-string
+ "\\+" "\\\\+" initial-input)
+ initial-input))
+ :preselect (if (listp def) (car def) def)
+ :history history
+ :keymap nil
+ :sort
+ (let ((sort (assoc this-command ivy-sort-functions-alist)))
+ (if sort
+ (cdr sort)
+ t)))))
;;;###autoload
(define-minor-mode ivy-mode
"Toggle Ivy mode on or off.
- With ARG, turn Ivy mode on if arg is positive, off otherwise.
- Turning on Ivy mode will set `completing-read-function' to
+ Turn Ivy mode on if ARG is positive, off otherwise.
+ Turning on Ivy mode sets `completing-read-function' to
`ivy-completing-read'.
Global bindings:
(setq completing-read-function 'ivy-completing-read)
(setq completing-read-function 'completing-read-default)))
- (defun ivy--preselect-index (candidates initial-input preselect matcher)
- "Return the index in CANDIDATES filtered by INITIAL-INPUT for PRESELECT.
- When MATCHER is non-nil it's used instead of `cl-remove-if-not'."
- (if initial-input
- (progn
- (setq initial-input (ivy--regex-plus initial-input))
- (setq candidates
- (if matcher
- (funcall matcher initial-input candidates)
- (cl-remove-if-not
- (lambda (x)
- (string-match initial-input x))
- candidates))))
- (when matcher
- (setq candidates (funcall matcher "" candidates))))
- (or (cl-position preselect candidates :test #'equal)
- (cl-position-if
- (lambda (x)
- (string-match (regexp-quote preselect) x))
- candidates)))
+ (defun ivy--preselect-index (preselect candidates)
+ "Return the index of PRESELECT in CANDIDATES."
+ (cond ((integerp preselect)
+ preselect)
+ ((cl-position preselect candidates :test #'equal))
+ ((stringp preselect)
+ (let ((re (regexp-quote preselect)))
+ (cl-position-if
+ (lambda (x)
+ (string-match re x))
+ candidates)))))
;;* Implementation
;;** Regex
(nreverse res)))
(defun ivy--regex (str &optional greedy)
- "Re-build regex from STR in case it has a space.
+ "Re-build regex pattern from STR in case it has a space.
When GREEDY is non-nil, join words in a greedy way."
(let ((hashed (unless greedy
(gethash str ivy--regex-hash))))
ivy--regex-hash)))))
(defun ivy--regex-ignore-order (str)
- "Re-build regex from STR by splitting it on spaces.
- Ignore the order of each group."
+ "Re-build regex from STR by splitting at spaces.
+ Ignore the order of each group.
+
+ ATTENTION: This is just a proof of concept and may not work as
+ expected. Besides ignoring the order of the tokens where 'foo'
+ and 'bar', 'bar' and 'foo' are matched, it also matches multiple
+ occurrences of 'foo' and 'bar'. To ignore the sort order and avoid
+ multiple matches, use `ivy-restrict-to-matches' instead.
+ "
(let* ((subs (split-string str " +" t))
(len (length subs)))
(cl-case len
(defun ivy--regex-plus (str)
"Build a regex sequence from STR.
- Spaces are wild, everything before \"!\" should match.
- Everything after \"!\" should not match."
+ Spaces are wild card characters, everything before \"!\" should
+ match. Everything after \"!\" should not match."
(let ((parts (split-string str "!" t)))
(cl-case (length parts)
(0
"Build a regex sequence from STR.
Insert .* between each char."
(if (string-match "\\`\\(\\^?\\)\\(.*?\\)\\(\\$?\\)\\'" str)
- (concat (match-string 1 str)
- (mapconcat #'string (string-to-list (match-string 2 str)) ".*")
- (match-string 3 str))
+ (prog1
+ (concat (match-string 1 str)
+ (mapconcat
+ (lambda (x)
+ (format "\\(%c\\)" x))
+ (string-to-list (match-string 2 str)) ".*")
+ (match-string 3 str))
+ (setq ivy--subexps (length (match-string 2 str))))
str))
;;** Rest
"Update the prompt according to `ivy--prompt'."
(when ivy--prompt
(unless (memq this-command '(ivy-done ivy-alt-done ivy-partial-or-done
- counsel-find-symbol))
+ counsel-find-symbol))
(setq ivy--prompt-extra ""))
(let (head tail)
(if (string-match "\\(.*\\): \\'" ivy--prompt)
ivy--full-length)
ivy--length)))
ivy--prompt-extra
- tail)
- (if ivy--directory
- (abbreviate-file-name ivy--directory)
- ""))))
+ tail)))
+ (d-str (if ivy--directory
+ (abbreviate-file-name ivy--directory)
+ "")))
(save-excursion
(goto-char (point-min))
(delete-region (point-min) (minibuffer-prompt-end))
- (when (> (length n-str) (window-width))
- (setq n-str (concat (substring n-str 0
- (max (- (window-width) 30)
- 10)) "... ")))
+ (if (> (+ (mod (+ (length n-str) (length d-str)) (window-width))
+ (length ivy-text))
+ (window-width))
+ (setq n-str (concat n-str "\n" d-str))
+ (setq n-str (concat n-str d-str)))
+ (let ((regex (format "\\([^\n]\\{%d\\}\\)[^\n]" (window-width))))
+ (while (string-match regex n-str)
+ (setq n-str (replace-match (concat (match-string 1 n-str) "\n") nil t n-str 1))))
(set-text-properties 0 (length n-str)
`(face minibuffer-prompt ,@std-props)
n-str)
(constrain-to-field nil (point-max))))))
(defun ivy--set-match-props (str match props)
- "Set STR text proprties that match MATCH to PROPS."
+ "Set STR text properties that match MATCH to PROPS."
(when (string-match match str)
(set-text-properties
(match-beginning 0)
"Insert Ivy completions display.
Should be run via minibuffer `post-command-hook'."
(when (memq 'ivy--exhibit post-command-hook)
+ (let ((inhibit-field-text-motion nil))
+ (constrain-to-field nil (point-max)))
(setq ivy-text (ivy--input))
(if (ivy-state-dynamic-collection ivy-last)
;; while-no-input would cause annoying
(string-match "\\`[[:alpha:]]:/" default-directory))
(ivy--cd (match-string 0 default-directory))
(ivy--cd "/")))
- (when (string-match "[[:alpha:]]:/" ivy-text)
+ (when (string-match "[[:alpha:]]:/$" ivy-text)
(let ((drive-root (match-string 0 ivy-text)))
(when (file-exists-p drive-root)
(ivy--cd drive-root)))))
(ivy--buffer-list "" ivy-use-virtual-buffers)))
(setq ivy--old-re nil))))
(ivy--insert-minibuffer
- (ivy--format
- (ivy--filter ivy-text ivy--all-candidates)))
+ (with-current-buffer (ivy-state-buffer ivy-last)
+ (ivy--format
+ (ivy--filter ivy-text ivy--all-candidates))))
(setq ivy--old-text ivy-text))))
(defun ivy--insert-minibuffer (text)
(ivy--resize-minibuffer-to-fit))))
(defun ivy--resize-minibuffer-to-fit ()
- "Resize the minibuffer window so it has enough space to display
- all of the text contained in the minibuffer."
+ "Resize the minibuffer window size to fit the text in the minibuffer."
(with-selected-window (minibuffer-window)
(if (fboundp 'window-text-pixel-size)
(let ((text-height (cdr (window-text-pixel-size)))
(body-height (window-body-height nil t)))
(when (> text-height body-height)
(window-resize nil (- text-height body-height) nil t t)))
- (let ((text-height (count-screen-lines))
- (body-height (window-body-height)))
- (when (> text-height body-height)
- (window-resize nil (- text-height body-height) nil t))))))
+ (let ((text-height (count-screen-lines))
+ (body-height (window-body-height)))
+ (when (> text-height body-height)
+ (window-resize nil (- text-height body-height) nil t))))))
(declare-function colir-blend-face-background "ext:colir")
(font-lock-append-text-property 0 (length str) 'face face str))))
str)
+ (declare-function flx-make-string-cache "ext:flx")
+ (declare-function flx-score "ext:flx")
+
+ (defvar ivy--flx-cache nil)
+
+ (eval-after-load 'flx
+ '(setq ivy--flx-cache (flx-make-string-cache)))
+
+ (defun ivy-toggle-case-fold ()
+ "Toggle the case folding between nil and auto.
+ In any completion session, the case folding starts in auto:
+
+ - when the input is all lower case, `case-fold-search' is t
+ - otherwise nil.
+
+ You can toggle this to make `case-fold-search' nil regardless of input."
+ (interactive)
+ (setq ivy-case-fold-search
+ (if ivy-case-fold-search
+ nil
+ 'auto))
+ ;; reset cache so that the candidate list updates
+ (setq ivy--old-re nil))
+
(defun ivy--filter (name candidates)
"Return all items that match NAME in CANDIDATES.
CANDIDATES are assumed to be static."
- (let* ((re (funcall ivy--regex-function name))
- (re-str (if (listp re) (caar re) re))
- (matcher (ivy-state-matcher ivy-last))
- (case-fold-search (string= name (downcase name)))
- (cands (cond
- (matcher
- (funcall matcher re candidates))
- ((and (equal re ivy--old-re)
- ivy--old-cands)
- ivy--old-cands)
- ((and ivy--old-re
- (stringp re)
- (stringp ivy--old-re)
- (not (string-match "\\\\" ivy--old-re))
- (not (equal ivy--old-re ""))
- (memq (cl-search
- (if (string-match "\\\\)\\'" ivy--old-re)
- (substring ivy--old-re 0 -2)
- ivy--old-re)
- re)
- '(0 2)))
- (ignore-errors
- (cl-remove-if-not
- (lambda (x) (string-match re x))
- ivy--old-cands)))
- (t
- (let ((re-list (if (stringp re) (list (cons re t)) re))
- (res candidates))
- (dolist (re re-list)
- (setq res
- (ignore-errors
- (funcall
- (if (cdr re)
- #'cl-remove-if-not
- #'cl-remove-if)
- (let ((re (car re)))
- (lambda (x) (string-match re x)))
- res))))
- res))))
- (tail (nthcdr ivy--index ivy--old-cands))
- idx)
- (when (and tail ivy--old-cands (not (equal "^" ivy--old-re)))
- (unless (and (not (equal re-str ivy--old-re))
- (or (setq ivy--index
- (or
- (cl-position (if (and (> (length re-str) 0)
- (eq ?^ (aref re-str 0)))
- (substring re-str 1)
- re-str) cands
- :test #'equal)
- (and ivy--directory
- (cl-position
- (concat re-str "/") cands
- :test #'equal))))))
- (while (and tail (null idx))
- ;; Compare with eq to handle equal duplicates in cands
- (setq idx (cl-position (pop tail) cands)))
- (setq ivy--index (or idx 0))))
- (when (and (string= name "") (not (equal ivy--old-re "")))
+ (let ((re (funcall ivy--regex-function name)))
+ (if (and (equal re ivy--old-re)
+ ivy--old-cands)
+ ;; quick caching for "C-n", "C-p" etc.
+ ivy--old-cands
+ (let* ((re-str (if (listp re) (caar re) re))
+ (matcher (ivy-state-matcher ivy-last))
+ (case-fold-search
+ (and ivy-case-fold-search
+ (string= name (downcase name))))
+ (cands (cond
+ (matcher
+ (funcall matcher re candidates))
+ ((and ivy--old-re
+ (stringp re)
+ (stringp ivy--old-re)
+ (not (string-match "\\\\" ivy--old-re))
+ (not (equal ivy--old-re ""))
+ (memq (cl-search
+ (if (string-match "\\\\)\\'" ivy--old-re)
+ (substring ivy--old-re 0 -2)
+ ivy--old-re)
+ re)
+ '(0 2)))
+ (ignore-errors
+ (cl-remove-if-not
+ (lambda (x) (string-match re x))
+ ivy--old-cands)))
+ (t
+ (let ((re-list (if (stringp re) (list (cons re t)) re))
+ (res candidates))
+ (dolist (re re-list)
+ (setq res
+ (ignore-errors
+ (funcall
+ (if (cdr re)
+ #'cl-remove-if-not
+ #'cl-remove-if)
+ (let ((re-str (car re)))
+ (lambda (x) (string-match re-str x)))
+ res))))
+ res)))))
+ (ivy--recompute-index name re-str cands)
+ (setq ivy--old-re (if cands re-str ""))
+ (setq ivy--old-cands (ivy--sort name cands))))))
+
+ (defcustom ivy-sort-matches-functions-alist '((t . nil))
+ "An alist of functions used to sort the matching candidates.
+
+ This is different from `ivy-sort-functions-alist', which is used
+ to sort the whole collection only once. The functions taken from
+ here are instead used on each input change, but they are used
+ only on already matching candidates, not on all of them.
+
+ The alist KEY is a collection function or t to match previously
+ not matched collection functions.
+
+ The alist VAL is a sorting function with the signature of
+ `ivy--prefix-sort'.")
+
+ (defun ivy--sort-files-by-date (_name candidates)
+ "Re-soft CANDIDATES according to file modification date."
+ (let ((default-directory ivy--directory))
+ (cl-sort (copy-sequence candidates)
+ (lambda (f1 f2)
+ (time-less-p
+ (nth 5 (file-attributes f2))
+ (nth 5 (file-attributes f1)))))))
+
+ (defun ivy--sort (name candidates)
+ "Re-sort CANDIDATES by NAME.
+ All CANDIDATES are assumed to match NAME."
+ (let ((key (or (ivy-state-caller ivy-last)
+ (when (functionp (ivy-state-collection ivy-last))
+ (ivy-state-collection ivy-last))))
+ fun)
+ (cond ((and (require 'flx nil 'noerror)
+ (eq ivy--regex-function 'ivy--regex-fuzzy))
+ (ivy--flx-sort name candidates))
+ ((setq fun (cdr (or (assoc key ivy-sort-matches-functions-alist)
+ (assoc t ivy-sort-matches-functions-alist))))
+ (funcall fun name candidates))
+ (t
+ candidates))))
+
+ (defun ivy--prefix-sort (name candidates)
+ "Re-sort CANDIDATES.
+ Prefix matches to NAME are put ahead of the list."
+ (if (or (string-match "^\\^" name) (string= name ""))
+ candidates
+ (let ((re-prefix (concat "^" (funcall ivy--regex-function name)))
+ res-prefix
+ res-noprefix)
+ (dolist (s candidates)
+ (if (string-match re-prefix s)
+ (push s res-prefix)
+ (push s res-noprefix)))
+ (nconc
+ (nreverse res-prefix)
+ (nreverse res-noprefix)))))
+
+ (defun ivy--recompute-index (name re-str cands)
+ (let* ((caller (ivy-state-caller ivy-last))
+ (func (or (and caller (cdr (assoc caller ivy-index-functions-alist)))
+ (cdr (assoc t ivy-index-functions-alist))
+ #'ivy-recompute-index-zero)))
+ (unless (eq this-command 'ivy-resume)
(setq ivy--index
- (or (cl-position (ivy-state-preselect ivy-last)
- cands :test #'equal)
- ivy--index)))
- (setq ivy--old-re (if cands re-str ""))
- (setq ivy--old-cands cands)))
+ (or
+ (cl-position (if (and (> (length re-str) 0)
+ (eq ?^ (aref re-str 0)))
+ (substring re-str 1)
+ re-str) cands
+ :test #'equal)
+ (and ivy--directory
+ (cl-position
+ (concat re-str "/") cands
+ :test #'equal))
+ (and (not (string= name ""))
+ (not (and (require 'flx nil 'noerror)
+ (eq ivy--regex-function 'ivy--regex-fuzzy)
+ (< (length cands) 200)))
+
+ (cl-position (nth ivy--index ivy--old-cands)
+ cands))
+ (funcall func re-str cands))))
+ (when (and (or (string= name "")
+ (string= name "^"))
+ (not (equal ivy--old-re "")))
+ (setq ivy--index
+ (or (ivy--preselect-index
+ (ivy-state-preselect ivy-last)
+ cands)
+ ivy--index)))))
+
+ (defun ivy-recompute-index-swiper (_re-str cands)
+ (let ((tail (nthcdr ivy--index ivy--old-cands))
+ idx)
+ (if (and tail ivy--old-cands (not (equal "^" ivy--old-re)))
+ (progn
+ (while (and tail (null idx))
+ ;; Compare with eq to handle equal duplicates in cands
+ (setq idx (cl-position (pop tail) cands)))
+ (or idx 0))
+ (if ivy--old-cands
+ ivy--index
+ ;; already in ivy-state-buffer
+ (let ((n (line-number-at-pos))
+ (res 0)
+ (i 0))
+ (dolist (c cands)
+ (when (eq n (read (get-text-property 0 'display c)))
+ (setq res i))
+ (cl-incf i))
+ res)))))
+
+ (defun ivy-recompute-index-swiper-async (_re-str cands)
+ (let ((tail (nthcdr ivy--index ivy--old-cands))
+ idx)
+ (if (and tail ivy--old-cands (not (equal "^" ivy--old-re)))
+ (progn
+ (while (and tail (null idx))
+ ;; Compare with `equal', since the collection is re-created
+ ;; each time with `split-string'
+ (setq idx (cl-position (pop tail) cands :test #'equal)))
+ (or idx 0))
+ ivy--index)))
+
+ (defun ivy-recompute-index-zero (_re-str _cands)
+ 0)
+
+ (defun ivy--flx-sort (name cands)
+ "Sort according to closeness to string NAME the string list CANDS."
+ (condition-case nil
+ (if (and cands
+ (< (length cands) 200))
+ (let* ((flx-name (if (string-match "^\\^" name)
+ (substring name 1)
+ name))
+ (cands-with-score
+ (delq nil
+ (mapcar
+ (lambda (x)
+ (let ((score (car (flx-score x flx-name ivy--flx-cache))))
+ (and score
+ (cons score x))))
+ cands))))
+ (if cands-with-score
+ (mapcar #'cdr
+ (sort cands-with-score
+ (lambda (x y)
+ (> (car x) (car y)))))
+ cands))
+ cands)
+ (error
+ cands)))
- (defvar ivy-format-function 'ivy-format-function-default
+ (defcustom ivy-format-function 'ivy-format-function-default
"Function to transform the list of candidates into a string.
- This string will be inserted into the minibuffer.")
-
- (defun ivy-format-function-default (cands)
- "Transform CANDS into a string for minibuffer."
- (if (bound-and-true-p truncate-lines)
- (mapconcat #'identity cands "\n")
- (let ((ww (- (window-width)
- (if (and (boundp 'fringe-mode) (eq fringe-mode 0)) 1 0))))
- (mapconcat
- (lambda (s)
- (if (> (length s) ww)
- (concat (substring s 0 (- ww 3)) "...")
- s))
- cands "\n"))))
-
- (defun ivy-format-function-arrow (cands)
- "Transform CANDS into a string for minibuffer."
+ This string is inserted into the minibuffer."
+ :type '(choice
+ (const :tag "Default" ivy-format-function-default)
+ (const :tag "Arrow prefix" ivy-format-function-arrow)
+ (const :tag "Full line" ivy-format-function-line)))
+
+ (defun ivy--truncate-string (str width)
+ "Truncate STR to WIDTH."
+ (if (> (string-width str) width)
+ (concat (substring str 0 (min (- width 3)
+ (- (length str) 3))) "...")
+ str))
+
+ (defun ivy--format-function-generic (selected-fn other-fn cand-pairs separator)
+ "Transform CAND-PAIRS into a string for minibuffer.
+ SELECTED-FN and OTHER-FN each take two string arguments.
+ SEPARATOR is used to join the candidates."
(let ((i -1))
(mapconcat
- (lambda (s)
- (concat (if (eq (cl-incf i) ivy--index)
- "> "
- " ")
- s))
- cands "\n")))
-
- (defcustom swiper-minibuffer-faces
- '(swiper-minibuffer-match-face-1
- swiper-minibuffer-match-face-2
- swiper-minibuffer-match-face-3
- swiper-minibuffer-match-face-4)
- "List of `swiper' faces for minibuffer group matches.")
+ (lambda (pair)
+ (let ((str (car pair))
+ (extra (cdr pair))
+ (curr (eq (cl-incf i) ivy--index)))
+ (if curr
+ (funcall selected-fn str extra)
+ (funcall other-fn str extra))))
+ cand-pairs
+ separator)))
+
+ (defun ivy-format-function-default (cand-pairs)
+ "Transform CAND-PAIRS into a string for minibuffer."
+ (ivy--format-function-generic
+ (lambda (str extra)
+ (concat (ivy--add-face str 'ivy-current-match) extra))
+ #'concat
+ cand-pairs
+ "\n"))
+
+ (defun ivy-format-function-arrow (cand-pairs)
+ "Transform CAND-PAIRS into a string for minibuffer."
+ (ivy--format-function-generic
+ (lambda (str extra)
+ (concat "> " (ivy--add-face str 'ivy-current-match) extra))
+ (lambda (str extra)
+ (concat " " str extra))
+ cand-pairs
+ "\n"))
+
+ (defun ivy-format-function-line (cand-pairs)
+ "Transform CAND-PAIRS into a string for minibuffer."
+ (ivy--format-function-generic
+ (lambda (str extra)
+ (ivy--add-face (concat str extra "\n") 'ivy-current-match))
+ (lambda (str extra)
+ (concat str extra "\n"))
+ cand-pairs
+ ""))
+
+ (defcustom ivy-minibuffer-faces
+ '(ivy-minibuffer-match-face-1
+ ivy-minibuffer-match-face-2
+ ivy-minibuffer-match-face-3
+ ivy-minibuffer-match-face-4)
+ "List of `ivy' faces for minibuffer group matches.")
(defun ivy--format-minibuffer-line (str)
(let ((start 0)
(while (<= i ivy--subexps)
(let ((face
(cond ((zerop ivy--subexps)
- (cadr swiper-minibuffer-faces))
+ (cadr ivy-minibuffer-faces))
((zerop i)
- (car swiper-minibuffer-faces))
+ (car ivy-minibuffer-faces))
(t
- (nth (1+ (mod (+ i 2) (1- (length swiper-minibuffer-faces))))
- swiper-minibuffer-faces)))))
+ (nth (1+ (mod (+ i 2) (1- (length ivy-minibuffer-faces))))
+ ivy-minibuffer-faces)))))
(if (fboundp 'add-face-text-property)
(add-face-text-property
(match-beginning i)
(start (max 0 (min start (- end (1- ivy-height)))))
(cands (cl-subseq cands start end))
(index (- ivy--index start)))
- (when ivy--directory
- (setq cands (mapcar (lambda (x)
- (if (string-match-p "/\\'" x)
- (propertize x 'face 'ivy-subdir)
- x))
- cands)))
+ (cond (ivy--directory
+ (setq cands (mapcar (lambda (x)
+ (if (string-match-p "/\\'" x)
+ (propertize x 'face 'ivy-subdir)
+ x))
+ cands)))
+ ((eq (ivy-state-collection ivy-last) 'internal-complete-buffer)
+ (setq cands (mapcar (lambda (x)
+ (let ((b (get-buffer x)))
+ (if (and b
+ (buffer-file-name b)
+ (buffer-modified-p b))
+ (propertize x 'face 'ivy-modified-buffer)
+ x)))
+ cands))))
(setq ivy--current (copy-sequence (nth index cands)))
- (setq cands (mapcar
- #'ivy--format-minibuffer-line
- cands))
- (setf (nth index cands)
- (ivy--add-face (nth index cands) 'ivy-current-match))
(let* ((ivy--index index)
- (res (concat "\n" (funcall ivy-format-function cands))))
+ (cand-pairs (mapcar
+ (lambda (cand)
+ (cons (ivy--format-minibuffer-line cand) nil)) cands))
+ (res (concat "\n" (funcall ivy-format-function cand-pairs))))
(put-text-property 0 (length res) 'read-only nil res)
res))))
(defvar recentf-list)
- (defface ivy-virtual '((t :inherit font-lock-builtin-face))
- "Face used by Ivy for matching virtual buffer names.")
+ (defcustom ivy-virtual-abbreviate 'name
+ "The mode of abbreviation for virtual buffer names."
+ :type '(choice
+ (const :tag "Only name" name)
+ (const :tag "Full path" full)
+ ;; eventually, uniquify
+ ))
(defun ivy--virtual-buffers ()
"Adapted from `ido-add-virtual-buffers-to-list'."
(delq nil (mapcar (lambda (bookmark)
(cdr (assoc 'filename bookmark)))
bookmarks)))))
- (setq name (file-name-nondirectory head))
+ (setq name
+ (if (eq ivy-virtual-abbreviate 'name)
+ (file-name-nondirectory head)
+ (expand-file-name head)))
(when (equal name "")
(setq name (file-name-nondirectory (directory-file-name head))))
(when (equal name "")
(goto-char pt)
(setq amend (buffer-substring-no-properties pt (point))))))
(when amend
- (insert amend))))
+ (insert (replace-regexp-in-string " +" " " amend)))))
(defun ivy-kill-ring-save ()
"Store the current candidates into the kill ring.
(defun ivy-reverse-i-search ()
"Enter a recursive `ivy-read' session using the current history.
- The selected history element will be inserted into the minibufer."
+ The selected history element will be inserted into the minibuffer."
(interactive)
(let ((enable-recursive-minibuffers t)
(history (symbol-value (ivy-state-history ivy-last)))
(setq ivy--all-candidates
(ivy--filter ivy-text ivy--all-candidates)))
+ ;;* Occur
+ (defvar-local ivy-occur-last nil
+ "Buffer-local value of `ivy-last'.
+ Can't re-use `ivy-last' because using e.g. `swiper' in the same
+ buffer would modify `ivy-last'.")
+
+ (defvar ivy-occur-mode-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map [mouse-1] 'ivy-occur-click)
+ (define-key map (kbd "RET") 'ivy-occur-press)
+ (define-key map (kbd "j") 'next-line)
+ (define-key map (kbd "k") 'previous-line)
+ (define-key map (kbd "h") 'backward-char)
+ (define-key map (kbd "l") 'forward-char)
+ (define-key map (kbd "g") 'ivy-occur-press)
+ (define-key map (kbd "a") 'ivy-occur-read-action)
+ (define-key map (kbd "o") 'ivy-occur-dispatch)
+ (define-key map (kbd "q") 'quit-window)
+ map)
+ "Keymap for Ivy Occur mode.")
+
+ (define-derived-mode ivy-occur-mode fundamental-mode "Ivy-Occur"
+ "Major mode for output from \\[ivy-occur].
+
+ \\{ivy-occur-mode-map}")
+
+ (defvar ivy-occur-grep-mode-map
+ (let ((map (copy-keymap ivy-occur-mode-map)))
+ (define-key map (kbd "C-x C-q") 'ivy-wgrep-change-to-wgrep-mode)
+ map)
+ "Keymap for Ivy Occur Grep mode.")
+
+ (define-derived-mode ivy-occur-grep-mode grep-mode "Ivy-Occur"
+ "Major mode for output from \\[ivy-occur].
+
+ \\{ivy-occur-grep-mode-map}")
+
+ (defvar counsel-git-grep-cmd)
+
+ (defun ivy-occur ()
+ "Stop completion and put the current matches into a new buffer.
+
+ The new buffer remembers current action(s).
+
+ While in the *ivy-occur* buffer, selecting a candidate with RET or
+ a mouse click will call the appropriate action for that candidate.
+
+ There is no limit on the number of *ivy-occur* buffers."
+ (interactive)
+ (let ((buffer
+ (generate-new-buffer
+ (format "*ivy-occur%s \"%s\"*"
+ (let (caller)
+ (if (setq caller (ivy-state-caller ivy-last))
+ (concat " " (prin1-to-string caller))
+ ""))
+ ivy-text)))
+ (do-grep (eq (ivy-state-caller ivy-last) 'counsel-git-grep)))
+ (with-current-buffer buffer
+ (if do-grep
+ (progn
+ (setq ivy--old-cands
+ (split-string
+ (shell-command-to-string
+ (format counsel-git-grep-cmd ivy--old-re))
+ "\n"
+ t))
+ (ivy-occur-grep-mode))
+ (ivy-occur-mode))
+ (setf (ivy-state-text ivy-last) ivy-text)
+ (setq ivy-occur-last ivy-last)
+ (setq-local ivy--directory ivy--directory)
+ (let ((inhibit-read-only t))
+ (erase-buffer)
+ (when do-grep
+ ;; Need precise number of header lines for `wgrep' to work.
+ (insert (format "-*- mode:grep; default-directory: %S -*-\n\n\n"
+ default-directory)))
+ (insert (format "%d candidates:\n" (length ivy--old-cands)))
+ (dolist (cand ivy--old-cands)
+ (let ((str (if do-grep
+ (concat "./" cand)
+ (concat " " cand))))
+ (add-text-properties
+ 0 (length str)
+ `(mouse-face
+ highlight
+ help-echo "mouse-1: call ivy-action")
+ str)
+ (insert str "\n")))))
+ (ivy-exit-with-action
+ `(lambda (_) (pop-to-buffer ,buffer)))))
+
+ (declare-function wgrep-change-to-wgrep-mode "ext:wgrep")
+
+ (defun ivy-wgrep-change-to-wgrep-mode ()
+ "Forward to `wgrep-change-to-wgrep-mode'."
+ (interactive)
+ (if (require 'wgrep nil 'noerror)
+ (wgrep-change-to-wgrep-mode)
+ (error "Package wgrep isn't installed")))
+
+ (defun ivy-occur-read-action ()
+ "Select one of the available actions as the current one."
+ (interactive)
+ (let ((ivy-last ivy-occur-last))
+ (ivy-read-action)))
+
+ (defun ivy-occur-dispatch ()
+ "Call one of the available actions on the current item."
+ (interactive)
+ (let* ((state-action (ivy-state-action ivy-occur-last))
+ (actions (if (symbolp state-action)
+ state-action
+ (copy-sequence state-action))))
+ (unwind-protect
+ (progn
+ (ivy-occur-read-action)
+ (ivy-occur-press))
+ (setf (ivy-state-action ivy-occur-last) actions))))
+
+ (defun ivy-occur-click (event)
+ "Execute action for the current candidate.
+ EVENT gives the mouse position."
+ (interactive "e")
+ (let ((window (posn-window (event-end event)))
+ (pos (posn-point (event-end event))))
+ (with-current-buffer (window-buffer window)
+ (goto-char pos)
+ (ivy-occur-press))))
+
+ (defun ivy-occur-press ()
+ "Execute action for the current candidate."
+ (interactive)
+ (require 'pulse)
+ (when (save-excursion
+ (beginning-of-line)
+ (looking-at "\\(?:./\\| \\)\\(.*\\)$"))
+ (let* ((ivy-last ivy-occur-last)
+ (ivy-text (ivy-state-text ivy-last))
+ (str (buffer-substring
+ (match-beginning 1)
+ (match-end 1)))
+ (coll (ivy-state-collection ivy-last))
+ (action (ivy--get-action ivy-last))
+ (ivy-exit 'done))
+ (with-ivy-window
+ (funcall action
+ (if (and (consp coll)
+ (consp (car coll)))
+ (cdr (assoc str coll))
+ str))
+ (if (memq (ivy-state-caller ivy-last)
+ '(swiper counsel-git-grep))
+ (with-current-buffer (window-buffer (selected-window))
+ (swiper--cleanup)
+ (swiper--add-overlays
+ (ivy--regex ivy-text)
+ (line-beginning-position)
+ (line-end-position)
+ (selected-window))
+ (run-at-time 0.5 nil 'swiper--cleanup))
+ (pulse-momentary-highlight-one-line (point)))))))
+
(provide 'ivy)
;;; ivy.el ends here
;; Author: Oleh Krehel <ohwoeowho@gmail.com>
;; URL: https://github.com/abo-abo/swiper
- ;; Version: 0.5.1
+ ;; Version: 0.7.0
;; Package-Requires: ((emacs "24.1"))
;; Keywords: matching
'((t (:inherit isearch-fail)))
"Face for `swiper' matches modulo 3.")
- (defface swiper-minibuffer-match-face-1
- '((((class color) (background light))
- :background "#d3d3d3")
- (((class color) (background dark))
- :background "#555555"))
- "The background face for `swiper' minibuffer matches."
- :group 'function-args-faces)
-
- (defface swiper-minibuffer-match-face-2
- '((((class color) (background light))
- :background "#e99ce8" :weight bold)
- (((class color) (background dark))
- :background "#777777" :weight bold))
- "Face for `swiper' minibuffer matches modulo 1.")
-
- (defface swiper-minibuffer-match-face-3
- '((((class color) (background light))
- :background "#bbbbff" :weight bold)
- (((class color) (background dark))
- :background "#7777ff" :weight bold))
- "Face for `swiper' minibuffer matches modulo 2.")
-
- (defface swiper-minibuffer-match-face-4
- '((((class color) (background light))
- :background "#ffbbff" :weight bold)
- (((class color) (background dark))
- :background "#8a498a" :weight bold))
- "Face for `swiper' minibuffer matches modulo 3.")
+ (define-obsolete-face-alias 'swiper-minibuffer-match-face-1
+ 'ivy-minibuffer-match-face-1 "0.6.0")
+
+ (define-obsolete-face-alias 'swiper-minibuffer-match-face-2
+ 'ivy-minibuffer-match-face-2 "0.6.0")
+
+ (define-obsolete-face-alias 'swiper-minibuffer-match-face-3
+ 'ivy-minibuffer-match-face-3 "0.6.0")
+
+ (define-obsolete-face-alias 'swiper-minibuffer-match-face-4
+ 'ivy-minibuffer-match-face-4 "0.6.0")
(defface swiper-line-face
'((t (:inherit highlight)))
(define-key map (kbd "M-q") 'swiper-query-replace)
(define-key map (kbd "C-l") 'swiper-recenter-top-bottom)
(define-key map (kbd "C-'") 'swiper-avy)
+ (define-key map (kbd "C-7") 'swiper-mc)
+ (define-key map (kbd "C-c C-f") 'swiper-toggle-face-matching)
map)
"Keymap for swiper.")
(let* ((enable-recursive-minibuffers t)
(from (ivy--regex ivy-text))
(to (query-replace-read-to from "Query replace" t)))
- (delete-minibuffer-contents)
- (ivy-set-action (lambda (_)
- (with-ivy-window
- (move-beginning-of-line 1)
- (perform-replace from to
- t t nil))))
(swiper--cleanup)
- (exit-minibuffer))))
+ (ivy-exit-with-action
+ (lambda (_)
+ (with-ivy-window
+ (move-beginning-of-line 1)
+ (perform-replace from to
+ t t nil)))))))
(defvar avy-background)
(defvar avy-all-windows)
+ (defvar avy-style)
+ (defvar avy-keys)
(declare-function avy--regex-candidates "ext:avy")
(declare-function avy--process "ext:avy")
(declare-function avy--overlay-post "ext:avy")
(declare-function avy-action-goto "ext:avy")
+ (declare-function avy--done "ext:avy")
+ (declare-function avy--make-backgrounds "ext:avy")
+ (declare-function avy-window-list "ext:avy")
+ (declare-function avy-read "ext:avy")
+ (declare-function avy-read-de-bruijn "ext:avy")
+ (declare-function avy-tree "ext:avy")
+ (declare-function avy-push-mark "ext:avy")
+ (declare-function avy--remove-leading-chars "ext:avy")
;;;###autoload
(defun swiper-avy ()
"Jump to one of the current swiper candidates."
(interactive)
(unless (string= ivy-text "")
- (with-ivy-window
- (let* ((avy-all-windows nil)
- (candidates
- (avy--regex-candidates
- (ivy--regex ivy-text)))
- (avy-background nil)
- (candidate
- (avy--process candidates #'avy--overlay-post)))
+ (let* ((avy-all-windows nil)
+ (candidates (append
+ (with-ivy-window
+ (avy--regex-candidates
+ (ivy--regex ivy-text)))
+ (save-excursion
+ (save-restriction
+ (narrow-to-region (window-start) (window-end))
+ (goto-char (point-min))
+ (forward-line)
+ (let ((cands))
+ (while (< (point) (point-max))
+ (push (cons (1+ (point))
+ (selected-window))
+ cands)
+ (forward-line))
+ cands)))))
+ (candidate (unwind-protect
+ (prog2
+ (avy--make-backgrounds
+ (append (avy-window-list)
+ (list (ivy-state-window ivy-last))))
+ (if (eq avy-style 'de-bruijn)
+ (avy-read-de-bruijn
+ candidates avy-keys)
+ (avy-read (avy-tree candidates avy-keys)
+ #'avy--overlay-post
+ #'avy--remove-leading-chars))
+ (avy-push-mark))
+ (avy--done))))
+ (if (window-minibuffer-p (cdr candidate))
+ (progn
+ (ivy-set-index (- (line-number-at-pos (car candidate)) 2))
+ (ivy--exhibit)
+ (ivy-done)
+ (ivy-call))
(ivy-quit-and-run
- (avy-action-goto candidate))))))
+ (avy-action-goto (caar candidate)))))))
+
+ (declare-function mc/create-fake-cursor-at-point "ext:multiple-cursors-core")
+ (declare-function multiple-cursors-mode "ext:multiple-cursors-core")
+
+ ;;;###autoload
+ (defun swiper-mc ()
+ (interactive)
+ (unless (require 'multiple-cursors nil t)
+ (error "multiple-cursors isn't installed"))
+ (let ((cands (nreverse ivy--old-cands)))
+ (unless (string= ivy-text "")
+ (ivy-exit-with-action
+ (lambda (_)
+ (let (cand)
+ (while (setq cand (pop cands))
+ (swiper--action cand)
+ (when cands
+ (mc/create-fake-cursor-at-point))))
+ (multiple-cursors-mode 1))))))
(defun swiper-recenter-top-bottom (&optional arg)
"Call (`recenter-top-bottom' ARG)."
gnus-summary-mode
gnus-article-mode
gnus-group-mode
- emms-playlist-mode erc-mode
+ emms-playlist-mode
+ emms-stream-mode
+ erc-mode
org-agenda-mode
dired-mode
jabber-chat-mode
elfeed-search-mode
+ elfeed-show-mode
fundamental-mode
Man-mode
woman-mode
mu4e-view-mode
- mu4e-headers-mode)))
+ mu4e-headers-mode
+ help-mode
+ debbugs-gnu-mode
+ occur-mode
+ occur-edit-mode
+ bongo-mode
+ eww-mode
+ twittering-mode
+ vc-dir-mode
+ w3m-mode)))
(unless (> (buffer-size) 100000)
(if (fboundp 'font-lock-ensure)
(font-lock-ensure)
(defvar swiper--width nil
"Store the amount of digits needed for the longest line nubmer.")
- (defun swiper--candidates ()
- "Return a list of this buffer lines."
+ (defvar swiper-use-visual-line nil
+ "When non-nil, use `line-move' instead of `forward-line'.")
+
+ (declare-function outline-show-all "outline")
+
+ (defun swiper--candidates (&optional numbers-width)
+ "Return a list of this buffer lines.
+
+ NUMBERS-WIDTH, when specified, is used for line numbers width
+ spec, instead of calculating it as the log of the buffer line
+ count."
+ (if (and visual-line-mode
+ ;; super-slow otherwise
+ (< (buffer-size) 20000))
+ (progn
+ (when (eq major-mode 'org-mode)
+ (require 'outline)
+ (if (fboundp 'outline-show-all)
+ (outline-show-all)
+ (with-no-warnings
+ (show-all))))
+ (setq swiper-use-visual-line t))
+ (setq swiper-use-visual-line nil))
(let ((n-lines (count-lines (point-min) (point-max))))
(unless (zerop n-lines)
- (setq swiper--width (1+ (floor (log n-lines 10))))
+ (setq swiper--width (or numbers-width
+ (1+ (floor (log n-lines 10)))))
(setq swiper--format-spec
(format "%%-%dd " swiper--width))
(let ((line-number 0)
+ (advancer (if swiper-use-visual-line
+ (lambda (arg) (line-move arg t))
+ #'forward-line))
candidates)
(save-excursion
(goto-char (point-min))
(swiper-font-lock-ensure)
(while (< (point) (point-max))
- (let ((str (concat " " (buffer-substring
- (line-beginning-position)
- (line-end-position)))))
+ (let ((str (concat
+ " "
+ (replace-regexp-in-string
+ "\t" " "
+ (if swiper-use-visual-line
+ (buffer-substring
+ (save-excursion
+ (beginning-of-visual-line)
+ (point))
+ (save-excursion
+ (end-of-visual-line)
+ (point)))
+ (buffer-substring
+ (point)
+ (line-end-position)))))))
+ (when (eq major-mode 'twittering-mode)
+ (remove-text-properties 0 (length str) '(field) str))
(put-text-property 0 1 'display
(format swiper--format-spec
(cl-incf line-number))
str)
(push str candidates))
- (forward-line 1))
+ (funcall advancer 1))
(nreverse candidates))))))
(defvar swiper--opoint 1
(interactive)
(swiper--ivy initial-input))
- (defvar swiper--anchor nil
- "A line number to which the search should be anchored.")
-
- (defvar swiper--len 0
- "The last length of input for which an anchoring was made.")
+ (declare-function evil-jumper--set-jump "ext:evil-jumper")
(defun swiper--init ()
"Perform initialization common to both completion methods."
(setq swiper--opoint (point))
- (setq swiper--len 0)
- (setq swiper--anchor (line-number-at-pos)))
+ (when (bound-and-true-p evil-jumper-mode)
+ (evil-jumper--set-jump)))
(defun swiper--re-builder (str)
"Transform STR into a swiper regex.
((equal str "")
"")
((equal str "^")
+ (setq ivy--subexps 0)
".")
((string-match "^\\^" str)
(setq ivy--old-re "")
(let ((re (ivy--regex-plus (substring str 1))))
- (format "^[0-9][0-9 ]\\{%d\\}%s"
- swiper--width
- (if (zerop ivy--subexps)
- (prog1 (format "\\(%s\\)" re)
- (setq ivy--subexps 1))
- re))))
+ (if (zerop ivy--subexps)
+ (prog1 (format "^ ?\\(%s\\)" re)
+ (setq ivy--subexps 1))
+ (format "^ %s" re))))
(t
(ivy--regex-plus str))))
(defvar swiper-history nil
"History for `swiper'.")
+ (defvar swiper-invocation-face nil
+ "The face at the point of invocation of `swiper'.")
+
(defun swiper--ivy (&optional initial-input)
"`isearch' with an overview using `ivy'.
When non-nil, INITIAL-INPUT is the initial search pattern."
(interactive)
(swiper--init)
+ (setq swiper-invocation-face
+ (plist-get (text-properties-at (point)) 'face))
(let ((candidates (swiper--candidates))
- (preselect (buffer-substring-no-properties
- (line-beginning-position)
- (line-end-position)))
+ (preselect
+ (if swiper-use-visual-line
+ (count-screen-lines
+ (point-min)
+ (save-excursion (beginning-of-visual-line) (point)))
+ (1- (line-number-at-pos))))
(minibuffer-allow-text-properties t)
res)
(unwind-protect
- (setq res (ivy-read
- "Swiper: "
- candidates
- :initial-input initial-input
- :keymap swiper-map
- :preselect preselect
- :require-match t
- :update-fn #'swiper--update-input-ivy
- :unwind #'swiper--cleanup
- :re-builder #'swiper--re-builder
- :history 'swiper-history))
- (if (null ivy-exit)
- (goto-char swiper--opoint)
- (swiper--action res ivy-text)))))
+ (setq res
+ (ivy-read
+ "Swiper: "
+ candidates
+ :initial-input initial-input
+ :keymap swiper-map
+ :preselect preselect
+ :require-match t
+ :update-fn #'swiper--update-input-ivy
+ :unwind #'swiper--cleanup
+ :action #'swiper--action
+ :re-builder #'swiper--re-builder
+ :history 'swiper-history
+ :caller 'swiper))
+ (unless res
+ (goto-char swiper--opoint)))))
+
+ (defun swiper-toggle-face-matching ()
+ "Toggle matching only the candidates with `swiper-invocation-face'."
+ (interactive)
+ (setf (ivy-state-matcher ivy-last)
+ (if (ivy-state-matcher ivy-last)
+ nil
+ #'swiper--face-matcher))
+ (setq ivy--old-re nil))
+
+ (defun swiper--face-matcher (regexp candidates)
+ "Return REGEXP-matching CANDIDATES.
+ Matched candidates should have `swiper-invocation-face'."
+ (cl-remove-if-not
+ (lambda (x)
+ (and
+ (string-match regexp x)
+ (let ((s (match-string 0 x))
+ (i 0))
+ (while (and (< i (length s))
+ (text-property-any
+ i (1+ i)
+ 'face swiper-invocation-face
+ s))
+ (cl-incf i))
+ (eq i (length s)))))
+ candidates))
(defun swiper--ensure-visible ()
"Remove overlays hiding point."
(num (if (string-match "^[0-9]+" str)
(string-to-number (match-string 0 str))
0)))
- (goto-char (point-min))
- (when (cl-plusp num)
+ (unless (eq this-command 'ivy-yank-word)
(goto-char (point-min))
- (forward-line (1- num))
- (if (and (equal ivy-text "")
- (>= swiper--opoint (line-beginning-position))
- (<= swiper--opoint (line-end-position)))
- (goto-char swiper--opoint)
- (re-search-forward re (line-end-position) t))
- (isearch-range-invisible (line-beginning-position)
- (line-end-position))
- (unless (and (>= (point) (window-start))
- (<= (point) (window-end (ivy-state-window ivy-last) t)))
- (recenter)))
+ (when (cl-plusp num)
+ (goto-char (point-min))
+ (if swiper-use-visual-line
+ (line-move (1- num))
+ (forward-line (1- num)))
+ (if (and (equal ivy-text "")
+ (>= swiper--opoint (line-beginning-position))
+ (<= swiper--opoint (line-end-position)))
+ (goto-char swiper--opoint)
+ (re-search-forward re (line-end-position) t))
+ (isearch-range-invisible (line-beginning-position)
+ (line-end-position))
+ (unless (and (>= (point) (window-start))
+ (<= (point) (window-end (ivy-state-window ivy-last) t)))
+ (recenter))))
(swiper--add-overlays re)))))
- (defun swiper--add-overlays (re &optional beg end)
+ (defun swiper--add-overlays (re &optional beg end wnd)
"Add overlays for RE regexp in visible part of the current buffer.
- BEG and END, when specified, are the point bounds."
- (let ((ov (make-overlay
- (line-beginning-position)
- (1+ (line-end-position)))))
+ BEG and END, when specified, are the point bounds.
+ WND, when specified is the window."
+ (setq wnd (or wnd (ivy-state-window ivy-last)))
+ (let ((ov (if visual-line-mode
+ (make-overlay
+ (save-excursion
+ (beginning-of-visual-line)
+ (point))
+ (save-excursion
+ (end-of-visual-line)
+ (point)))
+ (make-overlay
+ (line-beginning-position)
+ (1+ (line-end-position))))))
(overlay-put ov 'face 'swiper-line-face)
- (overlay-put ov 'window (ivy-state-window ivy-last))
+ (overlay-put ov 'window wnd)
(push ov swiper--overlays)
(let* ((wh (window-height))
(beg (or beg (save-excursion
swiper-faces)))))
(push overlay swiper--overlays)
(overlay-put overlay 'face face)
- (overlay-put overlay 'window (ivy-state-window ivy-last))
+ (overlay-put overlay 'window wnd)
(overlay-put overlay 'priority i)))
(cl-incf i)))))))))
- (defun swiper--action (x input)
- "Goto line X and search for INPUT."
+ (defun swiper--action (x)
+ "Goto line X."
(if (null x)
(user-error "No candidates")
- (goto-char (point-min))
- (forward-line (1- (read (get-text-property 0 'display x))))
- (re-search-forward
- (ivy--regex input) (line-end-position) t)
- (swiper--ensure-visible)
- (when (/= (point) swiper--opoint)
- (unless (and transient-mark-mode mark-active)
- (push-mark swiper--opoint t)
- (message "Mark saved where search started")))))
+ (with-ivy-window
+ (unless (equal (current-buffer)
+ (ivy-state-buffer ivy-last))
+ (switch-to-buffer (ivy-state-buffer ivy-last)))
+ (goto-char (point-min))
+ (funcall (if swiper-use-visual-line
+ #'line-move
+ #'forward-line)
+ (1- (read (get-text-property 0 'display x))))
+ (re-search-forward
+ (ivy--regex ivy-text) (line-end-position) t)
+ (swiper--ensure-visible)
+ (when (/= (point) swiper--opoint)
+ (unless (and transient-mark-mode mark-active)
+ (when (eq ivy-exit 'done)
+ (push-mark swiper--opoint t)
+ (message "Mark saved where search started")))))))
;; (define-key isearch-mode-map (kbd "C-o") 'swiper-from-isearch)
(defun swiper-from-isearch ()
Run `swiper' for those buffers."
(interactive)
(setq swiper-multi-buffers nil)
- (setq swiper-multi-candidates nil)
(ivy-read (swiper-multi-prompt)
'internal-complete-buffer
:action 'swiper-multi-action-1)
(ivy-read "Swiper: " swiper-multi-candidates
:action 'swiper-multi-action-2
- :unwind #'swiper--cleanup))
+ :unwind #'swiper--cleanup
+ :caller 'swiper-multi))
+
+ (defun swiper-all ()
+ "Run `swiper' for all opened buffers."
+ (interactive)
+ (ivy-read "Swiper: " (swiper--multi-candidates
+ (cl-remove-if-not
+ #'buffer-file-name
+ (buffer-list)))
+ :action 'swiper-multi-action-2
+ :unwind #'swiper--cleanup
+ :caller 'swiper-multi))
+
+ (defun swiper--multi-candidates (buffers)
+ (let* ((ww (window-width))
+ (res nil)
+ (column-2 (apply #'max
+ (mapcar
+ (lambda (b)
+ (length (buffer-name b)))
+ buffers)))
+ (column-1 (- ww 4 column-2 1)))
+ (dolist (buf buffers)
+ (with-current-buffer buf
+ (setq res
+ (append
+ (mapcar
+ (lambda (s)
+ (setq s (concat (ivy--truncate-string s column-1) " "))
+ (let ((len (length s)))
+ (put-text-property
+ (1- len) len 'display
+ (concat
+ (make-string
+ (- ww (string-width s) (length (buffer-name)) 3)
+ ?\ )
+ (buffer-name))
+ s)
+ s))
+ (swiper--candidates 4))
+ res))
+ nil))
+ res))
(defun swiper-multi-action-1 (x)
(if (member x swiper-multi-buffers)
(cond ((memq this-command '(ivy-done
ivy-alt-done
ivy-immediate-done))
- (let ((ww (window-width)))
- (dolist (buf swiper-multi-buffers)
- (with-current-buffer buf
- (setq swiper-multi-candidates
- (append
- (mapcar
- (lambda (s)
- (setq s (concat s " "))
- (let ((len (length s)))
- (put-text-property
- (1- len) len 'display
- (concat
- (make-string
- (max
- (- ww
- (string-width s)
- (length (buffer-name))
- 1)
- 0)
- ?\ )
- (buffer-name))
- s)
- s))
- (swiper--candidates))
- swiper-multi-candidates))))))
+ (setq swiper-multi-candidates
+ (swiper--multi-candidates
+ (mapcar #'get-buffer swiper-multi-buffers))))
((eq this-command 'ivy-call)
(delete-minibuffer-contents))))
(when (string-match "\\` *\\([^ ]+\\)\\'" buf-space)
(switch-to-buffer (match-string 1 buf-space))
(goto-char (point-min))
- (forward-line (1- (read x)))
+ (forward-line (1- (read (get-text-property 0 'display x))))
(re-search-forward
(ivy--regex ivy-text)
(line-end-position) t)