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

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

[elpa] externals/embark 95517246d8 7/7: Merge branch 'consult-grep-dwim'


From: ELPA Syncer
Subject: [elpa] externals/embark 95517246d8 7/7: Merge branch 'consult-grep-dwim'
Date: Wed, 6 Dec 2023 12:58:02 -0500 (EST)

branch: externals/embark
commit 95517246d8ef5cd837cd315f4689e922202d3df5
Merge: b24295ea88 a05b77f490
Author: Omar Antolín <omar.antolin@gmail.com>
Commit: Omar Antolín <omar.antolin@gmail.com>

    Merge branch 'consult-grep-dwim'
---
 CHANGELOG.org     | 10 ++++++++++
 README.org        | 17 +++++++++++-----
 embark-consult.el | 53 +++++++++++++++----------------------------------
 embark.el         | 59 +++++++++++++++++++++++++++++++++----------------------
 embark.texi       | 15 ++++++++++----
 5 files changed, 84 insertions(+), 70 deletions(-)

diff --git a/CHANGELOG.org b/CHANGELOG.org
index c5894a36e1..f3ed5ff9a8 100644
--- a/CHANGELOG.org
+++ b/CHANGELOG.org
@@ -1,6 +1,16 @@
 #+title: Embark changelog
 
 * Development version
