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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] master ed60d31 20/90: Make counsel-git-grep fully async


From: Oleh Krehel
Subject: [elpa] master ed60d31 20/90: Make counsel-git-grep fully async
Date: Tue, 30 Jun 2015 07:28:09 +0000

branch: master
commit ed60d31fc31de0dc4258696c2ecec9f1c20b06c7
Author: Oleh Krehel <address@hidden>
Commit: Oleh Krehel <address@hidden>

    Make counsel-git-grep fully async
    
    * counsel.el (counsel-git-grep-count): Rename to `counsel--gg-count' and
      make it async.
    (counsel-git-grep-function): Set `ivy--full-length' to -1. It means that
    `ivy--exhibit' should do nothing until the length is re-computed.
    (counsel-git-grep): Use the sync version of `counsel-git-grep-count' for
    the initial repo line count.
    (counsel--gg-candidates): New defun. When called, kill the previous
    git grep process and start a new one. The sentinel will insert the
    candidates, bypassing the `ivy--exhibit'.
    (counsel--gg-sentinel): New defun.
    (counsel--gg-count): Rename from `counsel-git-grep-count'. When finished
    computing, redisplay.
    
    * ivy.el (ivy--exhibit): Don't expect dynamic collection to return the
      candidates as before. Just call it and expect it to redisplay the
      minibuffer.
---
 counsel.el |   81 +++++++++++++++++++++++++++++++++++++++++++++++++----------
 ivy.el     |   18 +++++++------
 2 files changed, 77 insertions(+), 22 deletions(-)

diff --git a/counsel.el b/counsel.el
index 174a1b9..57bad38 100644
--- a/counsel.el
+++ b/counsel.el
@@ -198,14 +198,6 @@
 (defvar counsel--git-grep-dir nil
   "Store the base git directory.")
 
-(defun counsel-git-grep-count (str)
-  "Quickly count the amount of git grep STR matches."
-  (let* ((default-directory counsel--git-grep-dir)
-         (out (shell-command-to-string
-               (format "git grep -i -c '%s' | sed 's/.*:\\(.*\\)/\\1/g' | awk 
'{s+=$1} END {print s}'"
-                       (ivy--regex str)))))
-    (string-to-number out)))
-
 (defvar counsel--git-grep-count nil
   "Store the line count in current repository.")
 
