diff --git a/CHANGELOG.md b/CHANGELOG.md index 3358cf9..759f6ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,7 @@ ### Internal +* Replace the fixed `run-with-timer` delay in `helm-projectile-grep`/`helm-projectile-ack` (used so a search invoked as an action didn't start until the current Helm session tore down) with `helm-run-after-exit` when a session is live, and a direct call otherwise. No more arbitrary 10ms latency on the standalone commands, and the deferral is now explicit. * Tidy up top-level dependencies: `require` `grep` from the helpers that actually use `grep-find-ignored-files`/`-directories` (`helm-projectile--ignored-files`/`-directories`) instead of relying on it being pulled in transitively, and drop the unused `helm-locate` and `helm-global-bindings` requires. (No startup-time change - Helm loads all three transitively anyway; this just makes the dependencies honest.) * Drive `helm-projectile-toggle`'s command remaps from a single table (`helm-projectile--command-remaps`) instead of two hand-maintained copies of ~20 `define-key` calls. * Extract the remote virtual-Dired guard duplicated across the three Dired file actions into a `helm-projectile--with-virtual-dired` macro. diff --git a/helm-projectile.el b/helm-projectile.el index dd257e3..ea094ad 100644 --- a/helm-projectile.el +++ b/helm-projectile.el @@ -1558,6 +1558,17 @@ This function is obsolete; use `helm-projectile-mode' instead." (interactive) (helm-projectile-mode -1)) +(defun helm-projectile--run-grep-or-ack (&rest args) + "Call `helm-projectile-grep-or-ack' with ARGS. +When invoked from an action of a live Helm session, defer the search +until that session has exited (via `helm-run-after-exit'), because a new +Helm session must not start while the current one is tearing down. +Otherwise run it right away. This replaces an old `run-with-timer' that +guessed a fixed 10ms delay for the same purpose." + (if helm-alive-p + (apply #'helm-run-after-exit #'helm-projectile-grep-or-ack args) + (apply #'helm-projectile-grep-or-ack args))) + ;;;###autoload (defun helm-projectile-grep (&optional dir files) "Helm version of `projectile-grep'. @@ -1569,8 +1580,7 @@ prefix argument then ask for FILES." (include (if (equal current-prefix-arg '(4)) (read-string (projectile-prepend-project-name "Grep in: ")) files))) - (run-with-timer 0.01 nil - #'helm-projectile-grep-or-ack project-root nil nil nil include))) + (helm-projectile--run-grep-or-ack project-root nil nil nil include))) (defun helm-projectile--wildcard-to-ack-match (wildcard) "Transform WILDCARD into a form expected by \"match:\" filter of \"ack\"." @@ -1629,8 +1639,7 @@ Use `helm-projectile-rg' or `helm-projectile-ag' instead." (helm-grep-default-command helm-ack-grep-executable)) (helm-grep-read-ack-type)) types))) - (run-with-timer 0.01 nil - #'helm-projectile-grep-or-ack project-root t ignored helm-ack-grep-executable include))) + (helm-projectile--run-grep-or-ack project-root t ignored helm-ack-grep-executable include))) (make-obsolete 'helm-projectile-ack "use `helm-projectile-rg' or `helm-projectile-ag' instead." diff --git a/test/helm-projectile-test-helper.el b/test/helm-projectile-test-helper.el index a6b69fe..3d7b0a2 100644 --- a/test/helm-projectile-test-helper.el +++ b/test/helm-projectile-test-helper.el @@ -91,11 +91,12 @@ plain three-slot string so only the ignore globs vary." (defun helm-projectile-test--ack-args () "Return the args `helm-projectile-ack' would hand to `helm-projectile-grep-or-ack'. -`run-with-timer' is stubbed to capture them; the returned list is +The latter is stubbed to capture them (with no live Helm session, the +call runs straight through); the returned list is \(PROJECT-ROOT USE-ACK-P IGNORED ACK-EXECUTABLE INCLUDE)." - (let (args) - (cl-letf (((symbol-function 'run-with-timer) - (lambda (_delay _repeat _fn &rest rest) (setq args rest)))) + (let (args (helm-alive-p nil)) + (cl-letf (((symbol-function 'helm-projectile-grep-or-ack) + (lambda (&rest rest) (setq args rest)))) (helm-projectile-ack)) args)) diff --git a/test/helm-projectile-test.el b/test/helm-projectile-test.el index 5f6933c..8f67e73 100644 --- a/test/helm-projectile-test.el +++ b/test/helm-projectile-test.el @@ -406,6 +406,26 @@ (expect (helm-projectile-test--ag-command "ag" "--foo") :to-equal "ag --ignore TAGS --ignore build/ --foo %s %s %s"))) +(describe "helm-projectile--run-grep-or-ack" + ;; Replaces the old `run-with-timer' hack: run immediately when no Helm + ;; session is live, but defer via `helm-run-after-exit' when invoked as an + ;; action from one (so a new session doesn't start mid-teardown). + (it "runs the search immediately when no Helm session is live" + (spy-on 'helm-projectile-grep-or-ack) + (spy-on 'helm-run-after-exit) + (let ((helm-alive-p nil)) + (helm-projectile--run-grep-or-ack "/proj/" nil nil nil nil)) + (expect 'helm-projectile-grep-or-ack :to-have-been-called) + (expect 'helm-run-after-exit :not :to-have-been-called)) + + (it "defers via helm-run-after-exit when a Helm session is live" + (spy-on 'helm-projectile-grep-or-ack) + (spy-on 'helm-run-after-exit) + (let ((helm-alive-p t)) + (helm-projectile--run-grep-or-ack "/proj/" nil nil nil nil)) + (expect 'helm-run-after-exit :to-have-been-called) + (expect 'helm-projectile-grep-or-ack :not :to-have-been-called))) + (describe "helm-projectile-ack deprecation" ;; ack is superseded by rg/ag and Projectile dropped `projectile-ack'; ;; the command is kept working but marked obsolete.