emacs-elpa-diffs
[Top][All Lists]
Advanced

[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)
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]