+- You can now use around action hooks with multitarget actions (that
+  you couldn't previously was an oversight).
+- Users of the =embark-consult= package can now use consult async search
+  commands such as =consult-grep= as multitarget actions (through
+  =embark-act-all=) to search a list of files. For example, you can use
+  =consult-find= to search among file /names/ and once you have the
+  relevant files in the minibuffer, you can use =embark-act-all= to
+  search for some text in those files. When acting on buffers consult
+  async search commands will search the associated file if there is
+  one, or else the =default-directory= of the buffer.
 - =embark-bindings= and similar commands now show definition of keyboard
   macros.
 - =embark-org= now recognizes Org links in non-org buffers.
diff --git a/README.org b/README.org
index 9bf5593cb1..a010932c15 100644
--- a/README.org
+++ b/README.org
@@ -1094,11 +1094,18 @@ Besides those exporters and candidate collectors, the 
=embark-consult=
 package provides many subtle tweaks and small integrations between
 Embark and Consult. Some examples are:
 
-- The asynchronous search commands will start in the directory
-  associated to the Embark target if that target is a file, buffer,
-  bookmark or Emacs Lisp library.
-
- - For all other target types, a Consult search command (asynchronous
+- When used as actions, the asynchronous search commands will search
+  only the files associated to the targets: if the targets /are/ files,
+  it searches those files; for buffers it will search either the
+  associated file if there is one, else all files in the buffer's
+  =default-directory=; for bookmarks it will search the file they point
+  to, same for Emacs Lisp libraries. This is particularly powerful
+  when using =embark-act-all= to act on multiple files at once, for
+  example you can use =consult-find= to search among file /names/ and then
+  =embark-act-all= and =consult-grep= to search within the matching files.
+
+ - For all other target types, those that do not have a sensible
+   notion of associated file, a Consult search command (asynchronous
    or not) will search for the text of the target but leave the
    minibuffer open so you can interact with the Consult command.
 
diff --git a/embark-consult.el b/embark-consult.el
index f92c1cbe2f..c89b1789c4 100644
--- a/embark-consult.el
+++ b/embark-consult.el
@@ -362,47 +362,26 @@ This is intended to be used in 
`embark-target-injection-hooks'."
   (cl-pushnew #'embark-consult--unique-match
               (alist-get cmd embark-target-injection-hooks)))
 
-(cl-defun embark-consult--prep-async (&key type target &allow-other-keys)
-  "Either add Consult's async separator or ignore the TARGET depending on TYPE.
-If the TARGET of the given TYPE has an associated notion of
-directory, we don't want to search for the text of target, but
-rather just start a search in the associated directory.
-
-This is intended to be used in `embark-target-injection-hooks'
-for any action that is a Consult async command."
-  (let* ((style (alist-get consult-async-split-style
-                           consult-async-split-styles-alist))
-         (initial (plist-get style :initial))
-         (separator (plist-get style :separator))
-         (directory (embark--associated-directory target type)))
-    (when directory
-      (delete-minibuffer-contents))
-    (when initial
-      (goto-char (minibuffer-prompt-end))
-      (insert initial)
-      (goto-char (point-max)))
-    (when (and separator (null directory))
-      (goto-char (point-max))
-      (insert separator))))
-
-(cl-defun embark-consult--projectless
-    (&rest rest &key run target type &allow-other-keys)
-  "Run action with nil `consult-project-function', if TARGET has an directory.
-The values of TYPE which are considered to have an associated
-directory are: file, buffer, bookmark and library.  The REST of
-the arguments are also passed to RUN."
-  (if (embark--associated-directory target type)
+(cl-defun embark-consult--async-search-dwim
+    (&key action type target candidates &allow-other-keys)
+  "DWIM when using a Consult async search command as an ACTION.
+If the TYPE of the target(s) has a notion of associated
+file (files, buffers, libraries and some bookmarks do), then run
+the ACTION with `consult-project-function' set to nil, and search
+only the files associated to the TARGET or CANDIDATES.  For other
+types, run the ACTION with TARGET or CANDIDATES as initial input."
+  (if-let ((file-fn (cdr (assq type embark--associated-file-fn-alist))))
       (let (consult-project-function)
-        (apply run :target target :type type rest))
-    (apply run :target target :type type rest)))
+        (funcall action
+                 (delq nil (mapcar file-fn (or candidates (list target))))))
+    (funcall action nil (or target (string-join candidates " ")))))
 
 (map-keymap
  (lambda (_key cmd)
-   (cl-pushnew #'embark--cd (alist-get cmd embark-around-action-hooks))
-   (cl-pushnew #'embark-consult--projectless
-               (alist-get cmd embark-around-action-hooks))
-   (cl-pushnew #'embark-consult--prep-async
-               (alist-get cmd embark-target-injection-hooks)))
+   (unless (eq cmd #'consult-locate)
+     (cl-pushnew cmd embark-multitarget-actions)
+     (cl-pushnew #'embark-consult--async-search-dwim
+                 (alist-get cmd embark-around-action-hooks))))
  embark-consult-async-search-map)
 
 ;;; Tables of contents for buffers: imenu and outline candidate collectors
diff --git a/embark.el b/embark.el
index acaeb9e1cc..bc35629887 100644
--- a/embark.el
+++ b/embark.el
@@ -1983,7 +1983,8 @@ arguments are passed to the hooks as keyword arguments."
   (mapc (lambda (h) (apply h :action action :quit quit target))
         (alist-get :always hooks)))
 
-(defun embark--run-around-action-hooks (action target quit)
+(defun embark--run-around-action-hooks
+    (action target quit &optional non-interactive)
   "Run the `embark-around-action-hooks' for ACTION.
 All the applicable around hooks are composed in the order they
 are present in `embark-around-action-hooks'.  The keys t and
@@ -1991,7 +1992,11 @@ are present in `embark-around-action-hooks'.  The keys t 
and
 The :always hooks are executed always (outermost) and the t hooks
 are the default hooks, for when there are no command-specific
 hooks for ACTION.  The QUIT, ACTION and TARGET arguments are
-passed to the hooks as keyword arguments."
+passed to the hooks as keyword arguments.
+
+The optional argument NON-INTERACTIVE controls whether the action
+is run with `command-execute' or with `funcall' passing the
+target as argument."
   (apply
    (seq-reduce
     (lambda (fn hook)
@@ -2000,8 +2005,12 @@ passed to the hooks as keyword arguments."
       (reverse
        (append (or (alist-get action hooks) (alist-get t hooks))
                (alist-get :always hooks))))
-    (lambda (&rest args)
-      (command-execute (plist-get args :action))))
+    (if non-interactive
+        (lambda (&rest args)
+          (funcall (plist-get args :action)
+                   (or (plist-get args :candidates) (plist-get args :target))))
+      (lambda (&rest args)
+        (command-execute (plist-get args :action)))))
    :action action :quit quit target))
 
 (defun embark--act (action target &optional quit)
@@ -2076,12 +2085,11 @@ minibuffer before executing the action."
                       (when dedicate (set-window-dedicated-p dedicate nil)))
                     (unless (eq final-window action-window)
                       (select-window final-window))))