@@ -224,10 +216,11 @@
       (if (<= counsel--git-grep-count 20000)
           (progn
             (setq res (shell-command-to-string cmd))
-            (setq ivy--full-length nil))
-        (setq res (shell-command-to-string (concat cmd " | head -n 2000")))
-        (setq ivy--full-length (counsel-git-grep-count ivy-text)))
-      (split-string res "\n" t))))
+            (setq ivy--full-length nil)
+            (split-string res "\n" t))
+        (setq ivy--full-length -1)
+        (counsel--gg-candidates (ivy--regex string))
+        nil))))
 
 (defvar counsel-git-grep-map
   (let ((map (make-sparse-keymap)))
@@ -237,7 +230,7 @@
 (defun counsel-git-grep-recenter ()
   (interactive)
   (with-selected-window (ivy-state-window ivy-last)
-    (counsel-git-grep-action)
+    (counsel-git-grep-action ivy--current)
     (recenter-top-bottom)))
 
 (defun counsel-git-grep-action (x)
@@ -257,7 +250,7 @@
         (locate-dominating-file default-directory ".git"))
   (if (null counsel--git-grep-dir)
       (error "Not in a git repository")
-    (setq counsel--git-grep-count (counsel-git-grep-count ""))
+    (setq counsel--git-grep-count (counsel--gg-count "" t))
     (ivy-read "pattern: " 'counsel-git-grep-function
               :initial-input initial-input
               :matcher #'counsel-git-grep-matcher
@@ -421,6 +414,66 @@ The libraries are offered from `load-path'."
                          (get-text-property 0 'full-name x)))
               :keymap counsel-describe-map)))
 
+(defun counsel--gg-candidates (regex)
+  "Return git grep candidates for REGEX."
+  (counsel--gg-count regex)
+  (let* ((default-directory counsel--git-grep-dir)
+         (counsel-gg-process " *counsel-gg*")
+         (proc (get-process counsel-gg-process))
+         (buff (get-buffer counsel-gg-process)))
+    (when proc
+      (delete-process proc))
+    (when buff
+      (kill-buffer buff))
+    (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)))
+    (set-process-sentinel
+     proc
+     #'counsel--gg-sentinel)))
+
+(defun counsel--gg-sentinel (process event)
+  (if (string= event "finished\n")
+      (progn
+        (with-current-buffer (process-buffer process)
+          (setq ivy--all-candidates (split-string (buffer-string) "\n" t))
+          (setq ivy--old-cands ivy--all-candidates))
+        (unless (eq ivy--full-length -1)
+          (ivy--insert-minibuffer
+           (ivy--format ivy--all-candidates))))
+    (if (string= event "exited abnormally with code 1\n")
+        (message "Error"))))
+
+(defun counsel--gg-count (regex &optional no-async)
+  "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))
+        (counsel-ggc-process " *counsel-gg-count*"))
+    (if no-async
+        (string-to-number (shell-command-to-string cmd))
+      (let ((proc (get-process counsel-ggc-process))
+            (buff (get-buffer counsel-ggc-process)))
+        (when proc
+          (delete-process proc))
+        (when buff
+          (kill-buffer buff))
+        (setq proc (start-process-shell-command
+                    counsel-ggc-process
+                    counsel-ggc-process
+                    cmd))
+        (set-process-sentinel
+         proc
+         #'(lambda (process event)
+             (when (string= event "finished\n")
+               (with-current-buffer (process-buffer process)
+                 (setq ivy--full-length (string-to-number (buffer-string))))
+               (ivy--insert-minibuffer
+                (ivy--format ivy--all-candidates)))))))))
+
 (provide 'counsel)
 
 ;;; counsel.el ends here
diff --git a/ivy.el b/ivy.el
index 2115555..9ac4917 100644
--- a/ivy.el
+++ b/ivy.el
@@ -1013,12 +1013,14 @@ Should be run via minibuffer `post-command-hook'."
       ;; while-no-input would cause annoying
       ;; "Waiting for process to die...done" message interruptions
       (let ((inhibit-message t))
-        (while-no-input
-          (unless (equal ivy--old-text ivy-text)
-            (cl-letf ((store (ivy-state-dynamic-collection ivy-last))
-                      ((ivy-state-dynamic-collection ivy-last) nil))
-              (setq ivy--all-candidates (funcall store ivy-text))))
-          (ivy--insert-minibuffer (ivy--format ivy--all-candidates))))
+        (unless (equal ivy--old-text ivy-text)
+          (while-no-input
+            ;; dynamic collection should take care of everything
+            (funcall (ivy-state-dynamic-collection ivy-last) ivy-text)
+            (setq ivy--old-text ivy-text)))
+        (unless (eq ivy--full-length -1)
+          (ivy--insert-minibuffer
+           (ivy--format ivy--all-candidates))))
     (cond (ivy--directory
            (if (string-match "/\\'" ivy-text)
                (if (member ivy-text ivy--all-candidates)
@@ -1041,8 +1043,8 @@ Should be run via minibuffer `post-command-hook'."
              (setq ivy--old-re nil))))
     (ivy--insert-minibuffer
      (ivy--format
-      (ivy--filter ivy-text ivy--all-candidates))))
-  (setq ivy--old-text ivy-text))
+      (ivy--filter ivy-text ivy--all-candidates)))
+    (setq ivy--old-text ivy-text)))
 
 (defun ivy--insert-minibuffer (text)
   "Insert TEXT into minibuffer with appropriate cleanup."



reply via email to

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