(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")
(format "ag --vimgrep %S" regex))
nil)))
+;;;###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."
(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."
(if (< (length string) 3)
'((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, calling the appropriate function will
(when preselect
(unless (or (and require-match
(not (eq collection 'internal-complete-buffer)))
+ dynamic-collection
(let ((re (regexp-quote preselect)))
(cl-find-if (lambda (x) (string-match re x))
coll)))
(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)