-              ;; TODO uniformize the command and non-interactive cases?
-              (let ((argument
-                     (if multi
-                         (or (plist-get target :candidates) ; embark-act-all
-                             (list (plist-get target :target)))
-                       (plist-get target :target))))
+              (let ((target
+                     (if (and multi (null (plist-get target :candidates)))
+                         (plist-put
+                          target :candidates (list (plist-get target :target)))
+                       target)))
                 (lambda ()
                   (with-selected-window action-window
                     (embark--run-action-hooks embark-pre-action-hooks
@@ -2089,7 +2097,8 @@ minibuffer before executing the action."
                     (unwind-protect
                         (let ((current-prefix-arg prefix)
                               (default-directory directory))
-                          (funcall action argument))
+                          (embark--run-around-action-hooks
+                           action target quit :non-interactive))
                       (embark--run-action-hooks embark-post-action-hooks
                                                 action target quit))))))))
       (setq prefix-arg nil)
@@ -4089,23 +4098,25 @@ the REST of the arguments."
   (unless (y-or-n-p (format "Run %s on %s? " action target))
     (user-error "Canceled")))
 
+(defconst embark--associated-file-fn-alist
+  `((file . identity)
+    (buffer . ,(lambda (target)
+                 (let ((buffer (get-buffer target)))
+                   (or (buffer-file-name buffer)
+                       (buffer-local-value 'default-directory buffer)))))
+    (bookmark . bookmark-location)
+    (library . locate-library))
+  "Alist of functions that extract a file path from targets of a given type.")
+
 (defun embark--associated-directory (target type)
   "Return directory associated to TARGET of given TYPE.
 The supported values of TYPE are file, buffer, bookmark and
 library, which have an obvious notion of associated directory."
-  (setq target (pcase type
-                 ('file
-                  target)
-                 ('buffer
-                  (buffer-local-value 'default-directory (get-buffer target)))
-                 ('bookmark
-                  (bookmark-prop-get target 'filename))
-                 ('library
-                  (locate-library target))))
-  (when target
-    (if (file-directory-p target)
-        (file-name-as-directory target)
-      (file-name-directory target))))
+  (when-let ((file-fn (alist-get type embark--associated-file-fn-alist))
+             (file (funcall file-fn target)))
+    (if (file-directory-p file)
+        (file-name-as-directory file)
+      (file-name-directory file))))
 
 (cl-defun embark--cd (&rest rest &key run target type &allow-other-keys)
   "Run action with `default-directory' set to the directory of TARGET.
diff --git a/embark.texi b/embark.texi
index d512cf5696..cc41bf4ec5 100644
--- a/embark.texi
+++ b/embark.texi
@@ -1312,13 +1312,20 @@ Embark and Consult. Some examples are:
 
 @itemize
 @item
-The asynchronous search commands will start in the directory
-associated to the Embark target if that target is a file, buffer,
-bookmark or Emacs Lisp library.
+When used as actions, the asynchronous search commands will search
+only the files associated to the targets: if the targets @emph{are} files,
+it searches those files; for buffers it will search either the
+associated file if there is one, else all files in the buffer's
+@samp{default-directory}; for bookmarks it will search the file they point
+to, same for Emacs Lisp libraries. This is particularly powerful
+when using @samp{embark-act-all} to act on multiple files at once, for
+example you can use @samp{consult-find} to search among file @emph{names} and 
then
+@samp{embark-act-all} and @samp{consult-grep} to search within the matching 
files.
 
 @itemize
 @item
-For all other target types, a Consult search command (asynchronous
+For all other target types, those that do not have a sensible
+notion of associated file, a Consult search command (asynchronous
 or not) will search for the text of the target but leave the
 minibuffer open so you can interact with the Consult command.
 @end itemize



reply via email to

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