(const :tag "Count matches and show current match" "(%d/%d) ")
string))
+(defcustom ivy-add-newline-after-prompt nil
+ "When non-nil, add a newline after the `ivy-read' prompt."
+ :type 'boolean)
+
(defcustom ivy-wrap nil
"When non-nil, wrap around after the first and the last candidate."
:type 'boolean)
"Return a string that corresponds to the current thing at point."
(or
(thing-at-point 'url)
+ (and (eq (ivy-state-collection ivy-last) 'read-file-name-internal)
+ (ffap-file-at-point))
(let (s)
(cond ((stringp (setq s (thing-at-point 'symbol)))
(if (string-match "\\`[`']?\\(.*?\\)'?\\'" s)
(defvar Info-current-file)
+(eval-and-compile
+ (unless (fboundp 'defvar-local)
+ (defmacro defvar-local (var val &optional docstring)
+ "Define VAR as a buffer-local variable with default value VAL."
+ (declare (debug defvar) (doc-string 3))
+ (list 'progn (list 'defvar var val docstring)
+ (list 'make-variable-buffer-local (list 'quote var)))))
+ (unless (fboundp 'setq-local)
+ (defmacro setq-local (var val)
+ "Set variable VAR to value VAL in current buffer."
+ (list 'set (list 'make-local-variable (list 'quote var)) val))))
+
(defmacro ivy-quit-and-run (&rest body)
"Quit the minibuffer and run BODY afterwards."
`(progn
(setq dir (concat ivy-text ivy--directory))
(ivy--cd dir)
(ivy--exhibit))
- ((or
- (and
- (not (string= ivy-text ""))
- (setq dir (ivy-expand-file-if-directory ivy-text)))
- (and
- (> ivy--length 0)
- (not (string= ivy--current "./"))
- (setq dir (ivy-expand-file-if-directory ivy--current))))
+ ((and
+ (> ivy--length 0)
+ (not (string= ivy--current "./"))
+ (setq dir (ivy-expand-file-if-directory ivy--current)))
(ivy--cd dir)
(ivy--exhibit))
((or (and (equal ivy--directory "/")
When this directory doesn't exist, return nil."
(when (stringp file-name)
(let ((full-name
- (file-name-as-directory
- (expand-file-name file-name ivy--directory))))
- (when (file-directory-p full-name)
+ ;; Ignore host name must not match method "ssh"
+ (ignore-errors
+ (file-name-as-directory
+ (expand-file-name file-name ivy--directory)))))
+ (when (and full-name (file-directory-p full-name))
full-name))))
(defcustom ivy-tab-space nil
(defun ivy-resume ()
"Resume the last completion session."
(interactive)
- (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
+ (if (null (ivy-state-action ivy-last))
+ (user-error "The last session isn't compatible with `ivy-resume'")
+ (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-local ivy-calling nil
"When non-nil, call the current action when `ivy--index' changes.")
(defun ivy-set-index (index)
(progn
(insert ivy--default)
(when (and (with-ivy-window (derived-mode-p 'prog-mode))
+ (eq (ivy-state-caller ivy-last) 'swiper)
(not (file-exists-p ivy--default))
+ (not (ffap-url-p ivy--default))
+ (not (ivy-state-dynamic-collection ivy-last))
(> (point) (minibuffer-prompt-end)))
(undo-boundary)
(insert "\\_>")
(avy--process
(nreverse candidates)
(avy--style-fn avy-style)))))
- (ivy-set-index (- (line-number-at-pos candidate) 2))
- (ivy--exhibit)
- (ivy-done)))
+ (when (numberp candidate)
+ (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.
:value-type (choice
(const :tag "Plain sort" string-lessp)
(const :tag "File sort" ivy-sort-file-function-default)
- (const :tag "No sort" nil)))
+ (const :tag "No sort" nil)
+ (function :tag "Custom function")))
:group 'ivy)
(defvar ivy-index-functions-alist
(if (and (setq sort-fn (cdr (assoc t ivy-sort-functions-alist)))
(<= (length coll) ivy-sort-max-size))
(setq coll (cl-sort (copy-sequence coll) sort-fn))))))
+ (setq coll (ivy--set-candidates coll))
(when preselect
(unless (or (and require-match
(not (eq collection 'internal-complete-buffer)))
(ivy--directory
prompt)
(t
- nil)))
+ prompt)))
(setf (ivy-state-initial-input ivy-last) initial-input)))
;;;###autoload
:history history
:keymap nil
:sort
- (let ((sort (assoc this-command ivy-sort-functions-alist)))
+ (let ((sort (or (assoc this-command ivy-sort-functions-alist)
+ (assoc t ivy-sort-functions-alist))))
(if sort
(cdr sort)
t)))))
(set (make-local-variable 'minibuffer-default-add-function)
(lambda ()
(list ivy--default)))
+ (set (make-local-variable 'inhibit-field-text-motion) nil)
(when (display-graphic-p)
(setq truncate-lines t))
(setq-local max-mini-window-height ivy-height)
(window-width))
(setq n-str (concat n-str "\n" d-str))
(setq n-str (concat n-str d-str)))
+ (when ivy-add-newline-after-prompt
+ (setq n-str (concat n-str "\n")))
(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))))
(not (and (require 'flx nil 'noerror)
(eq ivy--regex-function 'ivy--regex-fuzzy)
(< (length cands) 200)))
-
+ ivy--old-cands
(cl-position (nth ivy--index ivy--old-cands)
cands))
(funcall func re-str cands))))
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)))
+ (if (null ivy--old-cands)
+ (let ((ln (with-ivy-window
+ (line-number-at-pos))))
+ (or (cl-position-if (lambda (x)
+ (>= (string-to-number x) ln))
+ cands)
+ 0))
+ (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--format-function-generic (selected-fn other-fn strs separator)
"Transform CAND-PAIRS into a string for minibuffer.
-SELECTED-FN and OTHER-FN each take two string arguments.
+SELECTED-FN and OTHER-FN each take one string argument.
SEPARATOR is used to join the candidates."
(let ((i -1))
(mapconcat
(cl-incf i))))))
str))
+(ivy-set-display-transformer
+ 'counsel-find-file 'ivy-read-file-transformer)
(ivy-set-display-transformer
'read-file-name-internal 'ivy-read-file-transformer)
(setq ivy--virtual-buffers (nreverse virtual-buffers))
(mapcar #'car ivy--virtual-buffers))))
-(defcustom ivy-ignore-buffers nil
- "List of regexps matching buffer names to ignore."
- :type '(repeat regexp))
+(defcustom ivy-ignore-buffers '("\\` ")
+ "List of regexps or functions matching buffer names to ignore."
+ :type '(repeat (choice regexp function)))
(defun ivy--buffer-list (str &optional virtual)
"Return the buffers that match STR.
(or (cl-remove-if
(lambda (buf)
(cl-find-if
- (lambda (regexp)
- (string-match regexp buf))
+ (lambda (f-or-r)
+ (if (functionp f-or-r)
+ (funcall f-or-r buf)
+ (string-match-p f-or-r buf)))
ivy-ignore-buffers))
res)
res))))
(propertize str 'face 'ivy-modified-buffer)
str)))
+(defun ivy-switch-buffer-occur ()
+ "Occur function for `ivy-switch-buffer' that uses `ibuffer'."
+ (let* ((cand-regexp
+ (concat "\\(" (mapconcat #'regexp-quote ivy--old-cands "\\|") "\\)"))
+ (new-qualifier `((name . ,cand-regexp))))
+ (ibuffer nil (buffer-name) new-qualifier)))
+
;;;###autoload
(defun ivy-switch-buffer ()
"Switch to another buffer."
(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 "j") 'ivy-occur-next-line)
+ (define-key map (kbd "k") 'ivy-occur-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 "f") 'ivy-occur-press)
+ (define-key map (kbd "g") 'ivy-occur-revert-buffer)
(define-key map (kbd "a") 'ivy-occur-read-action)
(define-key map (kbd "o") 'ivy-occur-dispatch)
+ (define-key map (kbd "c") 'ivy-occur-toggle-calling)
(define-key map (kbd "q") 'quit-window)
map)
"Keymap for Ivy Occur mode.")
+(defun ivy-occur-toggle-calling ()
+ "Toggle `ivy-calling'."
+ (interactive)
+ (if (setq ivy-calling (not ivy-calling))
+ (progn
+ (setq mode-name "Ivy-Occur [calling]")
+ (ivy-occur-press))
+ (setq mode-name "Ivy-Occur"))
+ (force-mode-line-update))
+
+(defun ivy-occur-next-line (&optional arg)
+ "Move the cursor down ARG lines.
+When `ivy-calling' isn't nil, call `ivy-occur-press'."
+ (interactive "p")
+ (forward-line arg)
+ (when ivy-calling
+ (ivy-occur-press)))
+
+(defun ivy-occur-previous-line (&optional arg)
+ "Move the cursor up ARG lines.
+When `ivy-calling' isn't nil, call `ivy-occur-press'."
+ (interactive "p")
+ (forward-line (- arg))
+ (when ivy-calling
+ (ivy-occur-press)))
+
(define-derived-mode ivy-occur-mode fundamental-mode "Ivy-Occur"
"Major mode for output from \\[ivy-occur].
(setq ivy--occurs-list
(plist-put ivy--occurs-list cmd occur)))
+(ivy-set-occur 'ivy-switch-buffer 'ivy-switch-buffer-occur)
+(ivy-set-occur 'ivy-switch-buffer-other-window 'ivy-switch-buffer-occur)
+
(defun ivy--occur-insert-lines (cands)
(dolist (str cands)
(add-text-properties
(ivy-exit-with-action
`(lambda (_) (pop-to-buffer ,buffer))))))
+(defun ivy-occur-revert-buffer ()
+ "Refresh the buffer making it up-to date with the collection.
+
+Currently only works for `swiper'. In that specific case, the
+*ivy-occur* buffer becomes nearly useless as the orignal buffer
+is updated, since the line numbers no longer match.
+
+Calling this function is as if you called `ivy-occur' on the
+updated original buffer."
+ (interactive)
+ (let ((caller (ivy-state-caller ivy-occur-last))
+ (ivy-last ivy-occur-last))
+ (when (eq caller 'swiper)
+ (let ((buffer (ivy-state-buffer ivy-occur-last)))
+ (unless (buffer-live-p buffer)
+ (error "buffer was killed"))
+ (let ((inhibit-read-only t))
+ (erase-buffer)
+ (funcall (plist-get ivy--occurs-list caller) t))))))
+
(declare-function wgrep-change-to-wgrep-mode "ext:wgrep")
(defun ivy-wgrep-change-to-wgrep-mode ()
(defun ivy-occur-press ()
"Execute action for the current candidate."
(interactive)
- (require 'pulse)
(when (save-excursion
(beginning-of-line)
(looking-at "\\(?:./\\| \\)\\(.*\\)$"))
+ (when (memq (ivy-state-caller ivy-occur-last)
+ '(swiper counsel-git-grep counsel-grep counsel-ag
+ counsel-describe-function counsel-describe-variable))
+ (let ((window (ivy-state-window ivy-occur-last)))
+ (when (or (null (window-live-p window))
+ (equal window (selected-window)))
+ (save-selected-window
+ (setf (ivy-state-window ivy-occur-last)
+ (display-buffer (ivy-state-buffer ivy-occur-last)
+ 'display-buffer-pop-up-window))))))
(let* ((ivy-last ivy-occur-last)
(ivy-text (ivy-state-text ivy-last))
(str (buffer-substring
(line-beginning-position)
(line-end-position)
(selected-window))
- (run-at-time 0.5 nil 'swiper--cleanup))
- (pulse-momentary-highlight-one-line (point)))))))
+ (run-at-time 0.5 nil 'swiper--cleanup)))))))
(defvar ivy-help-file (let ((default-directory
(if load-file-name