[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] master 8abed59 143/167: Add counsel-grep
From: |
Oleh Krehel |
Subject: |
[elpa] master 8abed59 143/167: Add counsel-grep |
Date: |
Tue, 08 Dec 2015 10:50:36 +0000 |
branch: master
commit 8abed590c9904fbdf7d6fbac3b7aed87627ed5c1
Author: Oleh Krehel <address@hidden>
Commit: Oleh Krehel <address@hidden>
Add counsel-grep
* ivy.el (ivy--reset-state): Don't push preselect onto collection for
:dynamic-collection.
(ivy-recompute-index-swiper-async): New defun. It's useful for
re-anchoring on collections produced async processes. The major
difference from `ivy-recompute-index-swiper' is using `equal' instead of
`eq'.
* counsel.el (counsel--async-sentinel): Add index recomputing logic.
When `ivy--old-cands' are null, recompute the index according to
:preselect, otherwise try `ivy--recompute-index'.
(counsel-grep): New command. Very similar to `swiper', except calls an
external process for each key update. Should be much faster for very
large files, both for startup and for matching. For smaller files, it's
less convenient.
(counsel-grep-function): New defun.
(counsel-grep-action): New defun.
Fixes #299
---
counsel.el | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ivy.el | 14 ++++++++++++++
2 files changed, 70 insertions(+), 0 deletions(-)
diff --git a/counsel.el b/counsel.el
index 7e6b9fd..020c917 100644
--- a/counsel.el
+++ b/counsel.el
@@ -562,6 +562,16 @@ Or the time of the last minibuffer update.")
(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")
@@ -1107,6 +1117,7 @@ Usable with `ivy-resume', `ivy-next-line-and-call' and
(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."
@@ -1121,6 +1132,51 @@ 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)
diff --git a/ivy.el b/ivy.el
index af786c0..f83d0d0 100644
--- a/ivy.el
+++ b/ivy.el
@@ -947,6 +947,7 @@ See also `ivy-sort-max-size'."
'((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
@@ -1192,6 +1193,7 @@ This is useful for recursive `ivy-read'."
(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)))
@@ -1851,6 +1853,18 @@ Prefix matches to NAME are put ahead of the list."
(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)
- [elpa] master ed2367b 134/167: swiper.el (swiper--candidates): Require outline, (continued)
- [elpa] master ed2367b 134/167: swiper.el (swiper--candidates): Require outline, Oleh Krehel, 2015/12/08
- [elpa] master 80d4dde 141/167: Fix broken candidate index in ivy-resume, Oleh Krehel, 2015/12/08
- [elpa] master d9ecd2e 133/167: Fix the preselect for (swiper "one"), Oleh Krehel, 2015/12/08
- [elpa] master 073b071 115/167: Allow to sort files by last modification time., Oleh Krehel, 2015/12/08
- [elpa] master 0c62f7e 132/167: ivy.el (ivy-alt-done): Split into smaller defuns, Oleh Krehel, 2015/12/08
- [elpa] master 59df2e9 131/167: ivy.el (ivy-alt-done): Refactor, Oleh Krehel, 2015/12/08
- [elpa] master 2bec99d 146/167: Ease production of functions like ivy-format-function-default, Oleh Krehel, 2015/12/08
- [elpa] master c546ae4 150/167: Enable recursive swiper calls, Oleh Krehel, 2015/12/08
- [elpa] master 1bf4ae2 140/167: Warn the user about the behavior of ivy--regex-ignore-order, Oleh Krehel, 2015/12/08
- [elpa] master 99d214d 142/167: Ivy-resume should restore the buffer for swiper, Oleh Krehel, 2015/12/08
- [elpa] master 8abed59 143/167: Add counsel-grep,
Oleh Krehel <=
- [elpa] master 3b67044 145/167: Convert ivy formatting functions to dotted pairs., Oleh Krehel, 2015/12/08
- [elpa] master ac09f6b 152/167: Fix the issue caused by recursive swiper calls, Oleh Krehel, 2015/12/08
- [elpa] master a34e532 155/167: swiper.el: Use show-all if outline-show-all isn't there, Oleh Krehel, 2015/12/08
- [elpa] master b57c57d 153/167: Fix the preselect for (swiper "one") again, Oleh Krehel, 2015/12/08
- [elpa] master a585fcd 156/167: Fix due to visual-line-mode weirdness, Oleh Krehel, 2015/12/08
- [elpa] master 1cf32c8 138/167: ivy.org manual edits, Oleh Krehel, 2015/12/08
- [elpa] master 7377445 147/167: Edit documentation strings in ivy.el, Oleh Krehel, 2015/12/08
- [elpa] master 1cceac1 154/167: Fix ivy-resume issue caused by the recursive calls change, Oleh Krehel, 2015/12/08
- [elpa] master ed9169d 158/167: swiper.el (swiper--update-input-ivy): Add a work-around for "M-j", Oleh Krehel, 2015/12/08
- [elpa] master 0332b3e 151/167: Remove 'field text property for twittering-mode, Oleh Krehel, 2015/12/08