[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] master 1f3fa31 167/167: Merge commit 'e264139e7fafbd1bbb68f9cef6d
From: |
Oleh Krehel |
Subject: |
[elpa] master 1f3fa31 167/167: Merge commit 'e264139e7fafbd1bbb68f9cef6d1c50b8e6cf1f3' from swiper |
Date: |
Tue, 08 Dec 2015 10:50:48 +0000 |
branch: master
commit 1f3fa31203c9830e3b621260ffc95c8ecabaaedf
Merge: a0561bf e264139
Author: Oleh Krehel <address@hidden>
Commit: Oleh Krehel <address@hidden>
Merge commit 'e264139e7fafbd1bbb68f9cef6d1c50b8e6cf1f3' from swiper
---
packages/swiper/README.md | 19 +-
packages/swiper/colir.el | 5 +-
packages/swiper/counsel.el | 297 +++++++--
packages/swiper/doc/Changelog.org | 322 ++++++++-
packages/swiper/doc/ivy.org | 476 ++++++++++++
packages/swiper/doc/ivy.texi | 591 +++++++++++++++
packages/swiper/doc/style.css | 107 +++
packages/swiper/ivy-hydra.el | 22 +-
packages/swiper/ivy-test.el | 32 +-
packages/swiper/ivy.el | 1447 ++++++++++++++++++++++++++-----------
packages/swiper/swiper.el | 451 ++++++++----
11 files changed, 3158 insertions(+), 611 deletions(-)
diff --git a/packages/swiper/README.md b/packages/swiper/README.md
index d70eeaf..0d80f8d 100644
--- a/packages/swiper/README.md
+++ b/packages/swiper/README.md
@@ -34,11 +34,18 @@ Here is some typical configuration:
(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.
diff --git a/packages/swiper/colir.el b/packages/swiper/colir.el
index 7eacbbd..e11ef7d 100644
--- a/packages/swiper/colir.el
+++ b/packages/swiper/colir.el
@@ -63,7 +63,10 @@
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)
diff --git a/packages/swiper/counsel.el b/packages/swiper/counsel.el
index 22dc505..9c86ec0 100644
--- a/packages/swiper/counsel.el
+++ b/packages/swiper/counsel.el
@@ -159,26 +159,29 @@
(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)))
@@ -224,7 +227,8 @@
:sort t
:action (lambda (x)
(describe-variable
- (intern x))))))
+ (intern x)))
+ :caller 'counsel-describe-variable)))
(ivy-set-actions
'counsel-describe-variable
@@ -236,6 +240,10 @@
'(("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'."
@@ -255,7 +263,8 @@
: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")
@@ -333,7 +342,9 @@
"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)))
@@ -348,13 +359,16 @@
(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)
@@ -364,8 +378,32 @@
(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
@@ -388,11 +426,28 @@
(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)
@@ -405,7 +460,8 @@ INITIAL-INPUT can be given as the initial minibuffer input."
: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."
@@ -479,6 +535,10 @@ Skip some dotfiles unless `ivy-text' requires them."
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))
@@ -491,7 +551,9 @@ Skip some dotfiles unless `ivy-text' requires them."
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")
@@ -500,6 +562,16 @@ Skip some dotfiles unless `ivy-text' requires them."
(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")
@@ -508,6 +580,24 @@ Skip some dotfiles unless `ivy-text' requires them."
(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
@@ -556,16 +646,25 @@ Skip some dotfiles unless `ivy-text' requires them."
(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."
@@ -663,8 +762,9 @@ The libraries are offered from `load-path'."
(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)))
@@ -673,7 +773,9 @@ The libraries are offered from `load-path'."
(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)))
@@ -687,8 +789,17 @@ The libraries are offered from `load-path'."
"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))
@@ -711,15 +822,19 @@ When NO-ASYNC is non-nil, do it synchronously."
(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)
@@ -728,6 +843,20 @@ CMD is a command name."
(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'.
@@ -738,11 +867,11 @@ Optional INITIAL-INPUT is the initial input in the
minibuffer."
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))
@@ -754,7 +883,7 @@ Optional INITIAL-INPUT is the initial input in the
minibuffer."
(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
@@ -762,11 +891,13 @@ Optional INITIAL-INPUT is the initial input in the
minibuffer."
(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")
@@ -824,7 +955,8 @@ Usable with `ivy-resume', `ivy-next-line-and-call' and
: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.")
@@ -834,7 +966,7 @@ Usable with `ivy-resume', `ivy-next-line-and-call' and
(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))
@@ -983,24 +1115,73 @@ Usable with `ivy-resume', `ivy-next-line-and-call' and
"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."
@@ -1035,6 +1216,38 @@ INITIAL-INPUT can be given as the initial minibuffer
input."
(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)
diff --git a/packages/swiper/doc/Changelog.org
b/packages/swiper/doc/Changelog.org
index 0f5ac2c..21076de 100644
--- a/packages/swiper/doc/Changelog.org
+++ b/packages/swiper/doc/Changelog.org
@@ -65,7 +65,7 @@ To have this feature, use something like this:
#+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
@@ -294,3 +294,323 @@ Use this command to exit the minibuffer choosing not the
current
candidate, but the current text. Bound to ~C-M-j~ or ~C-u C-j~.
See [[https://github.com/abo-abo/swiper/pull/183][#183]].
+
+* 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]].
diff --git a/packages/swiper/doc/ivy.org b/packages/swiper/doc/ivy.org
new file mode 100644
index 0000000..b26b00e
--- /dev/null
+++ b/packages/swiper/doc/ivy.org
@@ -0,0 +1,476 @@
+#+TITLE: Ivy User Manual
+#+AUTHOR: Oleh Krehel
+#+EMAIL: address@hidden
+#+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
address@hidden
+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.
+
address@hidden
+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.''
address@hidden 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
address@hidden 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
address@hidden 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
address@hidden 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
address@hidden 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
address@hidden 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
address@hidden 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
address@hidden 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
address@hidden vr
+#+END_TEXINFO
diff --git a/packages/swiper/doc/ivy.texi b/packages/swiper/doc/ivy.texi
new file mode 100644
index 0000000..b06c68c
--- /dev/null
+++ b/packages/swiper/doc/ivy.texi
@@ -0,0 +1,591 @@
+\input texinfo @c -*- texinfo -*-
address@hidden %**start of header
address@hidden ./ivy.info
address@hidden Ivy User Manual
address@hidden UTF-8
address@hidden en
address@hidden %**end of header
+
address@hidden
address@hidden
+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.
+
address@hidden
+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.''
address@hidden quotation
address@hidden copying
+
address@hidden Emacs
address@hidden
+* Ivy: (ivy). Using Ivy for completion.
address@hidden direntry
+
address@hidden
address@hidden
address@hidden Ivy User Manual
address@hidden Oleh Krehel
address@hidden
address@hidden 0pt plus 1filll
address@hidden
address@hidden titlepage
+
address@hidden
+
address@hidden
address@hidden Top
address@hidden Ivy User Manual
address@hidden
address@hidden ifnottex
+
address@hidden
+* Introduction::
+* Installation::
+* Getting started::
+* Key bindings::
+* Completion styles::
+* Variable Index::
+
address@hidden
+--- 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::
address@hidden detailmenu
address@hidden menu
+
address@hidden Introduction
address@hidden 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.
+
address@hidden 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.
+
address@hidden 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
address@hidden Ivy's code uses easy-to-examine global
+variables; avoids needless complications with branch-introducing
+custom macros.
+
address@hidden 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
address@hidden face. Or take the customization of actions, say
+after the candidate function is selected. @kbd{RET} uses
address@hidden 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.
+
address@hidden Discoverability
+Ivy displays easily discoverable commands through the hydra facility.
address@hidden 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.
+
address@hidden Installation
address@hidden Installation
+
+Install Ivy automatically through Emacs's package manager, or manually
+from Ivy's development repository.
address@hidden
+* Installing from Emacs Package Manager::
+* Installing from the Git repository::
address@hidden menu
+
address@hidden Installing from Emacs Package Manager
address@hidden Installing from Emacs Package Manager
+
address@hidden @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:
+
+
address@hidden
+(require 'package)
+(add-to-list 'package-archives
+ '("melpa" . "http://melpa.org/packages/"))
address@hidden lisp
+
+After this do @kbd{M-x} @code{package-refresh-contents} @kbd{RET}, followed by
address@hidden @code{package-install} @kbd{RET} @code{swiper} @kbd{RET}.
+
+For package manager details, see @ref{Packages,,,emacs,}.
+
address@hidden Installing from the Git repository
address@hidden Installing from the Git repository
+
+Why install from Git?
+
address@hidden
address@hidden
+No need to wait for MELPA's hourly builds
address@hidden
+Easy to revert to previous versions
address@hidden
+Contribute to Ivy's development; send patches; pull requests
address@hidden itemize
+
address@hidden steps}
+
+First clone the Swiper repository:
+
address@hidden
+cd ~/git && git clone https://github.com/abo-abo/swiper
+cd swiper && make compile
address@hidden example
+
+Then add this to Emacs init:
+
address@hidden
+(add-to-list 'load-path "~/git/swiper/")
+(require 'ivy)
address@hidden lisp
+
+To update the code:
+
address@hidden
+git pull
+make
address@hidden example
+
address@hidden Getting started
address@hidden Getting started
+
+First enable Ivy completion everywhere:
+
+
address@hidden
+(ivy-mode 1)
address@hidden lisp
+
+Note: @code{ivy-mode} can be toggled on and off with @kbd{M-x} @code{ivy-mode}.
address@hidden
+* Basic customization::
address@hidden menu
+
address@hidden Basic customization
address@hidden Basic customization
+
+Here are some basic settings particularly useful for new Ivy
+users:
+
address@hidden
+(setq ivy-use-virtual-buffers t)
+(setq ivy-height 10)
+(setq ivy-display-style 'fancy)
+(setq ivy-count-format "(%d/%d) ")
address@hidden lisp
+
+For additional customizations, refer to @code{M-x describe-variable}
+documentation.
+
address@hidden Key bindings
address@hidden Key bindings
+
address@hidden
+* Global key bindings::
+* Minibuffer key bindings::
address@hidden menu
+
address@hidden Global key bindings
address@hidden Global key bindings
+
+Recommended key bindings are:
address@hidden Ivy-based interface to standard commands
+
address@hidden
+(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)
address@hidden lisp
address@hidden Ivy-based interface to shell and system tools
+
address@hidden
+(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)
address@hidden lisp
address@hidden Ivy-resume and other commands
address@hidden resumes the last Ivy-based completion.
+
address@hidden
+(global-set-key (kbd "C-c C-r") 'ivy-resume)
address@hidden lisp
+
address@hidden Minibuffer key bindings
address@hidden Minibuffer key bindings
+
+Ivy includes several minibuffer bindings, which are defined in the
address@hidden keymap variable. The most frequently used ones
+are described here.
+
address@hidden or @code{counsel-M-x} add more through the @code{keymap}
argument to
address@hidden These keys, also active in the minibuffer, are described
+under their respective commands.
address@hidden
+* 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::
address@hidden menu
+
address@hidden Key bindings for navigation
address@hidden Key bindings for navigation
+
address@hidden
address@hidden
address@hidden (@code{ivy-next-line}) selects the next candidate
address@hidden
address@hidden (@code{ivy-previous-line}) selects the previous candidate
address@hidden
address@hidden<} (@code{ivy-beginning-of-buffer}) selects the first candidate
address@hidden
address@hidden>} (@code{ivy-end-of-buffer}) selects the last candidate
address@hidden
address@hidden (@code{ivy-scroll-up-command}) scrolls up by @code{ivy-height}
lines
address@hidden
address@hidden (@code{ivy-scroll-down-command}) scrolls down by
@code{ivy-height} lines
address@hidden itemize
+
address@hidden ivy-wrap
+This user option allows to get the wrap-around behavior for @kbd{C-n} and
address@hidden 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.
address@hidden defopt
+
address@hidden ivy-height
+Use this variable to adjust the minibuffer height, and therefore the
+scroll size for @kbd{C-v} and @kbd{M-v}.
address@hidden defopt
+
address@hidden Key bindings for single selection action then exit minibuffer
address@hidden 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.
+
address@hidden or @kbd{RET} (@code{ivy-done}) calls the default action and
exits the
+minibuffer.
+
address@hidden (@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}.
+
address@hidden (@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
address@hidden). 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.
+
address@hidden (@code{ivy-partial-or-done}) attempts partial completion,
extending
+current input as much as possible.
+
address@hidden TAB} is the same as @kbd{C-j}.
+
address@hidden (@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
address@hidden lists ignores the partial match and instead takes the
+current input to create a new directory with @code{dired-create-directory}.
+
address@hidden 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}).
address@hidden 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.
+
address@hidden Key bindings for multiple selections and actions keep minibuffer
open
address@hidden 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.
+
address@hidden (@code{ivy-call}) is the non-exiting version of the default
action,
address@hidden (@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.
+
address@hidden exits the minibuffer.
+
address@hidden recalls the state of the completion session just before
+its last exit. Useful after an accidental @kbd{C-m} (@code{ivy-done}).
+
address@hidden (@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.
+
address@hidden (@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
address@hidden lists. Just hold @kbd{C-M-n} for rapid-fire default
+action on each successive element of the list.
+
address@hidden (@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.
+
address@hidden Key bindings that alter minibuffer input
address@hidden Key bindings that alter minibuffer input
+
address@hidden (@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.
+
address@hidden (@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.
+
address@hidden (@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
address@hidden
+
address@hidden (@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.
+
address@hidden (@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.
+
address@hidden Other key bindings
address@hidden Other key bindings
+
address@hidden (@code{ivy-kill-ring-save}) copies selected candidates to the
kill
+ring; when the region is active, copies active region.
+
address@hidden Hydra in the minibuffer
address@hidden Hydra in the minibuffer
+
address@hidden (@code{hydra-ivy/body}) invokes Hydra menus with key shortcuts.
+
address@hidden 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:
address@hidden
address@hidden
address@hidden<} and @kbd{>} to adjust height of minibuffer,
address@hidden
+describes the current completion state, such as case folding and the
+current action.
address@hidden itemize
+
+Minibuffer editing is disabled when Hydra is active.
+
address@hidden Saving the current completion session to a buffer
address@hidden Saving the current completion session to a buffer
+
address@hidden C-o} (@code{ivy-occur}) saves the current candidates to a new
buffer;
+the list is active in the new buffer.
+
address@hidden 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$*}.
+
address@hidden Completion styles
address@hidden Completion styles
+
+Ivy's completion functions rely on the highly configurable regex
+builder.
+
+The default is:
+
address@hidden
+(setq ivy-re-builders-alist
+ '((t . ivy--regex-plus)))
address@hidden 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:
+
address@hidden
+(setq ivy-re-builders-alist
+ '((read-file-name-internal . ivy--regex-fuzzy)
+ (t . ivy--regex-plus)))
address@hidden 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:
address@hidden
+* ivy--regex-plus::
+* ivy--regex-ignore-order::
+* ivy--regex-fuzzy::
address@hidden menu
+
address@hidden ivy--regex-plus
address@hidden ivy--regex-plus
+
address@hidden is Ivy's default completion method.
+
address@hidden 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
+
address@hidden
+"\\(for\\).*\\(example\\)"
address@hidden 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.
+
address@hidden
+Standard regexp identifiers work:
+
+"^", "$", "\b" or "[a-z]"
address@hidden 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.
+
address@hidden ivy--regex-ignore-order
address@hidden ivy--regex-ignore-order
+
address@hidden 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.
+
address@hidden ivy--regex-fuzzy
address@hidden ivy--regex-fuzzy
+
address@hidden 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.
+
address@hidden Variable Index
address@hidden Variable Index
+
address@hidden vr
+
address@hidden
diff --git a/packages/swiper/doc/style.css b/packages/swiper/doc/style.css
new file mode 100644
index 0000000..547b4f0
--- /dev/null
+++ b/packages/swiper/doc/style.css
@@ -0,0 +1,107 @@
+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;
+}
diff --git a/packages/swiper/ivy-hydra.el b/packages/swiper/ivy-hydra.el
index 6ab1f9a..63755da 100644
--- a/packages/swiper/ivy-hydra.el
+++ b/packages/swiper/ivy-hydra.el
@@ -44,14 +44,20 @@
(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)
@@ -73,7 +79,11 @@ _h_ ^+^ _l_ _d_one _o_ops _m_: matcher %s(if (eq
ivy--regex-function 'i
(">" 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)
diff --git a/packages/swiper/ivy-test.el b/packages/swiper/ivy-test.el
index 10dd8f9..ec5857d 100644
--- a/packages/swiper/ivy-test.el
+++ b/packages/swiper/ivy-test.el
@@ -59,16 +59,33 @@
(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?")
@@ -84,11 +101,11 @@
(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 "^")
@@ -98,7 +115,7 @@
(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"
@@ -121,4 +138,3 @@
'("the" "The")))
(should (equal (ivy--filter "The" '("foo" "the" "The"))
'("The"))))
-
diff --git a/packages/swiper/ivy.el b/packages/swiper/ivy.el
index 04c254e..5127582 100644
--- a/packages/swiper/ivy.el
+++ b/packages/swiper/ivy.el
@@ -37,73 +37,126 @@
;;; 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
@@ -149,9 +202,13 @@ Only \"./\" and \"../\" apply here. They appear in reverse
order."
(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)
@@ -169,15 +226,23 @@ Only \"./\" and \"../\" apply here. They appear in
reverse order."
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))
@@ -186,7 +251,7 @@ Only \"./\" and \"../\" apply here. They appear in reverse
order."
"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.")
@@ -215,7 +280,7 @@ Otherwise, store nil.")
(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.")
@@ -238,6 +303,9 @@ When non-nil, it should contain one %d.")
(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)
@@ -250,11 +318,20 @@ When non-nil, it should contain one %d.")
,@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)
@@ -290,12 +367,11 @@ When non-nil, it should contain one %d.")
(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
@@ -309,14 +385,31 @@ When non-nil, it should contain one %d.")
"\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 ""))
- ((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.
@@ -334,59 +427,88 @@ Is is a cons cell, related to
`tramp-get-completion-function'."
"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."
@@ -397,13 +519,16 @@ When ARG is t, exit with current text, ignoring the
candidates."
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))
@@ -419,7 +544,10 @@ If the text hasn't changed as a result, forward to
`ivy-alt-done'."
(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)
@@ -437,7 +565,10 @@ If the text hasn't changed as a result, forward to
`ivy-alt-done'."
"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))
@@ -445,24 +576,28 @@ If the text hasn't changed as a result, forward to
`ivy-alt-done'."
(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.")
@@ -487,13 +622,13 @@ If the text hasn't changed as a result, forward to
`ivy-alt-done'."
(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 ()
@@ -562,6 +697,15 @@ If the input is empty, select the previous history element
instead."
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))))
@@ -604,7 +748,12 @@ If the input is empty, select the previous history element
instead."
(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.
@@ -642,15 +791,21 @@ Call the permanent action if possible."
"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."
@@ -740,6 +895,52 @@ On error (read-only), call `ivy-on-del-error-function'."
(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."
@@ -751,7 +952,7 @@ 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)
@@ -761,11 +962,34 @@ Prioritize directories."
"An alist of sorting functions for each collection function.
Interactive functions that call completion fit in here as well.
-For each entry, nil means no sorting. It's very useful to turn
-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))
@@ -773,10 +997,10 @@ The entry associated to t is used for all fall-through
cases.")
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
@@ -821,41 +1045,47 @@ Directories come first."
;;** 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
@@ -864,60 +1094,65 @@ candidates with each input."
("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))
@@ -927,15 +1162,18 @@ This is useful for recursive `ivy-read'."
(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)
@@ -962,7 +1200,9 @@ This is useful for recursive `ivy-read'."
(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
@@ -975,10 +1215,9 @@ This is useful for recursive `ivy-read'."
((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
@@ -994,27 +1233,43 @@ This is useful for recursive `ivy-read'."
(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))))
@@ -1037,47 +1292,56 @@ This is useful for recursive `ivy-read'."
;;;###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:
@@ -1093,26 +1357,17 @@ Minibuffer 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
@@ -1152,7 +1407,7 @@ This allows to \"quote\" N spaces by inputting N+1
spaces."
(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))))
@@ -1181,8 +1436,15 @@ When GREEDY is non-nil, join words in a greedy way."
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
@@ -1202,8 +1464,8 @@ Ignore the order of each group."
(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
@@ -1222,9 +1484,14 @@ Everything after \"!\" should not match."
"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
@@ -1258,7 +1525,7 @@ Insert .* between each char."
"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)
@@ -1287,17 +1554,21 @@ Insert .* between each char."
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)
@@ -1310,7 +1581,7 @@ Insert .* between each char."
(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)
@@ -1341,6 +1612,8 @@ Insert .* between each char."
"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
@@ -1364,7 +1637,7 @@ Should be run via minibuffer `post-command-hook'."
(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)))))
@@ -1383,8 +1656,9 @@ Should be run via minibuffer `post-command-hook'."
(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)
@@ -1406,18 +1680,17 @@ Should be run via minibuffer `post-command-hook'."
(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")
@@ -1441,109 +1714,296 @@ all of the text contained in the minibuffer."
(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)
@@ -1558,12 +2018,12 @@ This string will be inserted into the minibuffer.")
(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)
@@ -1594,20 +2054,27 @@ CANDS is a list of strings."
(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))))
@@ -1616,8 +2083,13 @@ CANDS is a list of strings."
(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'."
@@ -1632,7 +2104,10 @@ CANDS is a list of strings."
(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 "")
@@ -1746,7 +2221,7 @@ BUFFER may be a string or nil."
(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.
@@ -1780,7 +2255,7 @@ Don't finish completion."
(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)))
@@ -1801,6 +2276,170 @@ The selected history element will be inserted into the
minibufer."
(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
diff --git a/packages/swiper/swiper.el b/packages/swiper/swiper.el
index 1b2d906..d9bf724 100644
--- a/packages/swiper/swiper.el
+++ b/packages/swiper/swiper.el
@@ -4,7 +4,7 @@
;; Author: Oleh Krehel <address@hidden>
;; URL: https://github.com/abo-abo/swiper
-;; Version: 0.5.1
+;; Version: 0.7.0
;; Package-Requires: ((emacs "24.1"))
;; Keywords: matching
@@ -61,34 +61,17 @@
'((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)))
@@ -109,6 +92,8 @@
(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.")
@@ -120,37 +105,93 @@
(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)."
@@ -166,16 +207,28 @@
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)
@@ -187,28 +240,67 @@
(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
@@ -221,17 +313,13 @@ When non-nil, INITIAL-INPUT is the initial search
pattern."
(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.
@@ -241,48 +329,84 @@ there have line numbers. In the buffer, `ivy--regex'
should be used."
((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."
@@ -315,30 +439,43 @@ When non-nil, INITIAL-INPUT is the initial search
pattern."
(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
@@ -368,23 +505,31 @@ BEG and END, when specified, are the point bounds."
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 ()
@@ -411,13 +556,55 @@ BEG and END, when specified, are the point bounds."
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)
@@ -431,31 +618,9 @@ Run `swiper' for those 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))))
@@ -465,7 +630,7 @@ Run `swiper' for those buffers."
(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)
- [elpa] master 8dd88e4 149/167: doc/Changelog.org: Update up to 2bec99d, (continued)
- [elpa] master 8dd88e4 149/167: doc/Changelog.org: Update up to 2bec99d, Oleh Krehel, 2015/12/08
- [elpa] master 706349f 160/167: swiper.el (swiper-font-lock-ensure): Add vc-dir-mode, Oleh Krehel, 2015/12/08
- [elpa] master 2a55ada 163/167: doc/Changelog.org: Update up to 706349f, Oleh Krehel, 2015/12/08
- [elpa] master 98a4548 164/167: swiper.el: Bump version to 0.7.0, Oleh Krehel, 2015/12/08
- [elpa] master 84533bb 139/167: Minor fixes to ivy.org and export to ivy.texi, Oleh Krehel, 2015/12/08
- [elpa] master 17872ba 157/167: ivy.el: Structure all faces into ivy-faces custom group, Oleh Krehel, 2015/12/08
- [elpa] master 5a6217a 161/167: counsel.el (counsel-tmm): New command, Oleh Krehel, 2015/12/08
- [elpa] master e264139 166/167: doc/ivy.org: Add "Variable Index" node, Oleh Krehel, 2015/12/08
- [elpa] master c5661c0 162/167: ivy.el (ivy-completing-read): Use completing-read-default for tmm, Oleh Krehel, 2015/12/08
- [elpa] master 1992f44 165/167: doc/ivy.texi: Re-export using adjusted texinfo exporter, Oleh Krehel, 2015/12/08
- [elpa] master 1f3fa31 167/167: Merge commit 'e264139e7fafbd1bbb68f9cef6d1c50b8e6cf1f3' from swiper,
Oleh Krehel <=