dotemacs

My Emacs configuration
git clone git://git.entf.net/dotemacs
Log | Files | Refs | LICENSE

embark.el (181024B)


      1 ;;; embark.el --- Conveniently act on minibuffer completions   -*- lexical-binding: t; -*-
      2 
      3 ;; Copyright (C) 2021, 2022  Free Software Foundation, Inc.
      4 
      5 ;; Author: Omar Antolín Camarena <omar@matem.unam.mx>
      6 ;; Maintainer: Omar Antolín Camarena <omar@matem.unam.mx>
      7 ;; Keywords: convenience
      8 ;; Version: 0.22.1
      9 ;; Homepage: https://github.com/oantolin/embark
     10 ;; Package-Requires: ((emacs "27.1") (compat "29.1.4.0"))
     11 
     12 ;; This file is part of GNU Emacs.
     13 
     14 ;; This program is free software; you can redistribute it and/or modify
     15 ;; it under the terms of the GNU General Public License as published by
     16 ;; the Free Software Foundation, either version 3 of the License, or
     17 ;; (at your option) any later version.
     18 
     19 ;; This program is distributed in the hope that it will be useful,
     20 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
     21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     22 ;; GNU General Public License for more details.
     23 
     24 ;; You should have received a copy of the GNU General Public License
     25 ;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
     26 
     27 ;;; Commentary:
     28 
     29 ;; This package provides a sort of right-click contextual menu for
     30 ;; Emacs, accessed through the `embark-act' command (which you should
     31 ;; bind to a convenient key), offering you relevant actions to use on
     32 ;; a target determined by the context:
     33 
     34 ;; - In the minibuffer, the target is the current best completion
     35 ;;  candidate.
     36 ;; - In the `*Completions*' buffer the target is the completion at point.
     37 ;; - In a regular buffer, the target is the region if active, or else the
     38 ;;  file, symbol or url at point.
     39 
     40 ;; The type of actions offered depend on the type of the target:
     41 
     42 ;; - For files you get offered actions like deleting, copying,
     43 ;;  renaming, visiting in another window, running a shell command on the
     44 ;;  file, etc.
     45 ;; - For buffers the actions include switching to or killing the buffer.
     46 ;; - For package names the actions include installing, removing or
     47 ;;  visiting the homepage.
     48 
     49 ;; Everything is easily configurable: determining the current target,
     50 ;; classifying it, and deciding with actions are offered for each type
     51 ;; in the classification.  The above introduction just mentions part of
     52 ;; the default configuration.
     53 
     54 ;; Configuring which actions are offered for a type is particularly
     55 ;; easy and requires no programming: the `embark-keymap-alist'
     56 ;; variable associates target types with variable containing keymaps,
     57 ;; and those keymaps containing binds for the actions.  For example,
     58 ;; in the default configuration the type `file' is associated with the
     59 ;; symbol `embark-file-keymap'.  That symbol names a keymap with
     60 ;; single-letter key bindings for common Emacs file commands, for
     61 ;; instance `c' is bound to `copy-file'.  This means that if while you
     62 ;; are in the minibuffer after running a command that prompts for a
     63 ;; file, such as `find-file' or `rename-file', you can copy a file by
     64 ;; running `embark-act' and then pressing `c'.
     65 
     66 ;; These action keymaps are very convenient but not strictly necessary
     67 ;; when using `embark-act': you can use any command that reads from the
     68 ;; minibuffer as an action and the target of the action will be inserted
     69 ;; at the first minibuffer prompt.  After running `embark-act' all of your
     70 ;; key bindings and even `execute-extended-command' can be used to run a
     71 ;; command.  The action keymaps are normal Emacs keymaps and you should
     72 ;; feel free to bind in them whatever commands you find useful as actions.
     73 
     74 ;; The actions in `embark-general-map' are available no matter what
     75 ;; type of completion you are in the middle of.  By default this
     76 ;; includes bindings to save the current candidate in the kill ring
     77 ;; and to insert the current candidate in the previously selected
     78 ;; buffer (the buffer that was current when you executed a command
     79 ;; that opened up the minibuffer).
     80 
     81 ;; You can read about the Embark GitHub project wiki:
     82 ;; https://github.com/oantolin/embark/wiki/Default-Actions
     83 
     84 ;; Besides acting individually on targets, Embark lets you work
     85 ;; collectively on a set of target candidates.  For example, while
     86 ;; you are in the minibuffer the candidates are simply the possible
     87 ;; completions of your input.  Embark provides three commands to work
     88 ;; on candidate sets:
     89 
     90 ;; - The `embark-act-all' command runs the same action on each of the
     91 ;;   current candidates.  It is just like using `embark-act' on each
     92 ;;   candidate in turn.
     93 
     94 ;; - The `embark-collect' command produces a buffer listing all
     95 ;;   candidates, for you to peruse and run actions on at your leisure.
     96 ;;   The candidates are displayed as a list showing additional
     97 ;;   annotations.
     98 
     99 ;; - The `embark-export' command tries to open a buffer in an
    100 ;;   appropriate major mode for the set of candidates.  If the
    101 ;;   candidates are files export produces a Dired buffer; if they are
    102 ;;   buffers, you get an Ibuffer buffer; and if they are packages you
    103 ;;   get a buffer in package menu mode.
    104 
    105 ;; These are always available as "actions" (although they do not act
    106 ;; on just the current target but on all candidates) for embark-act
    107 ;; and are bound to A, S (for "snapshot") and E, respectively, in
    108 ;; embark-general-map.  This means that you do not have to bind your
    109 ;; own key bindings for these (although you can, of course), just a
    110 ;; key binding for `embark-act'.
    111 
    112 ;;; Code:
    113 
    114 
    115 (require 'compat)
    116 (eval-when-compile (require 'subr-x))
    117 
    118 (require 'ffap) ; used to recognize file and url targets
    119 
    120 ;;; User facing options
    121 
    122 (defgroup embark nil
    123   "Emacs Mini-Buffer Actions Rooted in Keymaps."
    124   :link '(info-link :tag "Info Manual" "(embark)")
    125   :link '(url-link :tag "Homepage" "https://github.com/oantolin/embark")
    126   :link '(emacs-library-link :tag "Library Source" "embark.el")
    127   :group 'minibuffer
    128   :prefix "embark-")
    129 
    130 (defcustom embark-keymap-alist
    131   '((file embark-file-map)
    132     (library embark-library-map)
    133     (environment-variables embark-file-map) ; they come up in file completion
    134     (url embark-url-map)
    135     (email embark-email-map)
    136     (buffer embark-buffer-map)
    137     (tab embark-tab-map)
    138     (expression embark-expression-map)
    139     (identifier embark-identifier-map)
    140     (defun embark-defun-map)
    141     (symbol embark-symbol-map)
    142     (face embark-face-map)
    143     (command embark-command-map)
    144     (variable embark-variable-map)
    145     (function embark-function-map)
    146     (minor-mode embark-command-map)
    147     (unicode-name embark-unicode-name-map)
    148     (package embark-package-map)
    149     (bookmark embark-bookmark-map)
    150     (region embark-region-map)
    151     (sentence embark-sentence-map)
    152     (paragraph embark-paragraph-map)
    153     (kill-ring embark-kill-ring-map)
    154     (heading embark-heading-map)
    155     (t embark-general-map))
    156   "Alist of action types and corresponding keymaps.
    157 The special key t is associated with the default keymap to use.
    158 Each value can be either a single symbol whose value is a keymap,
    159 or a list of such symbols."
    160   :type '(alist :key-type (symbol :tag "Target type")
    161                 :value-type (choice (variable :tag "Keymap")
    162                              (repeat :tag "Keymaps" variable))))
    163 
    164 (defcustom embark-target-finders
    165   '(embark-target-top-minibuffer-completion
    166     embark-target-active-region
    167     embark-target-text-heading-at-point
    168     embark-target-collect-candidate
    169     embark-target-completion-at-point
    170     embark-target-bug-reference-at-point
    171     embark-target-package-at-point
    172     embark-target-email-at-point
    173     embark-target-url-at-point
    174     embark-target-file-at-point
    175     embark-target-custom-variable-at-point
    176     embark-target-identifier-at-point
    177     embark-target-library-file-at-point
    178     embark-target-expression-at-point
    179     embark-target-sentence-at-point
    180     embark-target-paragraph-at-point
    181     embark-target-defun-at-point
    182     embark-target-prog-heading-at-point)
    183   "List of functions to determine the target in current context.
    184 Each function should take no arguments and return one of:
    185 
    186 1. a cons (TYPE . TARGET) where TARGET is a string and TYPE is a
    187    symbol (which is looked up in `embark-keymap-alist' to
    188    determine which additional keybindings for actions to setup);
    189 
    190 2. a dotted list of the form (TYPE TARGET START . END), where
    191    START and END are the buffer positions bounding TARGET, used
    192    for highlighting; or
    193 
    194 3. a possibly empty list of targets, each of type 1 or 2 (in
    195    particular if a target finder does not find any targets, it
    196    should return nil)."
    197   :type 'hook)
    198 
    199 (defcustom embark-transformer-alist
    200   '((minor-mode . embark--lookup-lighter-minor-mode)
    201     (embark-keybinding . embark--keybinding-command)
    202     (project-file . embark--project-file-full-path)
    203     (package . embark--remove-package-version)
    204     (multi-category . embark--refine-multi-category)
    205     (file . embark--simplify-path))
    206   "Alist associating type to functions for transforming targets.
    207 Each function should take a type and a target string and return a
    208 pair of the form a `cons' of the new type and the new target."
    209   :type '(alist :key-type symbol :value-type function))
    210 
    211 (defcustom embark-become-keymaps
    212   '(embark-become-help-map
    213     embark-become-file+buffer-map
    214     embark-become-shell-command-map
    215     embark-become-match-map)
    216   "List of keymaps for `embark-become'.
    217 Each keymap groups a set of related commands that can
    218 conveniently become one another."
    219   :type '(repeat variable))
    220 
    221 (defcustom embark-prompter 'embark-keymap-prompter
    222   "Function used to prompt the user for actions.
    223 This should be set to a function that prompts the use for an
    224 action and returns the symbol naming the action command.  The
    225 default value, `embark-keymap-prompter' activates the type
    226 specific action keymap given in `embark-keymap-alist'.
    227 There is also `embark-completing-read-prompter' which
    228 prompts for an action with completion."
    229   :type '(choice (const :tag "Use action keymaps" embark-keymap-prompter)
    230                  (const :tag "Read action with completion"
    231                         embark-completing-read-prompter)
    232                  (function :tag "Other")))
    233 
    234 (defcustom embark-keymap-prompter-key "@"
    235   "Key to switch to the keymap prompter from `embark-completing-read-prompter'.
    236 
    237 The key must be either nil or a string.  The
    238 string must be accepted by `key-valid-p'."
    239   :type '(choice key (const :tag "None" nil)))
    240 
    241 (defcustom embark-cycle-key nil
    242   "Key used for `embark-cycle'.
    243 
    244 If the key is set to nil it defaults to the global binding of
    245 `embark-act'.  The key must be a string which is accepted by
    246 `key-valid-p'."
    247   :type '(choice key (const :tag "Use embark-act key" nil)))
    248 
    249 (defcustom embark-help-key "C-h"
    250   "Key used for help.
    251 
    252 The key must be either nil or a string.  The
    253 string must be accepted by `key-valid-p'."
    254   :type '(choice (const "C-h")
    255                  (const "?")
    256                  (const :tag "None" nil)
    257                  key))
    258 
    259 (defcustom embark-keybinding-repeat
    260   (propertize "*" 'face 'embark-keybinding-repeat)
    261   "Indicator string for repeatable keybindings.
    262 Keybindings are formatted by the `completing-read' prompter and
    263 the verbose indicator."
    264   :type 'string)
    265 
    266 (defface embark-keybinding-repeat
    267   '((t :inherit font-lock-builtin-face))
    268   "Face used to indicate keybindings as repeatable.")
    269 
    270 (defface embark-keybinding '((t :inherit success))
    271   "Face used to display key bindings.
    272 Used by `embark-completing-read-prompter' and `embark-keymap-help'.")
    273 
    274 (defface embark-keymap '((t :slant italic))
    275   "Face used to display keymaps.
    276 Used by `embark-completing-read-prompter' and `embark-keymap-help'.")
    277 
    278 (defface embark-target '((t :inherit highlight))
    279   "Face used to highlight the target at point during `embark-act'.")
    280 
    281 (defcustom embark-quit-after-action t
    282   "Should `embark-act' quit the minibuffer?
    283 This controls whether calling `embark-act' without a prefix
    284 argument quits the minibuffer or not.  You can always get the
    285 opposite behavior to that indicated by this variable by calling
    286 `embark-act' with \\[universal-argument].
    287 
    288 Note that `embark-act' can also be called from outside the
    289 minibuffer and this variable is irrelevant in that case.
    290 
    291 In addition to t or nil this variable can also be set to an
    292 alist to specify the minibuffer quitting behavior per command.
    293 In the alist case one can additionally use the key t to
    294 prescribe a default for commands not used as alist keys."
    295   :type '(choice (const :tag "Always quit" t)
    296                  (const :tag "Never quit" nil)
    297                  (alist :tag "Configure per action"
    298                         :key-type (choice (function :tag "Action")
    299                                           (const :tag "All other actions" t))
    300                         :value-type (choice (const :tag "Quit")
    301                                             (const :tag "Do not quit")))))
    302 
    303 (defcustom embark-confirm-act-all t
    304   "Should `embark-act-all' prompt the user for confirmation?
    305 Even if this variable is nil you may still be prompted to confirm
    306 some uses of `embark-act-all', namely, for those actions whose
    307 entry in `embark-pre-action-hooks' includes `embark--confirm'."
    308   :type 'boolean)
    309 
    310 (defcustom embark-default-action-overrides nil
    311   "Alist associating target types with overriding default actions.
    312 When the source of a target is minibuffer completion, the default
    313 action for it is usually the command that opened the minibuffer
    314 in the first place but this can be overridden for a given type by
    315 an entry in this list.
    316 
    317 For example, if you run `delete-file' the default action for its
    318 completion candidates is `delete-file' itself.  You may prefer to
    319 make `find-file' the default action for all files, even if they
    320 were obtained from a `delete-file' prompt.  In that case you can
    321 configure that by adding an entry to this variable pairing `file'
    322 with `find-file'.
    323 
    324 In addition to target types, you can also use as keys in this alist,
    325 pairs of a target type and a command name.  Such a pair indicates that
    326 the override only applies if the target was obtained from minibuffer
    327 completion from that command.  For example adding an
    328 entry (cons (cons \\='file \\='delete-file) \\='find-file) to this alist would
    329 indicate that for files at the prompt of the `delete-file' command,
    330 `find-file' should be used as the default action."
    331   :type '(alist :key-type (choice (symbol :tag "Type")
    332                                   (cons (symbol :tag "Type")
    333                                         (symbol :tag "Command")))
    334                 :value-type (function :tag "Default action")))
    335 
    336 (defcustom embark-target-injection-hooks
    337   '((async-shell-command embark--allow-edit embark--shell-prep)
    338     (shell-command embark--allow-edit embark--shell-prep)
    339     (pp-eval-expression embark--eval-prep)
    340     (eval-expression embark--eval-prep)
    341     (package-delete embark--force-complete)
    342     ;; commands evaluating code found in the buffer, which may in turn prompt
    343     (embark-pp-eval-defun embark--ignore-target)
    344     (eval-defun embark--ignore-target)
    345     (eval-last-sexp embark--ignore-target)
    346     (embark-eval-replace embark--ignore-target)
    347     ;; commands which prompt for something that is *not* the target
    348     (write-region embark--ignore-target)
    349     (append-to-file embark--ignore-target)
    350     (shell-command-on-region embark--ignore-target)
    351     (format-encode-region embark--ignore-target)
    352     (format-decode-region embark--ignore-target)
    353     (xref-find-definitions embark--ignore-target)
    354     (xref-find-references embark--ignore-target)
    355     (sort-regexp-fields embark--ignore-target)
    356     (align-regexp embark--ignore-target))
    357   "Alist associating commands with post-injection setup hooks.
    358 For commands appearing as keys in this alist, run the
    359 corresponding value as a setup hook after injecting the target
    360 into in the minibuffer and before acting on it.  The hooks must
    361 accept arbitrary keyword arguments.  The :action command, the
    362 :target string and target :type are always present.  For actions
    363 at point the target :bounds are passed too.  The default pre-action
    364 hook is specified by the entry with key t.  Furthermore, hooks with
    365 the key :always are executed always."
    366   :type '(alist :key-type
    367                 (choice symbol
    368                         (const :tag "Default" t)
    369                         (const :tag "Always" :always))
    370                 :value-type hook))
    371 
    372 (defcustom embark-pre-action-hooks
    373   `(;; commands that need to position point at the beginning or end
    374     (eval-last-sexp embark--end-of-target)
    375     (indent-pp-sexp embark--beginning-of-target)
    376     (backward-up-list embark--beginning-of-target)
    377     (backward-list embark--beginning-of-target)
    378     (forward-list embark--end-of-target)
    379     (forward-sexp embark--end-of-target)
    380     (backward-sexp embark--beginning-of-target)
    381     (raise-sexp embark--beginning-of-target)
    382     (kill-sexp embark--beginning-of-target)
    383     (mark-sexp embark--beginning-of-target)
    384     (transpose-sexps embark--end-of-target)
    385     (transpose-sentences embark--end-of-target)
    386     (transpose-paragraphs embark--end-of-target)
    387     (forward-sentence embark--end-of-target)
    388     (backward-sentence embark--beginning-of-target)
    389     (backward-paragraph embark--beginning-of-target)
    390     (embark-insert embark--end-of-target)
    391     ;; commands we want to be able to jump back from
    392     ;; (embark-find-definition achieves this by calling
    393     ;; xref-find-definitions which pushes the markers itself)
    394     (find-library embark--xref-push-marker)
    395     ;; commands which prompt the user for confirmation before running
    396     (delete-file embark--confirm)
    397     (delete-directory embark--confirm)
    398     (kill-buffer embark--confirm)
    399     (embark-kill-buffer-and-window embark--confirm)
    400     (bookmark-delete embark--confirm)
    401     (package-delete embark--confirm)
    402     (,'tab-bar-close-tab-by-name embark--confirm) ;; Avoid package-lint warning
    403     ;; search for region contents outside said region
    404     (embark-isearch embark--unmark-target)
    405     (occur embark--unmark-target)
    406     (query-replace embark--beginning-of-target embark--unmark-target)
    407     (query-replace-regexp embark--beginning-of-target embark--unmark-target)
    408     ;; mark pseudo-action
    409     (mark embark--mark-target)
    410     ;; shells in new buffers
    411     (shell embark--universal-argument)
    412     (eshell embark--universal-argument)
    413     ;; do the actual work of selecting & deselecting targets
    414     (embark-select embark--select))
    415   "Alist associating commands with pre-action hooks.
    416 The hooks are run right before an action is embarked upon.  See
    417 `embark-target-injection-hooks' for information about the hook
    418 arguments and more details."
    419   :type '(alist :key-type
    420                 (choice symbol
    421                         (const :tag "Default" t)
    422                         (const :tag "Always" :always))
    423                 :value-type hook))
    424 
    425 (defcustom embark-post-action-hooks
    426   `((bookmark-delete embark--restart)
    427     (bookmark-rename embark--restart)
    428     (delete-file embark--restart)
    429     (embark-kill-ring-remove embark--restart)
    430     (embark-recentf-remove embark--restart)
    431     (embark-history-remove embark--restart)
    432     (rename-file embark--restart)
    433     (copy-file embark--restart)
    434     (delete-directory embark--restart)
    435     (make-directory embark--restart)
    436     (kill-buffer embark--restart)
    437     (embark-rename-buffer embark--restart)
    438     (,'tab-bar-rename-tab-by-name embark--restart) ;; Avoid package-lint warning
    439     (,'tab-bar-close-tab-by-name embark--restart)
    440     (package-delete embark--restart))
    441   "Alist associating commands with post-action hooks.
    442 The hooks are run after an embarked upon action concludes.  See
    443 `embark-target-injection-hooks' for information about the hook
    444 arguments and more details."
    445   :type '(alist :key-type
    446                 (choice symbol
    447                         (const :tag "Default" t)
    448                         (const :tag "Always" :always))
    449                 :value-type hook))
    450 
    451 (defcustom embark-around-action-hooks
    452   '(;; use directory of target as default-directory
    453     (shell embark--cd)
    454     (eshell embark--cd)
    455     ;; narrow to target for duration of action
    456     (repunctuate-sentences embark--narrow-to-target)
    457     ;; mark the target preserving point and previous mark
    458     (kill-region embark--mark-target)
    459     (kill-ring-save embark--mark-target)
    460     (indent-region embark--mark-target)
    461     (ispell-region embark--mark-target)
    462     (fill-region embark--mark-target)
    463     (upcase-region embark--mark-target)
    464     (downcase-region embark--mark-target)
    465     (capitalize-region embark--mark-target)
    466     (count-words-region embark--mark-target)
    467     (count-words embark--mark-target)
    468     (shell-command-on-region embark--mark-target)
    469     (delete-region embark--mark-target)
    470     (format-encode-region embark--mark-target)
    471     (format-decode-region embark--mark-target)
    472     (write-region embark--mark-target)
    473     (append-to-file embark--mark-target)
    474     (shell-command-on-region embark--mark-target)
    475     (embark-eval-replace embark--mark-target))
    476   "Alist associating commands with post-action hooks.
    477 The hooks are run instead of the embarked upon action.  The hook
    478 can decide whether or not to run the action or it can run it
    479 in some special environment, like inside a let-binding or inside
    480 `save-excursion'.  Each hook is called with keyword argument :run
    481 providing a function encapsulating the following around hooks and
    482 the action; the hook additionally receives the keyword arguments
    483 used for other types of action hooks, for more details see
    484 `embark-target-injection-hooks'."
    485   :type '(alist :key-type
    486                 (choice symbol
    487                         (const :tag "Default" t)
    488                         (const :tag "Always" :always))
    489                 :value-type hook))
    490 
    491 (defcustom embark-multitarget-actions '(embark-insert embark-copy-as-kill)
    492   "Commands for which `embark-act-all' should pass a list of targets.
    493 Normally `embark-act-all' runs the same action on each candidate
    494 separately, but when a command included in this variable's value
    495 is used as an action, `embark-act-all' will instead call it
    496 non-interactively with a single argument: the list of all
    497 candidates.  For commands on this list `embark-act' behaves
    498 similarly: it calls them non-interactively with a single
    499 argument: a one element list containing the target."
    500   :type '(repeat function))
    501 
    502 (defcustom embark-repeat-actions
    503   '((mark . region)
    504     ;; outline commands
    505     outline-next-visible-heading outline-previous-visible-heading
    506     outline-forward-same-level outline-backward-same-level
    507     outline-demote outline-promote
    508     outline-show-subtree (outline-mark-subtree . region)
    509     outline-move-subtree-up outline-move-subtree-down
    510     outline-up-heading outline-hide-subtree outline-cycle
    511     ;; org commands (remapped outline commands)
    512     org-forward-heading-same-level org-backward-heading-same-level
    513     org-next-visible-heading org-previous-visible-heading
    514     org-demote-subtree org-promote-subtree
    515     org-show-subtree (org-mark-subtree . region)
    516     org-move-subtree-up org-move-subtree-down
    517     ;; transpose commands
    518     transpose-sexps transpose-sentences transpose-paragraphs
    519     ;; movement
    520     embark-next-symbol embark-previous-symbol
    521     backward-up-list backward-list forward-list forward-sexp
    522     backward-sexp forward-sentence backward-sentence
    523     forward-paragraph backward-paragraph)
    524   "List of repeatable actions.
    525 When you use a command on this list as an Embark action from
    526 outside the minibuffer, `embark-act' does not exit but instead
    527 lets you act again on the possibly new target you reach.
    528 
    529 By default, after using one of these actions, when `embark-act'
    530 looks for targets again, it will start the target cycle at the
    531 same type as the previously acted upon target; that is, you
    532 \"don't loose your place in the target cycle\".
    533 
    534 Sometimes, however, you'll want to prioritize a different type of
    535 target to continue acting on.  The main example of this that if
    536 you use a marking command as an action, you almost always want to
    537 act on the region next.  For those cases, in addition to
    538 commands, you can also place on this list a pair of a command and
    539 the desired starting type for the target cycle for the next
    540 action."
    541   :type '(repeat (choice function
    542                          (cons function
    543                                (symbol :tag "Next target type")))))
    544 
    545 ;;; Stashing information for actions in buffer local variables
    546 
    547 (defvar-local embark--type nil
    548   "Cache for the completion type, meant to be set buffer-locally.")
    549 
    550 (defvar-local embark--target-buffer nil
    551   "Cache for the previous buffer, meant to be set buffer-locally.")
    552 
    553 (defvar-local embark--target-window nil
    554   "Cache for the previous window, meant to be set buffer-locally.
    555 Since windows can be reused to display different buffers, this
    556 window should only be used if it displays the buffer stored in
    557 the variable `embark--target-buffer'.")
    558 
    559 (defvar-local embark--command nil
    560   "Command that started the completion session.")
    561 
    562 (defvar-local embark--toggle-quit nil
    563   "Should we toggle the default quitting behavior for the next action?")
    564 
    565 (defun embark--minibuffer-point ()
    566   "Return length of minibuffer contents."
    567   (max 0 (- (point) (minibuffer-prompt-end))))
    568 
    569 (defun embark--default-directory ()
    570   "Guess a reasonable default directory for the current candidates."
    571   (if (and (minibufferp) minibuffer-completing-file-name)
    572       (let ((end (minibuffer-prompt-end))
    573             (contents (minibuffer-contents)))
    574         (expand-file-name
    575          (substitute-in-file-name
    576           (buffer-substring
    577            end
    578            (+ end
    579               (or (cdr
    580                    (last
    581                     (completion-all-completions
    582                      contents
    583                      minibuffer-completion-table
    584                      minibuffer-completion-predicate
    585                      (embark--minibuffer-point))))
    586                   (cl-position ?/ contents :from-end t)
    587                   0))))))
    588     default-directory))
    589 
    590 (defun embark--target-buffer ()
    591   "Return buffer that should be targeted by Embark actions."
    592   (cond
    593    ((and (minibufferp) (minibuffer-selected-window))
    594     (window-buffer (minibuffer-selected-window)))
    595    ((and embark--target-buffer (buffer-live-p embark--target-buffer))
    596     embark--target-buffer)
    597    (t (current-buffer))))
    598 
    599 (defun embark--target-window (&optional display)
    600   "Return window which should be selected when Embark actions run.
    601 If DISPLAY is non-nil, call `display-buffer' to produce the
    602 window if necessary."
    603   (cond
    604    ((and (minibufferp) (minibuffer-selected-window))
    605     (minibuffer-selected-window))
    606    ((and embark--target-window
    607          (window-live-p embark--target-window)
    608          (or (not (buffer-live-p embark--target-buffer))
    609              (eq (window-buffer embark--target-window) embark--target-buffer)))
    610     embark--target-window)
    611    ((and embark--target-buffer (buffer-live-p embark--target-buffer))
    612     (or (get-buffer-window embark--target-buffer)
    613         (when display (display-buffer embark--target-buffer))))
    614    (display (selected-window))))
    615 
    616 (defun embark--cache-info (buffer)
    617   "Cache information needed for actions in variables local to BUFFER.
    618 BUFFER defaults to the current buffer."
    619   (let ((cmd embark--command)
    620         (dir (embark--default-directory))
    621         (target-buffer (embark--target-buffer))
    622         (target-window (embark--target-window)))
    623     (with-current-buffer buffer
    624       (setq embark--command cmd
    625             default-directory dir
    626             embark--target-buffer target-buffer
    627             embark--target-window target-window))))
    628 
    629 (defun embark--cache-info--completion-list ()
    630   "Cache information needed for actions in a *Completions* buffer.
    631 Meant to be be added to `completion-setup-hook'."
    632   ;; when completion-setup-hook hook runs, the *Completions* buffer is
    633   ;; available in the variable standard-output
    634   (embark--cache-info standard-output)
    635   (with-current-buffer standard-output
    636     (when (minibufferp completion-reference-buffer)
    637       (setq embark--type
    638             (completion-metadata-get
    639              (with-current-buffer completion-reference-buffer
    640                (embark--metadata))
    641              'category)))))
    642 
    643 ;; We have to add this *after* completion-setup-function because that's
    644 ;; when the buffer is put in completion-list-mode and turning the mode
    645 ;; on kills all local variables! So we use a depth of 5.
    646 (add-hook 'completion-setup-hook #'embark--cache-info--completion-list 5)
    647 
    648 ;;;###autoload
    649 (progn
    650   (defun embark--record-this-command ()
    651     "Record command which opened the minibuffer.
    652 We record this because it will be the default action.
    653 This function is meant to be added to `minibuffer-setup-hook'."
    654     (setq-local embark--command this-command))
    655   (add-hook 'minibuffer-setup-hook #'embark--record-this-command))
    656 
    657 ;;; Internal variables
    658 
    659 (defvar embark--prompter-history nil
    660   "History used by the `embark-completing-read-prompter'.")
    661 
    662 ;;; Core functionality
    663 
    664 (defconst embark--verbose-indicator-buffer " *Embark Actions*")
    665 
    666 (defvar embark--minimal-indicator-overlay nil)
    667 
    668 (defun embark--metadata ()
    669   "Return current minibuffer completion metadata."
    670   (completion-metadata
    671    (buffer-substring-no-properties
    672     (minibuffer-prompt-end)
    673     (max (minibuffer-prompt-end) (point)))
    674    minibuffer-completion-table
    675    minibuffer-completion-predicate))
    676 
    677 (defun embark-target-active-region ()
    678   "Target the region if active."
    679   (when (use-region-p)
    680     (let ((start (region-beginning))
    681           (end (region-end)))
    682       `(region ,(buffer-substring start end) . (,start . ,end)))))
    683 
    684 (autoload 'dired-get-filename "dired")
    685 (declare-function image-dired-original-file-name "image-dired")
    686 
    687 (defun embark-target-file-at-point ()
    688   "Target file at point.
    689 This function mostly relies on `ffap-file-at-point', with the
    690 following exceptions:
    691 
    692 - In `dired-mode', it uses `dired-get-filename' instead.
    693 
    694 - In `imaged-dired-thumbnail-mode', it uses
    695   `image-dired-original-file-name' instead."
    696   (if-let (file (or (and (derived-mode-p 'dired-mode)
    697                          (dired-get-filename t 'no-error-if-not-filep))
    698                     (and (derived-mode-p 'image-dired-thumbnail-mode)
    699                          (image-dired-original-file-name))))
    700       (save-excursion
    701         (end-of-line)
    702         `(file ,(abbreviate-file-name (expand-file-name file))
    703                ,(save-excursion
    704                   (re-search-backward " " (line-beginning-position) 'noerror)
    705                   (1+ (point)))
    706                . ,(point)))
    707     (when-let* ((ffap-file (ffap-file-at-point))
    708                 (tap-file (thing-at-point 'filename))
    709                 ((not (or (ffap-url-p tap-file) (ffap-el-mode tap-file)))))
    710       `(file ,(abbreviate-file-name (expand-file-name ffap-file))
    711              ;; TODO the boundaries may be wrong, this should be generalized.
    712              ;; Unfortunately ffap does not make the bounds available.
    713              . ,(bounds-of-thing-at-point 'filename)))))
    714 
    715 (defun embark-target-library-file-at-point ()
    716   "Target the file of the Emacs Lisp library at point.
    717 The function `embark-target-file-at-point' could also easily
    718 target Emacs Lisp library files, the only reason it doesn't is so
    719 that library files and other types of file targets can be given
    720 different priorities in `embark-target-finders'."
    721   (when-let* ((name (thing-at-point 'filename))
    722               (lib (ffap-el-mode name)))
    723     `(file ,lib . ,(bounds-of-thing-at-point 'filename))))
    724 
    725 (defun embark-target-bug-reference-at-point ()
    726   "Target a bug reference at point."
    727   (when-let ((ov (seq-find (lambda (ov) (overlay-get ov 'bug-reference-url))
    728                            (overlays-at (point)))))
    729     `(url ,(overlay-get ov 'bug-reference-url)
    730           ,(overlay-start ov) . ,(overlay-end ov))))
    731 
    732 (defun embark-target-package-at-point ()
    733   "Target the package on the current line in a packages buffer."
    734   (when (derived-mode-p 'package-menu-mode)
    735     (when-let ((pkg (get-text-property (point) 'tabulated-list-id)))
    736       `(package ,(symbol-name (package-desc-name pkg))
    737                 ,(line-beginning-position) . ,(line-end-position)))))
    738 
    739 (defun embark-target-email-at-point ()
    740   "Target the email address at point."
    741   (when-let ((email (thing-at-point 'email)))
    742     (when (string-prefix-p "mailto:" email)
    743       (setq email (string-remove-prefix "mailto:" email)))
    744     `(email ,email . ,(bounds-of-thing-at-point 'email))))
    745 
    746 (defun embark-target-url-at-point ()
    747   "Target the URL at point."
    748   (if-let ((url (or (get-text-property (point) 'shr-url)
    749                     (get-text-property (point) 'image-url))))
    750       `(url ,url
    751             ,(previous-single-property-change
    752               (min (1+ (point)) (point-max)) 'mouse-face nil (point-min))
    753             . ,(next-single-property-change
    754                 (point) 'mouse-face nil (point-max)))
    755     (when-let ((url (thing-at-point 'url)))
    756       `(url ,url . ,(thing-at-point-bounds-of-url-at-point t)))))
    757 
    758 (declare-function widget-at "wid-edit")
    759 
    760 (defun embark-target-custom-variable-at-point ()
    761   "Target the variable corresponding to the customize widget at point."
    762   (when (derived-mode-p 'Custom-mode)
    763     (save-excursion
    764       (beginning-of-line)
    765       (when-let* ((widget (widget-at (point)))
    766                   (var (and (eq (car widget) 'custom-visibility)
    767                             (plist-get (cdr widget) :parent)))
    768                   (sym (and (eq (car var) 'custom-variable)
    769                             (plist-get (cdr var) :value))))
    770         `(variable
    771           ,(symbol-name sym)
    772           ,(point)
    773           . ,(progn
    774                (re-search-forward ":" (line-end-position) 'noerror)
    775                (point)))))))
    776 
    777 ;; NOTE: There is also (thing-at-point 'list), however it does
    778 ;; not work on strings and requires the point to be inside the
    779 ;; parentheses. This version here is slightly more general.
    780 (defun embark-target-expression-at-point ()
    781   "Target expression at point."
    782   (cl-flet ((syntax-p (class &optional (delta 0))
    783               (and (<= (point-min) (+ (point) delta) (point-max))
    784                    (eq (pcase class
    785                          ('open 4) ('close 5) ('prefix 6) ('string 7))
    786                        (syntax-class (syntax-after (+ (point) delta)))))))
    787     (when-let
    788         ((start
    789           (pcase-let ((`(_ ,open _ ,string _ _ _ _ ,start _ _) (syntax-ppss)))
    790             (ignore-errors ; set start=nil if delimiters are unbalanced
    791               (cond
    792                 (string start)
    793                 ((or (syntax-p 'open) (syntax-p 'prefix))
    794                  (save-excursion (backward-prefix-chars) (point)))
    795                 ((syntax-p 'close -1)
    796                  (save-excursion
    797                    (backward-sexp) (backward-prefix-chars) (point)))
    798                 ((syntax-p 'string) (point))
    799                 ((syntax-p 'string -1) (scan-sexps (point) -1))
    800                 (t open)))))
    801          (end (ignore-errors (scan-sexps start 1))))
    802       (unless (eq start (car (bounds-of-thing-at-point 'defun)))
    803       `(expression ,(buffer-substring start end) ,start . ,end)))))
    804 
    805 (defmacro embark-define-thingatpt-target (thing &rest modes)
    806   "Define a target finder for THING using the thingatpt library.
    807 If any MODES are given, the target finder only applies to buffers
    808 in one of those major modes."
    809   (declare (indent 1))
    810   `(defun ,(intern (format "embark-target-%s-at-point" thing)) ()
    811      ,(format "Target %s at point." thing)
    812      (when ,(if modes `(derived-mode-p ,@(mapcar (lambda (m) `',m) modes)) t)
    813        (when-let (bounds (bounds-of-thing-at-point ',thing))
    814          (cons ',thing (cons
    815                         (buffer-substring (car bounds) (cdr bounds))
    816                         bounds))))))
    817 
    818 (embark-define-thingatpt-target defun)
    819 (embark-define-thingatpt-target sentence
    820   text-mode help-mode Info-mode man-common)
    821 (embark-define-thingatpt-target paragraph
    822   text-mode help-mode Info-mode man-common)
    823 
    824 (defun embark--identifier-types (identifier)
    825   "Return list of target types appropriate for IDENTIFIER."
    826   (let ((symbol (intern-soft identifier)))
    827     (if (not
    828          (or (derived-mode-p 'emacs-lisp-mode 'inferior-emacs-lisp-mode)
    829              (and (not (derived-mode-p 'prog-mode))
    830                   symbol
    831                   (or (boundp symbol) (fboundp symbol) (symbol-plist symbol)))))
    832         '(identifier)
    833       (let* ((library (ffap-el-mode identifier))
    834              (types
    835               (append
    836                (and (commandp symbol) '(command))
    837                (and symbol (boundp symbol) (not (keywordp symbol)) '(variable))
    838                (and (fboundp symbol) (not (commandp symbol)) '(function))
    839                (and (facep symbol) '(face))
    840                (and library '(library))
    841                (and (featurep 'package) (embark--package-desc symbol)
    842                     '(package)))))
    843         (when (and library
    844                    (looking-back "\\(?:require\\|use-package\\).*"
    845                                  (line-beginning-position)))
    846           (setq types (embark--rotate types (cl-position 'library types))))
    847         (or types '(symbol))))))
    848 
    849 (defun embark-target-identifier-at-point ()
    850   "Target identifier at point.
    851 
    852 In Emacs Lisp and IELM buffers the identifier is promoted to a
    853 symbol, for which more actions are available.  Identifiers are
    854 also promoted to symbols if they are interned Emacs Lisp symbols
    855 and found in a buffer in a major mode that is not derived from
    856 `prog-mode' (this is intended for when you might be reading or
    857 writing about Emacs).
    858 
    859 As a convenience, in Org Mode an initial ' or surrounding == or
    860 ~~ are removed."
    861   (when-let (bounds (bounds-of-thing-at-point 'symbol))
    862     (let ((name (buffer-substring (car bounds) (cdr bounds))))
    863       (when (derived-mode-p 'org-mode)
    864         (cond ((string-prefix-p "'" name)
    865                (setq name (substring name 1))
    866                (cl-incf (car bounds)))
    867               ((string-match-p "^\\([=~]\\).*\\1$" name)
    868                (setq name (substring name 1 -1))
    869                (cl-incf (car bounds))
    870                (cl-decf (cdr bounds)))))
    871       (mapcar (lambda (type) `(,type ,name . ,bounds))
    872               (embark--identifier-types name)))))
    873 
    874 (defun embark-target-heading-at-point ()
    875   "Target the outline heading at point."
    876   (let ((beg (line-beginning-position))
    877         (end (line-end-position)))
    878     (when (save-excursion
    879             (goto-char beg)
    880             (and (bolp)
    881                  (looking-at
    882                   ;; default definition from outline.el
    883                   (or (bound-and-true-p outline-regexp) "[*\^L]+"))))
    884       (require 'outline) ;; Ensure that outline commands are available
    885       `(heading ,(buffer-substring beg end) ,beg . ,end))))
    886 
    887 (defun embark-target-text-heading-at-point ()
    888   "Target the outline heading at point in text modes."
    889   (when (derived-mode-p 'text-mode)
    890     (embark-target-heading-at-point)))
    891 
    892 (defun embark-target-prog-heading-at-point ()
    893   "Target the outline heading at point in programming modes."
    894   (when (derived-mode-p 'prog-mode)
    895     (embark-target-heading-at-point)))
    896 
    897 (defun embark-target-top-minibuffer-completion ()
    898   "Target the top completion candidate in the minibuffer.
    899 Return the category metadatum as the type of the target.
    900 
    901 This target finder is meant for the default completion UI and
    902 completion UI highly compatible with it, like Icomplete.
    903 Many completion UIs can still work with Embark but will need
    904 their own target finder.  See for example
    905 `embark--vertico-selected'."
    906   (when (and (minibufferp) minibuffer-completion-table)
    907     (pcase-let* ((`(,category . ,candidates) (embark-minibuffer-candidates))
    908                  (contents (minibuffer-contents))
    909                  (top (if (test-completion contents
    910                                            minibuffer-completion-table
    911                                            minibuffer-completion-predicate)
    912                           contents
    913                         (let ((completions (completion-all-sorted-completions)))
    914                           (if (null completions)
    915                               contents
    916                             (concat
    917                              (substring contents
    918                                         0 (or (cdr (last completions)) 0))
    919                              (car completions)))))))
    920       (cons category (or (car (member top candidates)) top)))))
    921 
    922 (defun embark-target-collect-candidate ()
    923   "Target the collect candidate at point."
    924   (when (derived-mode-p 'embark-collect-mode)
    925     (when-let ((button
    926                 (pcase (get-text-property (point) 'tabulated-list-column-name)
    927                   ("Candidate" (button-at (point)))
    928                   ("Annotation" (previous-button (point)))))
    929                (start (button-start button))
    930                (end (button-end button))
    931                (candidate (tabulated-list-get-id)))
    932       `(,embark--type
    933         ,(if (eq embark--type 'file)
    934              (abbreviate-file-name (expand-file-name candidate))
    935            candidate)
    936         ,start . ,end))))
    937 
    938 (defun embark-target-completion-at-point ()
    939   "Return the completion candidate at point in a completions buffer."
    940   (when (derived-mode-p 'completion-list-mode)
    941     (if (not (get-text-property (point) 'mouse-face))
    942         (user-error "No completion here")
    943       ;; this fairly delicate logic is taken from `choose-completion'
    944       (let (beg end)
    945         (cond
    946          ((and (not (eobp)) (get-text-property (point) 'mouse-face))
    947           (setq end (point) beg (1+ (point))))
    948          ((and (not (bobp))
    949                (get-text-property (1- (point)) 'mouse-face))
    950           (setq end (1- (point)) beg (point)))
    951          (t (user-error "No completion here")))
    952         (setq beg (previous-single-property-change beg 'mouse-face))
    953         (setq end (or (next-single-property-change end 'mouse-face)
    954                       (point-max)))
    955         (let ((raw (or (get-text-property beg 'completion--string)
    956                        (buffer-substring beg end))))
    957           `(,embark--type
    958             ,(if (eq embark--type 'file)
    959                  (abbreviate-file-name (expand-file-name raw))
    960                raw)
    961             ,beg . ,end))))))
    962 
    963 (defun embark--cycle-key ()
    964   "Return the key to use for `embark-cycle'."
    965   (if embark-cycle-key
    966       (if (key-valid-p embark-cycle-key)
    967           (key-parse embark-cycle-key)
    968         (error "`embark-cycle-key' is invalid"))
    969     (car (where-is-internal #'embark-act))))
    970 
    971 (defun embark--raw-action-keymap (type)
    972   "Return raw action map for targets of given TYPE.
    973 This does not take into account the default action, help key or
    974 cycling bindings, just what's registered in
    975 `embark-keymap-alist'."
    976   (make-composed-keymap
    977    (mapcar #'symbol-value
    978            (let ((actions (or (alist-get type embark-keymap-alist)
    979                               (alist-get t embark-keymap-alist))))
    980              (ensure-list actions)))))
    981 
    982 (defun embark--action-keymap (type cycle)
    983   "Return action keymap for targets of given TYPE.
    984 If CYCLE is non-nil bind `embark-cycle'."
    985   (make-composed-keymap
    986    (let ((map (make-sparse-keymap))
    987          (default-action (embark--default-action type)))
    988      (define-key map [13] default-action)
    989      (when-let ((cycle-key (and cycle (embark--cycle-key))))
    990        (define-key map cycle-key #'embark-cycle))
    991      (when embark-help-key
    992        (keymap-set map embark-help-key #'embark-keymap-help))
    993      map)
    994    (embark--raw-action-keymap type)))
    995 
    996 (defun embark--truncate-target (target)
    997   "Truncate TARGET string."
    998   (unless (stringp target)
    999     (setq target (format "%s" target)))
   1000   (if-let (pos (string-match-p "\n" target))
   1001       (concat (car (split-string target "\n" 'omit-nulls "\\s-*")) "…")
   1002     target))
   1003 
   1004 ;;;###autoload
   1005 (defun embark-eldoc-first-target (report &rest _)
   1006   "Eldoc function reporting the first Embark target at point.
   1007 This function uses the eldoc REPORT callback and is meant to be
   1008 added to `eldoc-documentation-functions'."
   1009   (when-let (((not (minibufferp)))
   1010              (target (car (embark--targets))))
   1011     (funcall report
   1012              (format "Embark on %s ‘%s’"
   1013                      (plist-get target :type)
   1014                      (embark--truncate-target (plist-get target :target))))))
   1015 
   1016 ;;;###autoload
   1017 (defun embark-eldoc-target-types (report &rest _)
   1018   "Eldoc function reporting the types of all Embark targets at point.
   1019 This function uses the eldoc REPORT callback and is meant to be
   1020 added to `eldoc-documentation-functions'."
   1021   (when-let (((not (minibufferp)))
   1022              (targets (embark--targets)))
   1023     (funcall report
   1024              (format "Embark target types: %s"
   1025                      (mapconcat
   1026                       (lambda (target) (symbol-name (plist-get target :type)))
   1027                       targets
   1028                       ", ")))))
   1029 
   1030 (defun embark--format-targets (target shadowed-targets rep)
   1031   "Return a formatted string indicating the TARGET of an action.
   1032 
   1033 This is used internally by the minimal indicator and for the
   1034 targets section of the verbose indicator.  The string will also
   1035 mention any SHADOWED-TARGETS.  A non-nil REP indicates we are in
   1036 a repeating sequence of actions."
   1037   (let ((act (propertize
   1038               (cond
   1039                ((plist-get target :multi) "∀ct")
   1040                (rep "Rep")
   1041                (t "Act"))
   1042               'face 'highlight)))
   1043     (cond
   1044      ((eq (plist-get target :type) 'embark-become)
   1045       (propertize "Become" 'face 'highlight))
   1046      ((and (minibufferp)
   1047            (not (eq 'embark-keybinding
   1048                     (completion-metadata-get
   1049                      (embark--metadata)
   1050                      'category))))
   1051       ;; we are in a minibuffer but not from the
   1052       ;; completing-read prompter, use just "Act"
   1053       act)
   1054      ((plist-get target :multi)
   1055       (format "%s on %s %ss"
   1056               act
   1057               (plist-get target :multi)
   1058               (plist-get target :type)))
   1059      (t (format
   1060          "%s on %s%s ‘%s’"
   1061          act
   1062          (plist-get target :type)
   1063          (if shadowed-targets
   1064              (format (propertize "(%s)" 'face 'shadow)
   1065                      (mapconcat
   1066                       (lambda (target) (symbol-name (plist-get target :type)))
   1067                       shadowed-targets
   1068                       ", "))
   1069            "")
   1070          (embark--truncate-target (plist-get target :target)))))))
   1071 
   1072 (defun embark-minimal-indicator ()
   1073   "Minimal indicator, appearing in the minibuffer prompt or echo area.
   1074 This indicator displays a message showing the types of all
   1075 targets, starting with the current target, and the value of the
   1076 current target.  The message is displayed in the echo area, or if
   1077 the minibuffer is open, the message is added to the prompt."
   1078   (lambda (&optional keymap targets _prefix)
   1079     (if (null keymap)
   1080         (when embark--minimal-indicator-overlay
   1081           (delete-overlay embark--minimal-indicator-overlay)
   1082           (setq-local embark--minimal-indicator-overlay nil))
   1083       (let ((indicator (embark--format-targets
   1084                         (car targets) (cdr targets)
   1085                         (eq (lookup-key keymap [13]) #'embark-done))))
   1086         (if (not (minibufferp))
   1087             (message "%s" indicator)
   1088           (unless embark--minimal-indicator-overlay
   1089             (setq-local embark--minimal-indicator-overlay
   1090                         (make-overlay (point-min) (point-min)
   1091                                       (current-buffer) t t)))
   1092           (overlay-put embark--minimal-indicator-overlay
   1093                        'before-string (concat indicator
   1094                                               (if (<= (length indicator)
   1095                                                       (* 0.4 (frame-width)))
   1096                                                   " "
   1097                                                 "\n"))))))))
   1098 
   1099 (defun embark--read-key-sequence (update)
   1100   "Read key sequence, call UPDATE function with prefix keys."
   1101   (let (timer prefix)
   1102     (unwind-protect
   1103         (progn
   1104           (when (functionp update)
   1105             (setq timer (run-at-time
   1106                          0.05 0.05
   1107                          (lambda ()
   1108                            (let ((new-prefix (this-single-command-keys)))
   1109                              (unless (equal prefix new-prefix)
   1110                                (setq prefix new-prefix)
   1111                                (when (/= (length prefix) 0)
   1112                                  (funcall update prefix))))))))
   1113           (read-key-sequence-vector nil nil nil t 'cmd-loop))
   1114       (when timer
   1115         (cancel-timer timer)))))
   1116 
   1117 (defvar embark-indicators) ; forward declaration
   1118 
   1119 (defun embark-keymap-prompter (keymap update)
   1120   "Let the user choose an action using the bindings in KEYMAP.
   1121 Besides the bindings in KEYMAP, the user is free to use all their
   1122 key bindings and even \\[execute-extended-command] to select a command.
   1123 UPDATE is the indicator update function."
   1124   (let* ((keys (let ((overriding-terminal-local-map keymap))
   1125                  (embark--read-key-sequence update)))
   1126          (cmd (let ((overriding-terminal-local-map keymap))
   1127                 (key-binding keys 'accept-default))))
   1128     ;; Set last-command-event as it would be from the command loop.
   1129     ;; Previously we only set it locally for digit-argument and for
   1130     ;; the mouse scroll commands handled in this function. But other
   1131     ;; commands can need it too! For example, electric-pair-mode users
   1132     ;; may wish to bind ( to self-insert-command in embark-region-map.
   1133     ;; Also, as described in issue #402, there are circumstances where
   1134     ;; you might run consult-narrow through the embark-keymap-prompter.
   1135     (setq last-command-event (aref keys (1- (length keys))))
   1136     (pcase cmd
   1137       ((or 'embark-keymap-help
   1138            (and 'nil            ; cmd is nil but last key is help-char
   1139                 (guard (eq help-char (aref keys (1- (length keys)))))))
   1140        (let ((embark-indicators
   1141               (cl-set-difference embark-indicators
   1142                                  '(embark-verbose-indicator
   1143                                    embark-mixed-indicator)))
   1144              (prefix-map
   1145               (if (eq cmd 'embark-keymap-help)
   1146                   keymap
   1147                 (let ((overriding-terminal-local-map keymap))
   1148                   (key-binding (seq-take keys (1- (length keys)))
   1149                                'accept-default)))))
   1150          (when-let ((win (get-buffer-window embark--verbose-indicator-buffer
   1151                                             'visible)))
   1152            (quit-window 'kill-buffer win))
   1153          (embark-completing-read-prompter prefix-map update)))
   1154       ((or 'universal-argument 'universal-argument-more
   1155            'negative-argument 'digit-argument 'embark-toggle-quit)
   1156        ;; prevent `digit-argument' from modifying the overriding map
   1157        (let ((overriding-terminal-local-map overriding-terminal-local-map))
   1158          (command-execute cmd))
   1159        (embark-keymap-prompter
   1160         (make-composed-keymap universal-argument-map keymap)
   1161         update))
   1162       ((or 'minibuffer-keyboard-quit 'abort-recursive-edit 'abort-minibuffers)
   1163        nil)
   1164       ((guard (let ((def (lookup-key keymap keys))) ; if directly
   1165                                                     ; bound, then obey
   1166                 (and def (not (numberp def))))) ; number means "invalid prefix"
   1167        cmd)
   1168       ('self-insert-command
   1169        (minibuffer-message "Not an action")
   1170        (embark-keymap-prompter keymap update))
   1171       ((or 'scroll-other-window 'scroll-other-window-down)
   1172        (let ((minibuffer-scroll-window
   1173               ;; NOTE: Here we special case the verbose indicator!
   1174               (or (get-buffer-window embark--verbose-indicator-buffer 'visible)
   1175                   minibuffer-scroll-window)))
   1176          (ignore-errors (command-execute cmd)))
   1177        (embark-keymap-prompter keymap update))
   1178       ((or 'scroll-bar-toolkit-scroll 'mwheel-scroll 'mac-mwheel-scroll)
   1179        (funcall cmd last-command-event)
   1180        (embark-keymap-prompter keymap update))
   1181       ('execute-extended-command
   1182        (intern-soft (read-extended-command)))
   1183       ((or 'keyboard-quit 'keyboard-escape-quit)
   1184        nil)
   1185       (_ cmd))))
   1186 
   1187 (defun embark--command-name (cmd)
   1188   "Return an appropriate name for CMD.
   1189 If CMD is a symbol, use its symbol name; for lambdas, use the
   1190 first line of the documentation string; otherwise use the word
   1191 \"unnamed\"."
   1192   (concat ; fresh copy, so we can freely add text properties
   1193    (cond
   1194     ((stringp (car-safe cmd)) (car cmd))
   1195     ((eq (car-safe cmd) 'menu-item) (cadr cmd))
   1196     ((keymapp cmd)
   1197      (propertize (if (symbolp cmd) (format "+%s" cmd) "<keymap>")
   1198                  'face 'embark-keymap))
   1199     ((symbolp cmd)
   1200      (let ((name (symbol-name cmd)))
   1201        (if (string-prefix-p "embark-action--" name) ; direct action mode
   1202            (format "(%s)" (string-remove-prefix "embark-action--" name))
   1203          name)))
   1204     ((when-let (doc (and (functionp cmd) (ignore-errors (documentation cmd))))
   1205        (save-match-data
   1206          (when (string-match "^\\(.*\\)$" doc)
   1207            (match-string 1 doc)))))
   1208     (t "<unnamed>"))))
   1209 
   1210 ;; Taken from Marginalia, needed by the verbose indicator.
   1211 ;; We cannot use the completion annotators in this case.
   1212 (defconst embark--advice-regexp
   1213   (rx bos
   1214       (1+ (seq (? "This function has ")
   1215                (or ":before" ":after" ":around" ":override"
   1216                    ":before-while" ":before-until" ":after-while"
   1217                    ":after-until" ":filter-args" ":filter-return")
   1218                " advice: " (0+ nonl) "\n"))
   1219       "\n")
   1220   "Regexp to match lines about advice in function documentation strings.")
   1221 
   1222 ;; Taken from Marginalia, needed by the verbose indicator.
   1223 ;; We cannot use the completion annotators in this case.
   1224 (defun embark--function-doc (sym)
   1225   "Documentation string of function SYM."
   1226   (let ((vstr (and (symbolp sym) (keymapp sym) (boundp sym)
   1227                    (eq (symbol-function sym) (symbol-value sym))
   1228                    (documentation-property sym 'variable-documentation))))
   1229     (when-let (str (or (ignore-errors (documentation sym)) vstr))
   1230       ;; Replace standard description with variable documentation
   1231       (when (and vstr (string-match-p "\\`Prefix command" str))
   1232         (setq str vstr))
   1233       (save-match-data
   1234         (if (string-match embark--advice-regexp str)
   1235             (substring str (match-end 0))
   1236           str)))))
   1237 
   1238 (defun embark--action-repeatable-p (action)
   1239   "Is ACTION repeatable?
   1240 When the return value is non-nil it will be the desired starting
   1241 point of the next target cycle or t to indicate the default,
   1242 namely that the target cycle for the next action should begin at
   1243 the type of the current target."
   1244   (or (cdr (assq action embark-repeat-actions))
   1245       (and (memq action embark-repeat-actions) t)))
   1246 
   1247 (defun embark--formatted-bindings (keymap &optional nested)
   1248   "Return the formatted keybinding of KEYMAP.
   1249 The keybindings are returned in their order of appearance.
   1250 If NESTED is non-nil subkeymaps are not flattened."
   1251   (let* ((commands
   1252           (cl-loop for (key . def) in (embark--all-bindings keymap nested)
   1253                    for name = (embark--command-name def)
   1254                    for cmd = (keymap--menu-item-binding def)
   1255                    unless (memq cmd '(nil embark-keymap-help
   1256                                       negative-argument digit-argument))
   1257                    collect (list name cmd key
   1258                                  (concat
   1259                                   (if (eq (car-safe def) 'menu-item)
   1260                                       "menu-item"
   1261                                     (key-description key))))))
   1262          (width (cl-loop for (_name _cmd _key desc) in commands
   1263                          maximize (length desc)))
   1264          (default)
   1265          (candidates
   1266           (cl-loop for item in commands
   1267                    for (name cmd key desc) = item
   1268                    for desc-rep =
   1269                    (concat
   1270                     (propertize desc 'face 'embark-keybinding)
   1271                     (and (embark--action-repeatable-p cmd)
   1272                          embark-keybinding-repeat))
   1273                    for formatted =
   1274                    (propertize
   1275                     (concat desc-rep
   1276                             (make-string (- width (length desc-rep) -1) ?\s)
   1277                             name)
   1278                     'embark-command cmd)
   1279                    when (equal key [13])
   1280                    do (setq default formatted)
   1281                    collect (cons formatted item))))
   1282     (cons candidates default)))
   1283 
   1284 (defun embark--with-category (category candidates)
   1285   "Return completion table for CANDIDATES of CATEGORY with sorting disabled."
   1286   (lambda (string predicate action)
   1287     (if (eq action 'metadata)
   1288         `(metadata (display-sort-function . identity)
   1289                    (cycle-sort-function . identity)
   1290                    (category . ,category))
   1291       (complete-with-action
   1292        action candidates string predicate))))
   1293 
   1294 (defun embark-completing-read-prompter (keymap update &optional no-default)
   1295   "Prompt via completion for a command bound in KEYMAP.
   1296 If NO-DEFAULT is t, no default value is passed to`completing-read'.
   1297 
   1298 UPDATE is the indicator update function.  It is not used directly
   1299 here, but if the user switches to `embark-keymap-prompter', the
   1300 UPDATE function is passed to it."
   1301   (let* ((candidates+def (embark--formatted-bindings keymap))
   1302          (candidates (car candidates+def))
   1303          (def (and (not no-default) (cdr candidates+def)))
   1304          (buf (current-buffer))
   1305          (choice
   1306           (catch 'choice
   1307             (minibuffer-with-setup-hook
   1308                 (lambda ()
   1309                   (let ((map (make-sparse-keymap)))
   1310                     (define-key map "\M-q"
   1311                                 (lambda ()
   1312                                   (interactive)
   1313                                   (with-current-buffer buf
   1314                                     (embark-toggle-quit))))
   1315                     (when-let (cycle (embark--cycle-key))
   1316                       ;; Rebind `embark-cycle' in order allow cycling
   1317                       ;; from the `completing-read' prompter. Additionally
   1318                       ;; `embark-cycle' can be selected via
   1319                       ;; `completing-read'. The downside is that this breaks
   1320                       ;; recursively acting on the candidates of type
   1321                       ;; embark-keybinding in the `completing-read' prompter.
   1322                       (define-key map cycle
   1323                         (cond
   1324                          ((eq (lookup-key keymap cycle) 'embark-cycle)
   1325                           (lambda ()
   1326                             (interactive)
   1327                             (throw 'choice 'embark-cycle)))
   1328                          ((null embark-cycle-key)
   1329                           (lambda ()
   1330                             (interactive)
   1331                             (minibuffer-message
   1332                              "No cycling possible; press `%s' again to act."
   1333                              (key-description cycle))
   1334                             (define-key map cycle #'embark-act))))))
   1335                     (when embark-keymap-prompter-key
   1336                       (keymap-set map embark-keymap-prompter-key
   1337                         (lambda ()
   1338                           (interactive)
   1339                           (message "Press key binding")
   1340                           (let ((cmd (embark-keymap-prompter keymap update)))
   1341                             (if (null cmd)
   1342                                 (user-error "Unknown key")
   1343                               (throw 'choice cmd))))))
   1344                     (use-local-map
   1345                      (make-composed-keymap map (current-local-map)))))
   1346               (completing-read
   1347                "Command: "
   1348                (embark--with-category 'embark-keybinding candidates)
   1349                nil nil nil 'embark--prompter-history def)))))
   1350     (pcase (assoc choice candidates)
   1351       (`(,_formatted ,_name ,cmd ,key ,_desc)
   1352        ;; Set last-command-event as it would be from the command loop.
   1353        (setq last-command-event (aref key (1- (length key))))
   1354        cmd)
   1355       ('nil (intern-soft choice)))))
   1356 
   1357 ;;; Verbose action indicator
   1358 
   1359 (defgroup embark-indicators nil
   1360   "Indicators display information about actions and targets."
   1361   :group 'embark)
   1362 
   1363 (defcustom embark-indicators
   1364   '(embark-mixed-indicator
   1365     embark-highlight-indicator
   1366     embark-isearch-highlight-indicator)
   1367   "Indicator functions to use when acting or becoming.
   1368 The indicator functions are called from both `embark-act' and
   1369 from `embark-become' and should display information about this to
   1370 the user, such as: which of those two commands is running; a
   1371 description of the key bindings that are available for actions or
   1372 commands to become; and, in the case of `embark-act', the type
   1373 and value of the targets, and whether other targets are available
   1374 via `embark-cycle'.  The indicator function is free to display as
   1375 much or as little of this information as desired and can use any
   1376 Emacs interface elements to do so.
   1377 
   1378 Embark comes with five such indicators:
   1379 
   1380 - `embark-minimal-indicator', which does not display any
   1381   information about keybindings, but does display types and
   1382   values of action targets in the echo area or minibuffer prompt,
   1383 
   1384 - `embark-verbose-indicator', which pops up a buffer containing
   1385   detailed information including key bindings and the first line
   1386   of the docstring of the commands they run, and
   1387 
   1388 - `embark-mixed-indicator', which combines the minimal and the
   1389   verbose indicator: the minimal indicator is shown first and the
   1390   verbose popup is shown after `embark-mixed-indicator-delay'
   1391   seconds.
   1392 
   1393 - `embark-highlight-indicator', which highlights the target
   1394   at point.
   1395 
   1396 - `embark-isearch-highlight-indicator', which when the target at
   1397   point is an identifier or symbol, lazily highlights all
   1398   occurrences of it.
   1399 
   1400 The protocol for indicator functions is as follows:
   1401 
   1402 When called from `embark-act', an indicator function is called
   1403 without arguments.  The indicator function should then return a
   1404 closure, which captures the indicator state.  The returned
   1405 closure must accept up to three optional arguments, the action
   1406 keymap, the targets (plists as returned by `embark--targets') and
   1407 the prefix keys typed by the user so far.  The keymap, targets
   1408 and prefix keys may be updated when cycling targets at point
   1409 resulting in multiple calls to the closure.  When called from
   1410 `embark-become', the indicator closure will be called with the
   1411 keymap of commands to become, a fake target list containing a
   1412 single target of type `embark-become' and whose value is the
   1413 minibuffer input, and the prefix set to nil.  Note, in
   1414 particular, that if an indicator function wishes to distinguish
   1415 between `embark-act' and `embark-become' it should check whether
   1416 the `car' of the first target is `embark-become'.
   1417 
   1418 After the action has been performed the indicator closure is
   1419 called without arguments, such that the indicator can perform the
   1420 necessary cleanup work.  For example, if the indicator adds
   1421 overlays, it should remove these overlays.  The indicator should
   1422 be written in a way that it is safe to call it for cleanup more
   1423 than once, in fact, it should be able to handle any sequence of
   1424 update and cleanup calls ending in a call for cleanup.
   1425 
   1426 NOTE: Experience shows that the indicator calling convention may
   1427 change again in order to support more action features.  The
   1428 calling convention should currently be considered unstable.
   1429 Please keep this in mind when writing a custom indicator
   1430 function, or when using the `which-key' indicator function from
   1431 the wiki."
   1432   :type '(repeat
   1433           (choice
   1434            (const :tag "Verbose indicator" embark-verbose-indicator)
   1435            (const :tag "Minimal indicator" embark-minimal-indicator)
   1436            (const :tag "Mixed indicator" embark-mixed-indicator)
   1437            (const :tag "Highlight target" embark-highlight-indicator)
   1438            (const :tag "Highlight all occurrences"
   1439                   embark-isearch-highlight-indicator)
   1440            (function :tag "Other"))))
   1441 
   1442 (defface embark-verbose-indicator-documentation
   1443   '((t :inherit completions-annotations))
   1444   "Face used by the verbose action indicator to display binding descriptions.
   1445 Used by `embark-verbose-indicator'.")
   1446 
   1447 (defface embark-verbose-indicator-title '((t :height 1.1 :weight bold))
   1448   "Face used by the verbose action indicator for the title.
   1449 Used by `embark-verbose-indicator'.")
   1450 
   1451 (defface embark-verbose-indicator-shadowed '((t :inherit shadow))
   1452   "Face used by the verbose action indicator for the shadowed targets.
   1453 Used by `embark-verbose-indicator'.")
   1454 
   1455 (defcustom embark-verbose-indicator-display-action
   1456   '(display-buffer-reuse-window)
   1457   "Parameters added to `display-buffer-alist' to show the actions buffer.
   1458 See the docstring of `display-buffer' for information on what
   1459 display actions and parameters are available."
   1460   :type `(choice
   1461           (const :tag "Reuse some window"
   1462                  (display-buffer-reuse-window))
   1463           (const :tag "Below target buffer"
   1464                  (display-buffer-below-selected
   1465                   (window-height . fit-window-to-buffer)))
   1466           (const :tag "Bottom of frame (fixed-size)"
   1467                  (display-buffer-at-bottom))
   1468           (const :tag "Bottom of frame (resizes during cycling)"
   1469                  (display-buffer-at-bottom
   1470                   (window-height . fit-window-to-buffer)))
   1471           (const :tag "Side window on the right"
   1472                  (display-buffer-in-side-window (side . right)))
   1473           (const :tag "Side window on the left"
   1474                  (display-buffer-in-side-window (side . left)))
   1475           (sexp :tag "Other")))
   1476 
   1477 (defcustom embark-verbose-indicator-excluded-actions nil
   1478   "Commands not displayed by `embark-verbose-indicator'.
   1479 This variable should be set to a list of symbols and regexps.
   1480 The verbose indicator will exclude from its listing any commands
   1481 matching an element of this list."
   1482   :type '(choice
   1483           (const :tag "Exclude nothing" nil)
   1484           (const :tag "Exclude Embark general actions"
   1485                  (embark-collect embark-live embark-export
   1486                   embark-cycle embark-act-all embark-keymap-help
   1487                   embark-become embark-isearch))
   1488           (repeat :tag "Other" (choice regexp symbol))))
   1489 
   1490 (defcustom embark-verbose-indicator-buffer-sections
   1491   `(target "\n" shadowed-targets " " cycle "\n" bindings)
   1492   "List of sections to display in the verbose indicator buffer, in order.
   1493 You can use either a symbol designating a concrete section (one
   1494 of the keywords below, but without the colon), a string literal
   1495 or a function returning a string or list of strings to insert and
   1496 that accepts the following keyword arguments:
   1497 
   1498 - `:target', the target as a cons of type and value,
   1499 - `:shadowed-targets', a list of conses for the other targets,
   1500 - `:bindings' a list returned by `embark--formatted-bindings', and
   1501 - `:cycle', a string describing the key binding of `embark-cycle'."
   1502   :type '(repeat
   1503           (choice (const :tag "Current target name" target)
   1504                   (const :tag "List of other shadowed targets" shadowed-targets)
   1505                   (const :tag "Key bindings" bindings)
   1506                   (const :tag "Cycle indicator" cycle)
   1507                   (string :tag "Literal string")
   1508                   (function :tag "Custom function"))))
   1509 
   1510 (defcustom embark-verbose-indicator-nested t
   1511   "Whether the verbose indicator should use nested keymap navigation.
   1512 When this variable is non-nil the actions buffer displayed by
   1513 `embark-verbose-indicator' will include any prefix keys found in
   1514 the keymap it is displaying, and will update to show what is
   1515 bound under the prefix if the prefix is pressed.  If this
   1516 variable is nil, then the actions buffer will contain a flat list
   1517 of all full key sequences bound in the keymap."
   1518   :type 'boolean)
   1519 
   1520 (defun embark--verbose-indicator-excluded-p (cmd)
   1521   "Return non-nil if CMD should be excluded from the verbose indicator."
   1522   (seq-find (lambda (x)
   1523               (if (symbolp x)
   1524                   (eq cmd x)
   1525                 (string-match-p x (symbol-name cmd))))
   1526             embark-verbose-indicator-excluded-actions))
   1527 
   1528 (cl-defun embark--verbose-indicator-section-target
   1529     (&key targets bindings &allow-other-keys)
   1530   "Format the TARGETS section for the indicator buffer.
   1531 BINDINGS is the formatted list of keybindings."
   1532   (let ((result (embark--format-targets
   1533                  (car targets)
   1534                  nil   ; the shadowed targets section deals with these
   1535                  (cl-find 'embark-done bindings :key #'caddr :test #'eq))))
   1536     (add-face-text-property 0 (length result)
   1537                             'embark-verbose-indicator-title
   1538                             'append
   1539                             result)
   1540     result))
   1541 
   1542 (cl-defun embark--verbose-indicator-section-cycle
   1543     (&key cycle shadowed-targets &allow-other-keys)
   1544   "Format the CYCLE key section for the indicator buffer.
   1545 SHADOWED-TARGETS is the list of other targets."
   1546   (concat
   1547    (and cycle (propertize (format "(%s to cycle)" cycle)
   1548                           'face 'embark-verbose-indicator-shadowed))
   1549    (and shadowed-targets "\n")))
   1550 
   1551 (cl-defun embark--verbose-indicator-section-shadowed-targets
   1552     (&key shadowed-targets &allow-other-keys)
   1553   "Format the SHADOWED-TARGETS section for the indicator buffer."
   1554   (when shadowed-targets
   1555     (propertize (format "Shadowed targets at point: %s"
   1556                         (string-join shadowed-targets ", "))
   1557                 'face 'embark-verbose-indicator-shadowed)))
   1558 
   1559 (cl-defun embark--verbose-indicator-section-bindings
   1560     (&key bindings &allow-other-keys)
   1561   "Format the BINDINGS section for the indicator buffer."
   1562   (let* ((max-width (apply #'max (cons 0 (mapcar (lambda (x)
   1563                                                   (string-width (car x)))
   1564                                                 bindings))))
   1565          (fmt (format "%%-%ds" (1+ max-width)))
   1566          (result nil))
   1567     (dolist (binding bindings (string-join (nreverse result)))
   1568       (let ((cmd (caddr binding)))
   1569         (unless (embark--verbose-indicator-excluded-p cmd)
   1570           (let ((keys (format fmt (car binding)))
   1571                 (doc (embark--function-doc cmd)))
   1572             (push (format "%s%s\n" keys
   1573                           (propertize
   1574                            (car (split-string (or doc "") "\n"))
   1575                            'face 'embark-verbose-indicator-documentation))
   1576                           result)))))))
   1577 
   1578 (defun embark--verbose-indicator-update (keymap targets)
   1579   "Update verbose indicator buffer.
   1580 The arguments are the new KEYMAP and TARGETS."
   1581   (with-current-buffer (get-buffer-create embark--verbose-indicator-buffer)
   1582     (let* ((inhibit-read-only t)
   1583            (bindings
   1584             (embark--formatted-bindings keymap embark-verbose-indicator-nested))
   1585            (bindings (car bindings))
   1586            (shadowed-targets (mapcar
   1587                               (lambda (x) (symbol-name (plist-get x :type)))
   1588                               (cdr targets)))
   1589            (cycle (let ((ck (where-is-internal #'embark-cycle keymap)))
   1590                     (and ck (key-description (car ck))))))
   1591       (setq-local cursor-type nil)
   1592       (setq-local truncate-lines t)
   1593       (setq-local buffer-read-only t)
   1594       (erase-buffer)
   1595       (dolist (section embark-verbose-indicator-buffer-sections)
   1596         (insert
   1597          (if (stringp section)
   1598              section
   1599            (or (funcall
   1600                 (let ((prefixed (intern (format
   1601                                          "embark--verbose-indicator-section-%s"
   1602                                          section))))
   1603                   (cond
   1604                    ((fboundp prefixed) prefixed)
   1605                    ((fboundp section) section)
   1606                    (t (error "Undefined verbose indicator section `%s'"
   1607                              section))))
   1608                 :targets targets :shadowed-targets shadowed-targets
   1609                 :bindings bindings :cycle cycle)
   1610                ""))))
   1611       (goto-char (point-min)))))
   1612 
   1613 (defun embark-verbose-indicator ()
   1614   "Indicator that displays a table of key bindings in a buffer.
   1615 The default display includes the type and value of the current
   1616 target, the list of other target types, and a table of key
   1617 bindings, actions and the first line of their docstrings.
   1618 
   1619 The order and formatting of these items is completely
   1620 configurable through the variable
   1621 `embark-verbose-indicator-buffer-sections'.
   1622 
   1623 If the keymap being shown contains prefix keys, the table of key
   1624 bindings can either show just the prefixes and update once the
   1625 prefix is pressed, or it can contain a flat list of all full key
   1626 sequences bound in the keymap.  This is controlled by the
   1627 variable `embark-verbose-indicator-nested'.
   1628 
   1629 To reduce clutter in the key binding table, one can set the
   1630 variable `embark-verbose-indicator-excluded-actions' to a list
   1631 of symbols and regexps matching commands to exclude from the
   1632 table.
   1633 
   1634 To configure how a window is chosen to display this buffer, see
   1635 the variable `embark-verbose-indicator-display-action'."
   1636   (lambda (&optional keymap targets prefix)
   1637     (if (not keymap)
   1638         (when-let ((win (get-buffer-window embark--verbose-indicator-buffer
   1639                                            'visible)))
   1640           (quit-window 'kill-buffer win))
   1641       (embark--verbose-indicator-update
   1642        (if (and prefix embark-verbose-indicator-nested)
   1643            ;; Lookup prefix keymap globally if not found in action keymap
   1644            (let ((overriding-terminal-local-map keymap))
   1645              (key-binding prefix 'accept-default))
   1646          keymap)
   1647        targets)
   1648       (let ((display-buffer-alist
   1649              `(,@display-buffer-alist
   1650                (,(regexp-quote embark--verbose-indicator-buffer)
   1651                 ,@embark-verbose-indicator-display-action))))
   1652         (display-buffer embark--verbose-indicator-buffer)))))
   1653 
   1654 (defcustom embark-mixed-indicator-delay 0.5
   1655   "Time in seconds after which the verbose indicator is shown.
   1656 The mixed indicator starts by showing the minimal indicator and
   1657 after this delay shows the verbose indicator."
   1658   :type '(choice (const :tag "No delay" 0)
   1659                  (number :tag "Delay in seconds")))
   1660 
   1661 (defcustom embark-mixed-indicator-both nil
   1662   "Show both indicators, even after the verbose indicator appeared."
   1663   :type 'boolean)
   1664 
   1665 (defun embark-mixed-indicator ()
   1666   "Mixed indicator showing keymap and targets.
   1667 The indicator shows the `embark-minimal-indicator' by default.
   1668 After `embark-mixed-indicator-delay' seconds, the
   1669 `embark-verbose-indicator' is shown.  This which-key-like approach
   1670 ensures that Embark stays out of the way for quick actions.  The
   1671 helpful keybinding reminder still pops up automatically without
   1672 further user intervention."
   1673   (let ((vindicator (embark-verbose-indicator))
   1674         (mindicator (embark-minimal-indicator))
   1675         vindicator-active
   1676         vtimer)
   1677     (lambda (&optional keymap targets prefix)
   1678       ;; Always cancel the timer.
   1679       ;; 1. When updating, cancel timer, since the user has pressed
   1680       ;;    a key before the timer elapsed.
   1681       ;; 2. For cleanup, the timer must also be canceled.
   1682       (when vtimer
   1683         (cancel-timer vtimer)
   1684         (setq vtimer nil))
   1685       (if (not keymap)
   1686           (progn
   1687             (funcall vindicator)
   1688             (when mindicator
   1689               (funcall mindicator)))
   1690         (when mindicator
   1691           (funcall mindicator keymap targets prefix))
   1692         (if vindicator-active
   1693             (funcall vindicator keymap targets prefix)
   1694           (setq vtimer
   1695                 (run-at-time
   1696                  embark-mixed-indicator-delay nil
   1697                  (lambda ()
   1698                    (when (and (not embark-mixed-indicator-both) mindicator)
   1699                      (funcall mindicator)
   1700                      (setq mindicator nil))
   1701                    (setq vindicator-active t)
   1702                    (funcall vindicator keymap targets prefix)))))))))
   1703 
   1704 ;;;###autoload
   1705 (defun embark-bindings-in-keymap (keymap)
   1706   "Explore command key bindings in KEYMAP with `completing-read'.
   1707 The selected command will be executed.  Interactively, prompt the
   1708 user for a KEYMAP variable."
   1709   (interactive
   1710    (list
   1711     (symbol-value
   1712      (intern-soft
   1713       (completing-read
   1714        "Keymap: "
   1715        (embark--with-category
   1716         'variable
   1717         (cl-loop for x being the symbols
   1718                  if (and (boundp x) (keymapp (symbol-value x)))
   1719                  collect (symbol-name x)))
   1720        nil t nil 'variable-name-history
   1721        (let ((major-mode-map
   1722               (concat (symbol-name major-mode) "-map")))
   1723          (when (intern-soft major-mode-map) major-mode-map)))))))
   1724   (when-let (command (embark-completing-read-prompter keymap nil 'no-default))
   1725     (call-interactively command)))
   1726 
   1727 ;;;###autoload
   1728 (defun embark-bindings (no-global)
   1729   "Explore all current command key bindings with `completing-read'.
   1730 The selected command will be executed.
   1731 
   1732 If NO-GLOBAL is non-nil (interactively, if called with a prefix
   1733 argument) omit global key bindings; this leaves key bindings from
   1734 minor mode maps and the local map (usually set by the major
   1735 mode), but also less common keymaps such as those from a text
   1736 property or overlay, or the overriding maps:
   1737 `overriding-terminal-local-map' and `overriding-local-map'."
   1738   (interactive "P")
   1739   (embark-bindings-in-keymap
   1740    (make-composed-keymap
   1741     (let ((all-maps (current-active-maps t)))
   1742       (if no-global (remq global-map all-maps) all-maps)))))
   1743 
   1744 ;;;###autoload
   1745 (defun embark-bindings-at-point ()
   1746   "Explore all key bindings at point with `completing-read'.
   1747 The selected command will be executed.
   1748 
   1749 This command lists key bindings found in keymaps specified by the
   1750 text properties `keymap' or `local-map', from either buffer text
   1751 or an overlay.  These are not widely used in Emacs, and when they
   1752 are used can be somewhat hard to discover.  Examples of locations
   1753 that have such a keymap are links and images in `eww' buffers,
   1754 attachment links in `gnus' article buffers, and the 'Stash' line
   1755 in a `vc-dir' buffer."
   1756   (interactive)
   1757   (let ((keymaps (delq nil (list (get-char-property (point) 'keymap)
   1758                                  (get-char-property (point) 'local-map)))))
   1759     (unless keymaps
   1760       (user-error "No key bindings found at point"))
   1761     (embark-bindings-in-keymap (make-composed-keymap keymaps))))
   1762 
   1763 ;;;###autoload
   1764 (defun embark-prefix-help-command ()
   1765   "Prompt for and run a command bound in the prefix used for this command.
   1766 The prefix described consists of all but the last event of the
   1767 key sequence that ran this command.  This function is intended to
   1768 be used as a value for `prefix-help-command'.
   1769 
   1770 In addition to using completion to select a command, you can also
   1771 type @ and the key binding (without the prefix)."
   1772   (interactive)
   1773   (when-let ((keys (this-command-keys-vector))
   1774              (prefix (seq-take keys (1- (length keys))))
   1775              (keymap (key-binding prefix 'accept-default)))
   1776     (embark-bindings-in-keymap keymap)))
   1777 
   1778 (defun embark--prompt (indicators keymap targets)
   1779   "Call the prompter with KEYMAP and INDICATORS.
   1780 The TARGETS are displayed for actions outside the minibuffer."
   1781   (mapc (lambda (i) (funcall i keymap targets)) indicators)
   1782   (condition-case nil
   1783       (minibuffer-with-setup-hook
   1784           (lambda ()
   1785             ;; if the prompter opens its own minibuffer, show
   1786             ;; the indicator there too
   1787             (let ((inner-indicators (mapcar #'funcall embark-indicators)))
   1788               (mapc (lambda (i) (funcall i keymap targets)) inner-indicators)
   1789               (add-hook 'minibuffer-exit-hook
   1790                         (lambda () (mapc #'funcall inner-indicators))
   1791                         nil t)))
   1792         (let ((enable-recursive-minibuffers t))
   1793           (funcall embark-prompter keymap
   1794                    (lambda (prefix)
   1795                      (mapc (lambda (i) (funcall i keymap targets prefix))
   1796                            indicators)))))
   1797     (quit nil)))
   1798 
   1799 (defvar embark--run-after-command-functions nil
   1800   "Abnormal hook, used by `embark--run-after-command'.")
   1801 
   1802 (defun embark--run-after-command (fn &rest args)
   1803   "Call FN with ARGS after the current commands finishes.
   1804 If multiple functions are queued with this function during the
   1805 same command, they will be called in the order from the one
   1806 queued most recently to the one queued least recently."
   1807   ;; We don't simply add FN to `post-command-hook' because FN may recursively
   1808   ;; call this function.  In that case, FN would modify `post-command-hook'
   1809   ;; from within post-command-hook, which doesn't behave properly in our case.
   1810   ;; We use our own abnormal hook and run it from PCH in a way that it is OK to
   1811   ;; modify it from within its own functions.
   1812   (unless embark--run-after-command-functions
   1813     (let (pch timer has-run)
   1814       (setq pch
   1815             (lambda ()
   1816               (remove-hook 'post-command-hook pch)
   1817               (cancel-timer timer)
   1818               (unless has-run
   1819                 (setq has-run t)
   1820                 (while embark--run-after-command-functions
   1821                   ;; The following funcall may recursively call
   1822                   ;; `embark--run-after-command', modifying
   1823                   ;; `embark--run-after-command-functions'.  This is why this
   1824                   ;; loop has to be implemented carefully.  We have to pop the
   1825                   ;; function off the hook before calling it.  Using `dolist'
   1826                   ;; on the hook would also be incorrect, because it wouldn't
   1827                   ;; take modifications of this hook into account.
   1828                   (with-demoted-errors "embark PCH: %S"
   1829                     (condition-case nil
   1830                         (funcall (pop embark--run-after-command-functions))
   1831                       (quit (message "Quit"))))))))
   1832       (add-hook 'post-command-hook pch 'append)
   1833       ;; Generally we prefer `post-command-hook' because it plays well with
   1834       ;; keyboard macros.  In some cases, `post-command-hook' isn't run after
   1835       ;; exiting a recursive edit, so set up the following timer as a backup.
   1836       (setq timer (run-at-time 0 nil pch))))
   1837 
   1838   ;; Keep the default-directory alive, since this is often overwritten,
   1839   ;; for example by Consult commands.
   1840   ;; TODO it might be necessary to add more dynamically bound variables
   1841   ;; here. What we actually want are functions `capture-dynamic-scope'
   1842   ;; and `eval-in-dynamic-scope', but this does not exist?
   1843   (let ((dir default-directory))
   1844     (push (lambda ()
   1845             (let ((default-directory dir))
   1846               (apply fn args)))
   1847           embark--run-after-command-functions)))
   1848 
   1849 (defun embark--quit-and-run (fn &rest args)
   1850   "Quit the minibuffer and then call FN with ARGS.
   1851 If called outside the minibuffer, simply apply FN to ARGS."
   1852   (if (not (minibufferp))
   1853       (apply fn args)
   1854     (apply #'embark--run-after-command fn args)
   1855     (embark--run-after-command #'set 'ring-bell-function ring-bell-function)
   1856     (setq ring-bell-function #'ignore)
   1857     (if (fboundp 'minibuffer-quit-recursive-edit)
   1858         (minibuffer-quit-recursive-edit)
   1859       (abort-recursive-edit))))
   1860 
   1861 (defun embark--run-action-hooks (hooks action target quit)
   1862   "Run HOOKS for ACTION.
   1863 The HOOKS argument must be alist.  The keys t and :always are
   1864 treated specially.  The :always hooks are executed always and the
   1865 t hooks are the default hooks, for when there are no
   1866 command-specific hooks for ACTION.  The QUIT, ACTION and TARGET
   1867 arguments are passed to the hooks as keyword arguments."
   1868   (mapc (lambda (h) (apply h :action action :quit quit target))
   1869         (or (alist-get action hooks)
   1870             (alist-get t hooks)))
   1871   (mapc (lambda (h) (apply h :action action :quit quit target))
   1872         (alist-get :always hooks)))
   1873 
   1874 (defun embark--run-around-action-hooks (action target quit)
   1875   "Run the `embark-around-action-hooks' for ACTION.
   1876 All the applicable around hooks are composed in the order they
   1877 are present in `embark-around-action-hooks'.  The keys t and
   1878 :always in `embark-around-action-hooks' are treated specially.
   1879 The :always hooks are executed always (outermost) and the t hooks
   1880 are the default hooks, for when there are no command-specific
   1881 hooks for ACTION.  The QUIT, ACTION and TARGET arguments are
   1882 passed to the hooks as keyword arguments."
   1883   (apply
   1884    (seq-reduce
   1885     (lambda (fn hook)
   1886       (lambda (&rest args) (apply hook (plist-put args :run fn))))
   1887     (let ((hooks embark-around-action-hooks))
   1888       (reverse
   1889        (append (or (alist-get action hooks) (alist-get t hooks))
   1890                (alist-get :always hooks))))
   1891     (lambda (&rest args)
   1892       (command-execute (plist-get args :action))))
   1893    :action action :quit quit target))
   1894 
   1895 (defun embark--act (action target &optional quit)
   1896   "Perform ACTION injecting the TARGET.
   1897 If called from a minibuffer with non-nil QUIT, quit the
   1898 minibuffer before executing the action."
   1899   (if (memq action '(embark-become       ; these actions should run in
   1900                      embark-collect      ; the current buffer, not the
   1901                      embark-live         ; target buffer
   1902                      embark-export
   1903                      embark-select
   1904                      embark-act-all))
   1905       (progn
   1906         (embark--run-action-hooks embark-pre-action-hooks action target quit)
   1907         (unwind-protect (embark--run-around-action-hooks action target quit)
   1908           (embark--run-action-hooks embark-post-action-hooks
   1909                                     action target quit)))
   1910     (let* ((command embark--command)
   1911            (prefix prefix-arg)
   1912            (action-window (embark--target-window t))
   1913            (directory default-directory)
   1914            (inject
   1915             (lambda ()
   1916               (let ((contents (minibuffer-contents)))
   1917                 (delete-minibuffer-contents)
   1918                 (insert
   1919                  (propertize
   1920                   (substring-no-properties (plist-get target :target))
   1921                   'embark--initial-input contents)))
   1922               (if (memq 'ivy--queue-exhibit post-command-hook)
   1923                   ;; Ivy has special needs: (1) for file names
   1924                   ;; ivy-immediate-done is not equivalent to
   1925                   ;; exit-minibuffer, (2) it needs a chance to run
   1926                   ;; its post command hook first, so use depth 10
   1927                   (add-hook 'post-command-hook 'ivy-immediate-done 10 t)
   1928                 (add-hook 'post-command-hook #'exit-minibuffer nil t))
   1929               (embark--run-action-hooks embark-target-injection-hooks
   1930                                         action target quit)))
   1931            (dedicate (and (derived-mode-p 'embark-collect-mode)
   1932                           (not (window-dedicated-p))
   1933                           (selected-window)))
   1934            (multi (memq action embark-multitarget-actions))
   1935            (run-action
   1936             (if (and (commandp action) (not multi))
   1937                 (lambda ()
   1938                   (let (final-window)
   1939                     (when dedicate (set-window-dedicated-p dedicate t))
   1940                     (unwind-protect
   1941                         (with-selected-window action-window
   1942                           (let ((enable-recursive-minibuffers t)
   1943                                 (embark--command command)
   1944                                 (prefix-arg prefix)
   1945                                 ;; the next two avoid mouse dialogs
   1946                                 (use-dialog-box nil)
   1947                                 (last-nonmenu-event 13)
   1948                                 (default-directory directory))
   1949                             (embark--run-action-hooks embark-pre-action-hooks
   1950                                                       action target quit)
   1951                             (minibuffer-with-setup-hook inject
   1952                               ;; pacify commands that use (this-command-keys)
   1953                               (when (= (length (this-command-keys)) 0)
   1954                                 (set--this-command-keys
   1955                                  (if (characterp last-command-event)
   1956                                      (string last-command-event)
   1957                                   "\r")))
   1958                               (setq this-command action)
   1959                               (embark--run-around-action-hooks
   1960                                action target quit)))
   1961                           (setq final-window (selected-window)))
   1962                       (embark--run-action-hooks embark-post-action-hooks
   1963                                                 action target quit)
   1964                       (when dedicate (set-window-dedicated-p dedicate nil)))
   1965                     (unless (eq final-window action-window)
   1966                       (select-window final-window))))
   1967               ;; TODO uniformize the command and non-interactive cases?
   1968               (let ((argument
   1969                      (if multi
   1970                          (or (plist-get target :candidates) ; embark-act-all
   1971                              (list (plist-get target :target)))
   1972                        (plist-get target :target))))
   1973                 (lambda ()
   1974                   (with-selected-window action-window
   1975                     (embark--run-action-hooks embark-pre-action-hooks
   1976                                               action target quit)
   1977                     (unwind-protect
   1978                         (let ((current-prefix-arg prefix)
   1979                               (default-directory directory))
   1980                           (funcall action argument))
   1981                       (embark--run-action-hooks embark-post-action-hooks
   1982                                                 action target quit))))))))
   1983       (setq prefix-arg nil)
   1984       (if quit (embark--quit-and-run run-action) (funcall run-action)))))
   1985 
   1986 (defun embark--refine-multi-category (_type target)
   1987   "Refine `multi-category' TARGET to its actual type."
   1988   (or (get-text-property 0 'multi-category target)
   1989       (cons 'general target)))
   1990 
   1991 (defun embark--simplify-path (_type target)
   1992   "Simplify and '//' or '~/' in the TARGET file path."
   1993   (cons 'file (substitute-in-file-name target)))
   1994 
   1995 (defun embark--keybinding-command (_type target)
   1996   "Treat an `embark-keybinding' TARGET as a command."
   1997   (when-let ((cmd (get-text-property 0 'embark-command target)))
   1998     (cons 'command (format "%s" cmd))))
   1999 
   2000 (defun embark--lookup-lighter-minor-mode (_type target)
   2001   "If TARGET is a lighter, look up its minor mode.
   2002 
   2003 The `describe-minor-mode' command has as completion candidates
   2004 both minor-modes and their lighters.  This function replaces the
   2005 lighters by their minor modes, so actions expecting a function
   2006 work on them."
   2007   (cons 'minor-mode
   2008         (let ((symbol (intern-soft target)))
   2009           (if (and symbol (boundp symbol))
   2010               target
   2011             (symbol-name (lookup-minor-mode-from-indicator target))))))
   2012 
   2013 (declare-function project-current "project")
   2014 (declare-function project-roots "project")
   2015 (declare-function project-root "project")
   2016 
   2017 (defun embark--project-file-full-path (_type target)
   2018   "Get full path of project file TARGET."
   2019   ;; TODO project-find-file can be called from outside all projects in
   2020   ;; which case it prompts for a project first; we don't support that
   2021   ;; case yet, since there is no current project.
   2022   (cons 'file
   2023         (if-let ((project (project-current))
   2024                  (root (if (fboundp 'project-root)
   2025                            (project-root project)
   2026                          (with-no-warnings
   2027                            (car (project-roots project))))))
   2028             (expand-file-name target root)
   2029           target)))
   2030 
   2031 (defun embark--remove-package-version (_type target)
   2032   "Remove version number from a versioned package TARGET."
   2033   (cons 'package (replace-regexp-in-string "-[0-9.]+$" "" target)))
   2034 
   2035 (defun embark--targets ()
   2036   "Retrieve current targets.
   2037 
   2038 An initial guess at the current targets and their types is
   2039 determined by running the functions in `embark-target-finders'.
   2040 Each function should either return nil, a pair of a type symbol
   2041 and target string or a triple of a type symbol, target string and
   2042 target bounds.
   2043 
   2044 In the minibuffer only the first target finder returning non-nil
   2045 is taken into account.  When finding targets at point in other
   2046 buffers, all target finder function is executed.
   2047 
   2048 For each target, the type is then looked up as a key in the
   2049 variable `embark-transformer-alist'.  If there is a transformer
   2050 for the type, it is called with the type and target, and must
   2051 return a `cons' of the transformed type and transformed target.
   2052 
   2053 The return value of `embark--targets' is a list of plists.  Each
   2054 plist concerns one target, and has keys `:type', `:target',
   2055 `:orig-type', `:orig-target' and `:bounds'."
   2056   (let (targets)
   2057     (run-hook-wrapped
   2058      'embark-target-finders
   2059      (lambda (fun)
   2060        (dolist (found (when-let (result (funcall fun))
   2061                         (if (consp (car result)) result (list result))))
   2062          (let* ((type (or (car found) 'general))
   2063                 (target+bounds (cdr found))
   2064                 (target (if (consp target+bounds)
   2065                             (car target+bounds)
   2066                           target+bounds))
   2067                 (bounds (and (consp target+bounds) (cdr target+bounds)))
   2068                 (full-target
   2069                  (append
   2070                   (list :orig-type type :orig-target target :bounds bounds)
   2071                   (if-let (transform (alist-get type embark-transformer-alist))
   2072                       (let ((trans (funcall transform type target)))
   2073                         (list :type (car trans) :target (cdr trans)))
   2074                     (list :type type :target target)))))
   2075            (push full-target targets)))
   2076        (and targets (minibufferp))))
   2077     (cl-delete-duplicates
   2078      (nreverse targets)
   2079      :test (lambda (t1 t2)
   2080              (and (equal (plist-get t1 :target) (plist-get t2 :target))
   2081                   (eq (plist-get t1 :type) (plist-get t2 :type)))))))
   2082 
   2083 (defun embark--default-action (type)
   2084   "Return default action for the given TYPE of target.
   2085 The most common case is that the target comes from minibuffer
   2086 completion, in which case the default action is the command that
   2087 opened the minibuffer in the first place.  This can be overridden
   2088 by `embark-default-action-overrides'.
   2089 
   2090 For targets that do not come from minibuffer completion
   2091 \(typically some thing at point in a regular buffer) and whose
   2092 type is not listed in `embark-default-action-overrides', the
   2093 default action is given by whatever binding RET has in the action
   2094 keymap for the given type."
   2095   (or (alist-get (cons type embark--command) embark-default-action-overrides
   2096                  nil nil #'equal)
   2097       (alist-get type embark-default-action-overrides)
   2098       (alist-get t embark-default-action-overrides)
   2099       embark--command
   2100       (lookup-key (embark--raw-action-keymap type) "\r")))
   2101 
   2102 (defun embark--rotate (list k)
   2103   "Rotate LIST by K elements and return the rotated list."
   2104   (setq k (mod k (length list)))
   2105   (append (seq-drop list k) (seq-take list k)))
   2106 
   2107 (defun embark--orig-target (target)
   2108   "Convert TARGET to original target."
   2109   (plist-put
   2110    (plist-put
   2111     (copy-sequence target)
   2112     :target (plist-get target :orig-target))
   2113    :type (plist-get target :orig-type)))
   2114 
   2115 (defun embark--quit-p (action)
   2116   "Determine whether to quit the minibuffer after ACTION.
   2117 This function consults `embark-quit-after-action' to decide
   2118 whether or not the user wishes to quit the minibuffer after
   2119 performing the ACTION, assuming this is done from a minibuffer."
   2120   (let* ((cfg embark-quit-after-action)
   2121          (quit (if (consp cfg) (alist-get action cfg (alist-get t cfg)) cfg)))
   2122     (when embark--toggle-quit (setq quit (not quit)))
   2123     (setq embark--toggle-quit nil)
   2124     quit))
   2125 
   2126 ;;;###autoload
   2127 (defun embark-act (&optional arg)
   2128   "Prompt the user for an action and perform it.
   2129 The targets of the action are chosen by `embark-target-finders'.
   2130 By default, if called from a minibuffer the target is the top
   2131 completion candidate.  When called from a non-minibuffer buffer
   2132 there can multiple targets and you can cycle among them by using
   2133 `embark-cycle' (which is bound by default to the same key
   2134 binding `embark-act' is, but see `embark-cycle-key').
   2135 
   2136 This command uses `embark-prompter' to ask the user to specify an
   2137 action, and calls it injecting the target at the first minibuffer
   2138 prompt.
   2139 
   2140 If you call this from the minibuffer, it can optionally quit the
   2141 minibuffer.  The variable `embark-quit-after-action' controls
   2142 whether calling `embark-act' with nil ARG quits the minibuffer,
   2143 and if ARG is non-nil it will do the opposite.  Interactively,
   2144 ARG is the prefix argument.
   2145 
   2146 If instead you call this from outside the minibuffer, the first
   2147 ARG targets are skipped over (if ARG is negative the skipping is
   2148 done by cycling backwards) and cycling starts from the following
   2149 target."
   2150   (interactive "P")
   2151   (let* ((targets (or (embark--targets) (user-error "No target found")))
   2152          (indicators (mapcar #'funcall embark-indicators))
   2153          (default-done nil))
   2154     (when arg
   2155       (if (minibufferp)
   2156           (embark-toggle-quit)
   2157         (setq targets (embark--rotate targets (prefix-numeric-value arg)))))
   2158     (unwind-protect
   2159         (while
   2160             (let* ((target (car targets))
   2161                    (action
   2162                     (or (embark--prompt
   2163                          indicators
   2164                          (let ((embark-default-action-overrides
   2165                                 (if default-done
   2166                                     `((t . ,default-done))
   2167                                   embark-default-action-overrides)))
   2168                            (embark--action-keymap (plist-get target :type)
   2169                                                   (cdr targets)))
   2170                          targets)
   2171                         (user-error "Canceled")))
   2172                    (default-action (or default-done
   2173                                        (embark--default-action
   2174                                         (plist-get target :type)))))
   2175               (cond
   2176                ;; When acting twice in the minibuffer, do not restart
   2177                ;; `embark-act'.  Otherwise the next `embark-act' will
   2178                ;; find a target in the original buffer.
   2179                ((eq action #'embark-act)
   2180                 (message "Press an action key"))
   2181                ((eq action #'embark-cycle)
   2182                 (setq targets (embark--rotate
   2183                                targets (prefix-numeric-value prefix-arg))))
   2184                (t
   2185                 ;; if the action is non-repeatable, cleanup indicator now
   2186                 (let ((repeat (embark--action-repeatable-p action)))
   2187                   (unless repeat (mapc #'funcall indicators))
   2188                   (condition-case err
   2189                       (embark--act
   2190                        action
   2191                        (if (and (eq action default-action)
   2192                                 (eq action embark--command)
   2193                                 (not (memq action embark-multitarget-actions)))
   2194                            (embark--orig-target target)
   2195                          target)
   2196                        (embark--quit-p action))
   2197                     (user-error
   2198                      (funcall (if repeat #'message #'user-error)
   2199                               "%s" (cadr err))))
   2200                   (when-let (new-targets (and repeat (embark--targets)))
   2201                     ;; Terminate repeated prompter on default action,
   2202                     ;; when repeating. Jump to the region type if the
   2203                     ;; region is active after the action, or else to the
   2204                     ;; current type again.
   2205                     (setq default-done #'embark-done
   2206                           targets
   2207                           (embark--rotate
   2208                            new-targets
   2209                            (or (cl-position-if
   2210                                 (let ((desired-type
   2211                                        (if (eq repeat t)
   2212                                            (plist-get (car targets) :type)
   2213                                          repeat)))
   2214                                   (lambda (x)
   2215                                     (eq (plist-get x :type) desired-type)))
   2216                                 new-targets)
   2217                                0)))))))))
   2218       (mapc #'funcall indicators))))
   2219 
   2220 (defun embark--maybe-transform-candidates ()
   2221   "Collect candidates and see if they all transform to the same type.
   2222 Return a plist with keys `:type', `:orig-type', `:candidates', and
   2223 `:orig-candidates'."
   2224   (pcase-let* ((`(,type . ,candidates)
   2225                 (run-hook-with-args-until-success 'embark-candidate-collectors))
   2226                (bounds (mapcar #'cdr-safe candidates)))
   2227     (setq candidates
   2228           (mapcar (lambda (x) (if (consp x) (car x) x)) candidates))
   2229     (when (eq type 'file)
   2230       (let ((dir (embark--default-directory)))
   2231         (setq candidates
   2232               (mapcar (lambda (cand)
   2233                         (abbreviate-file-name (expand-file-name cand dir)))
   2234                       candidates))))
   2235     (append
   2236      (list :orig-type type :orig-candidates candidates :bounds bounds)
   2237      (or (when candidates
   2238            (when-let ((transformer (alist-get type embark-transformer-alist)))
   2239              (pcase-let* ((`(,new-type . ,first-cand)
   2240                            (funcall transformer type (car candidates))))
   2241                (let ((new-candidates (list first-cand)))
   2242                  (when (cl-every
   2243                         (lambda (cand)
   2244                           (pcase-let ((`(,t-type . ,t-cand)
   2245                                        (funcall transformer type cand)))
   2246                             (when (eq t-type new-type)
   2247                               (push t-cand new-candidates)
   2248                               t)))
   2249                         (cdr candidates))
   2250                    (list :type new-type
   2251                          :candidates (nreverse new-candidates)))))))
   2252          (list :type type :candidates candidates)))))
   2253 
   2254 ;;;###autoload
   2255 (defun embark-act-all (&optional arg)
   2256   "Prompt the user for an action and perform it on each candidate.
   2257 The candidates are chosen by `embark-candidate-collectors'.
   2258 By default, if called from a minibuffer the candidates are the
   2259 completion candidates.
   2260 
   2261 This command uses `embark-prompter' to ask the user to specify an
   2262 action, and calls it injecting the target at the first minibuffer
   2263 prompt.
   2264 
   2265 If you call this from the minibuffer, it can optionally quit the
   2266 minibuffer.  The variable `embark-quit-after-action' controls
   2267 whether calling `embark-act' with nil ARG quits the minibuffer,
   2268 and if ARG is non-nil it will do the opposite.  Interactively,
   2269 ARG is the prefix argument."
   2270   (interactive "P")
   2271   (let* ((transformed (embark--maybe-transform-candidates))
   2272          (type (plist-get transformed :type))
   2273          (orig-type (plist-get transformed :orig-type))
   2274          (candidates
   2275           (or (cl-mapcar
   2276                (lambda (cand orig-cand bounds)
   2277                  (list :type type :target cand
   2278                        :bounds (when bounds
   2279                                  (cons (copy-marker (car bounds))
   2280                                        (copy-marker (cdr bounds))))
   2281                        :orig-type orig-type :orig-target orig-cand))
   2282                (plist-get transformed :candidates)
   2283                (plist-get transformed :orig-candidates)
   2284                (plist-get transformed :bounds))
   2285               (user-error "No candidates to act on")))
   2286          (indicators (mapcar #'funcall embark-indicators)))
   2287     (when arg (embark-toggle-quit))
   2288     (unwind-protect
   2289         (let* ((action
   2290                 (or (embark--prompt
   2291                      indicators (embark--action-keymap type nil)
   2292                      (list (list :type type :multi (length candidates))))
   2293                     (user-error "Canceled")))
   2294                (prefix prefix-arg)
   2295                (act (lambda (candidate)
   2296                       (cl-letf (((symbol-function 'embark--restart) #'ignore)
   2297                                 ((symbol-function 'embark--confirm) #'ignore))
   2298                         (let ((prefix-arg prefix))
   2299                           (embark--act action candidate)))))
   2300                (quit (embark--quit-p action)))
   2301           (when (and (eq action (embark--default-action type))
   2302                      (eq action embark--command))
   2303             (setq candidates (mapcar #'embark--orig-target candidates)))
   2304           (when (or (not (or embark-confirm-act-all
   2305                              (memq 'embark--confirm
   2306                                    (alist-get action embark-pre-action-hooks))))
   2307                     (y-or-n-p (format "Run %s on %d %ss? "
   2308                                       action (length candidates) type)))
   2309             (if (memq action embark-multitarget-actions)
   2310                 (let ((prefix-arg prefix))
   2311                   (embark--act action transformed quit))
   2312               (if quit
   2313                   (embark--quit-and-run #'mapc act candidates)
   2314                 (mapc act candidates)
   2315                 (when (memq 'embark--restart
   2316                             (alist-get action embark-post-action-hooks))
   2317                   (embark--restart))))))
   2318       (dolist (cand candidates)
   2319         (when-let ((bounds (plist-get cand :bounds)))
   2320           (set-marker (car bounds) nil) ; yay, manual memory management!
   2321           (set-marker (cdr bounds) nil)))
   2322       (setq prefix-arg nil)
   2323       (mapc #'funcall indicators))))
   2324 
   2325 (defun embark-highlight-indicator ()
   2326   "Action indicator highlighting the target at point."
   2327   (let (overlay)
   2328     (lambda (&optional keymap targets _prefix)
   2329       (let ((bounds (plist-get (car targets) :bounds)))
   2330         (when (and overlay (or (not keymap) (not bounds)))
   2331           (delete-overlay overlay)
   2332           (setq overlay nil))
   2333         (when bounds
   2334           (if overlay
   2335               (move-overlay overlay (car bounds) (cdr bounds))
   2336             (setq overlay (make-overlay (car bounds) (cdr bounds))))
   2337           (overlay-put overlay 'face 'embark-target)
   2338           (overlay-put overlay 'window (selected-window))
   2339           ;; high priority to override both bug reference and the lazy
   2340           ;; isearch highlights in embark-isearch-highlight-indicator
   2341           (overlay-put overlay 'priority 1001))))))
   2342 
   2343 (defun embark-isearch-highlight-indicator ()
   2344   "Action indicator highlighting all occurrences of the identifier at point.
   2345 This indicator only does something for targets which are
   2346 identifiers or symbols.  For those it uses `isearch''s lazy
   2347 highlighting feature to highlight all occurrences of the target in
   2348 the buffer.  This indicator is best used in conjunction with
   2349 `embark-highlight-indicator': by using them both you get the
   2350 target and the other occurrences of it highlighted in different
   2351 colors."
   2352   (lambda (&optional _keymap targets _prefix)
   2353     (if (and (not (minibufferp))
   2354              (memq (plist-get (car targets) :orig-type) '(symbol identifier)))
   2355         (let ((isearch-string (plist-get (car targets) :target))
   2356               (isearch-regexp-function #'isearch-symbol-regexp))
   2357           (isearch-lazy-highlight-new-loop))
   2358       (setq isearch-lazy-highlight-last-string nil)
   2359       (lazy-highlight-cleanup t))))
   2360 
   2361 (defun embark-cycle (_arg)
   2362   "Cycle over the next ARG targets at point.
   2363 If ARG is negative, cycle backwards."
   2364   (interactive "p")
   2365   (user-error "Not meant to be called directly"))
   2366 
   2367 (defun embark-done ()
   2368   "Terminate sequence of repeated actions."
   2369   (interactive))
   2370 
   2371 ;;;###autoload
   2372 (defun embark-dwim (&optional arg)
   2373   "Run the default action on the current target.
   2374 The target of the action is chosen by `embark-target-finders'.
   2375 
   2376 If the target comes from minibuffer completion, then the default
   2377 action is the command that opened the minibuffer in the first
   2378 place, unless overridden by `embark-default-action-overrides'.
   2379 
   2380 For targets that do not come from minibuffer completion
   2381 \(typically some thing at point in a regular buffer) and whose
   2382 type is not listed in `embark-default-action-overrides', the
   2383 default action is given by whatever binding RET has in the action
   2384 keymap for the target's type.
   2385 
   2386 See `embark-act' for the meaning of the prefix ARG."
   2387   (interactive "P")
   2388   (if-let ((targets (embark--targets)))
   2389       (let* ((target
   2390               (or (nth
   2391                    (if (or (null arg) (minibufferp))
   2392                        0
   2393                      (mod (prefix-numeric-value arg) (length targets)))
   2394                    targets)))
   2395              (type (plist-get target :type))
   2396              (default-action (embark--default-action type))
   2397              (action (or (command-remapping default-action) default-action)))
   2398         (unless action
   2399           (user-error "No default action for %s targets" type))
   2400         (when (and arg (minibufferp)) (setq embark--toggle-quit t))
   2401         (embark--act action
   2402                      (if (and (eq default-action embark--command)
   2403                               (not (memq default-action
   2404                                          embark-multitarget-actions)))
   2405                          (embark--orig-target target)
   2406                        target)
   2407                      (embark--quit-p action)))
   2408     (user-error "No target found")))
   2409 
   2410 (defun embark--become-keymap ()
   2411   "Return keymap of commands to become for current command."
   2412   (let ((map (make-composed-keymap
   2413               (cl-loop for keymap-name in embark-become-keymaps
   2414                        for keymap = (symbol-value keymap-name)
   2415                        when (where-is-internal embark--command (list keymap))
   2416                        collect keymap))))
   2417     (when embark-help-key
   2418       (keymap-set map embark-help-key #'embark-keymap-help))
   2419     map))
   2420 
   2421 ;;;###autoload
   2422 (defun embark-become (&optional full)
   2423   "Make current command become a different command.
   2424 Take the current minibuffer input as initial input for new
   2425 command.  The new command can be run normally using key bindings or
   2426 \\[execute-extended-command], but if the current command is found in a keymap in
   2427 `embark-become-keymaps', that keymap is activated to provide
   2428 convenient access to the other commands in it.
   2429 
   2430 If FULL is non-nil (interactively, if called with a prefix
   2431 argument), the entire minibuffer contents are used as the initial
   2432 input of the new command.  By default only the part of the
   2433 minibuffer contents between the current completion boundaries is
   2434 taken.  What this means is fairly technical, but (1) usually
   2435 there is no difference: the completion boundaries include the
   2436 entire minibuffer contents, and (2) the most common case where
   2437 these notions differ is file completion, in which case the
   2438 completion boundaries single out the path component containing
   2439 point."
   2440   (interactive "P")
   2441   (unless (minibufferp)
   2442     (user-error "Not in a minibuffer"))
   2443   (let* ((target (if full
   2444                      (minibuffer-contents)
   2445                    (pcase-let ((`(,beg . ,end) (embark--boundaries)))
   2446                      (substring (minibuffer-contents) beg
   2447                                 (+ end (embark--minibuffer-point))))))
   2448          (keymap (embark--become-keymap))
   2449          (targets `((:type embark-become :target ,target)))
   2450          (indicators (mapcar #'funcall embark-indicators))
   2451          (become (unwind-protect
   2452                      (embark--prompt indicators keymap targets)
   2453                    (mapc #'funcall indicators))))
   2454     (unless become
   2455       (user-error "Canceled"))
   2456     (embark--become-command become target)))
   2457 
   2458 (defun embark--become-command (command input)
   2459   "Quit current minibuffer and start COMMAND with INPUT."
   2460   (embark--quit-and-run
   2461    (lambda ()
   2462      (minibuffer-with-setup-hook
   2463          (lambda ()
   2464            (delete-minibuffer-contents)
   2465            (insert input))
   2466        (let ((use-dialog-box nil) ;; avoid mouse dialogs
   2467              (last-nonmenu-event 13))
   2468          (setq this-command command)
   2469          (command-execute command))))))
   2470 
   2471 (defmacro embark-define-keymap (&rest _)
   2472   "Obsolete macro, use `defvar-keymap' instead."
   2473   (error "`embark-define-keymap' has been deprecated in Embark 0.21.
   2474 Use standard methods for defining keymaps, such as `defvar-keymap'.
   2475 Remember to make `embark-general-map' the parent if appropriate"))
   2476 
   2477 ;;; Embark collect
   2478 
   2479 (defgroup embark-collect nil
   2480   "Buffers for acting on collected Embark targets."
   2481   :group 'embark)
   2482 
   2483 (defcustom embark-candidate-collectors
   2484   '(embark-selected-candidates
   2485     embark-minibuffer-candidates
   2486     embark-completions-buffer-candidates
   2487     embark-dired-candidates
   2488     embark-ibuffer-candidates
   2489     embark-embark-collect-candidates
   2490     embark-custom-candidates)
   2491   "List of functions that collect all candidates in a given context.
   2492 These are used to fill an Embark Collect buffer.  Each function
   2493 should return either nil (to indicate it found no candidates) or
   2494 a list whose first element is a symbol indicating the type of
   2495 candidates and whose `cdr' is the list of candidates, each of
   2496 which should be either a string or a dotted list of the
   2497 form (TARGET START . END), where START and END are the buffer
   2498 positions bounding the TARGET string."
   2499   :type 'hook)
   2500 
   2501 (defcustom embark-exporters-alist
   2502   '((buffer . embark-export-ibuffer)
   2503     (file . embark-export-dired)
   2504     (package . embark-export-list-packages)
   2505     (bookmark . embark-export-bookmarks)
   2506     (variable . embark-export-customize-variable)
   2507     (face . embark-export-customize-face)
   2508     (symbol . embark-export-apropos)
   2509     (minor-mode . embark-export-apropos)
   2510     (function . embark-export-apropos)
   2511     (command . embark-export-apropos)
   2512     (t . embark-collect))
   2513   "Alist associating completion types to export functions.
   2514 Each function should take a list of strings which are candidates
   2515 for actions and make a buffer appropriate to manage them.  For
   2516 example, the default is to make a Dired buffer for files, and an
   2517 ibuffer for buffers.
   2518 
   2519 The key t is also allowed in the alist, and the corresponding
   2520 value indicates the default function to use for other types.  The
   2521 default is `embark-collect'"
   2522   :type '(alist :key-type symbol :value-type function))
   2523 
   2524 (defcustom embark-after-export-hook nil
   2525   "Hook run after `embark-export' in the newly created buffer."
   2526   :type 'hook)
   2527 
   2528 (defface embark-collect-candidate '((t :inherit default))
   2529   "Face for candidates in Embark Collect buffers.")
   2530 
   2531 (defface embark-collect-group-title
   2532   '((t :inherit shadow :slant italic))
   2533   "Face for group titles in Embark Collect buffers.")
   2534 
   2535 (defface embark-collect-group-separator
   2536   '((t :inherit shadow :strike-through t italic))
   2537   "Face for group titles in Embark Collect buffers.")
   2538 
   2539 (defcustom embark-collect-group-format
   2540   (concat
   2541    (propertize "    " 'face 'embark-collect-group-separator)
   2542    (propertize " %s " 'face 'embark-collect-group-title)
   2543    (propertize " " 'face 'completions-group-separator
   2544                'display '(space :align-to right)))
   2545   "Format string used for the group title in Embark Collect buffers."
   2546   :type 'string)
   2547 
   2548 (defface embark-collect-annotation '((t :inherit completions-annotations))
   2549   "Face for annotations in Embark Collect.
   2550 This is only used for annotation that are not already fontified.")
   2551 
   2552 (defvar-local embark--rerun-function nil
   2553   "Function to rerun the collect or export that made the current buffer.")
   2554 
   2555 (autoload 'package-delete "package")
   2556 (declare-function package--from-builtin "package")
   2557 (declare-function package-desc-extras "package")
   2558 (declare-function package-desc-name "package")
   2559 (defvar package--builtins)
   2560 (defvar package-alist)
   2561 (defvar package-archive-contents)
   2562 (defvar package--initialized)
   2563 
   2564 (defun embark--package-desc (pkg)
   2565   "Return the description structure for package PKG."
   2566   (or ; found this in `describe-package-1'
   2567    (car (alist-get pkg package-alist))
   2568    (if-let ((built-in (assq pkg package--builtins)))
   2569            (package--from-builtin built-in)
   2570            (car (alist-get pkg package-archive-contents)))))
   2571 
   2572 (defun embark-minibuffer-candidates ()
   2573   "Return all current completion candidates from the minibuffer."
   2574   (when (minibufferp)
   2575     (let* ((all (completion-all-completions
   2576                  (minibuffer-contents)
   2577                  minibuffer-completion-table
   2578                  minibuffer-completion-predicate
   2579                  (embark--minibuffer-point)))
   2580            (last (last all)))
   2581       (when last (setcdr last nil))
   2582       (cons
   2583        (completion-metadata-get (embark--metadata) 'category)
   2584        all))))
   2585 
   2586 (defun embark-sorted-minibuffer-candidates ()
   2587   "Return a sorted list of current minibuffer completion candidates.
   2588 This using the same sort order that `icomplete' and
   2589 `minibuffer-force-complete' use.  The intended usage is that you
   2590 replace `embark-minibuffer-candidates' with this function in the
   2591 list `embark-candidate-collectors'."
   2592   (when (minibufferp)
   2593     (cons
   2594      (completion-metadata-get (embark--metadata) 'category)
   2595      (nconc (cl-copy-list (completion-all-sorted-completions)) nil))))
   2596 
   2597 (declare-function dired-get-marked-files "dired")
   2598 (declare-function dired-move-to-filename "dired")
   2599 (declare-function dired-move-to-end-of-filename "dired")
   2600 
   2601 (defun embark-dired-candidates ()
   2602   "Return marked or all files shown in Dired buffer.
   2603 If any buffer is marked, return marked buffers; otherwise, return
   2604 all buffers."
   2605   (when (derived-mode-p 'dired-mode)
   2606     (cons 'file
   2607           (or
   2608            ;; dired-get-marked-files returns the file on the current
   2609            ;; line if no marked files are found; and when the fourth
   2610            ;; argument is non-nil, the "no marked files" case is
   2611            ;; distinguished from the "single marked file" case by
   2612            ;; returning (list t marked-file) in the latter
   2613            (let ((marked (dired-get-marked-files t nil nil t)))
   2614              (and (cdr marked)
   2615                   (if (eq (car marked) t) (cdr marked) marked)))
   2616            (save-excursion
   2617              (goto-char (point-min))
   2618              (let (files)
   2619                (while (not (eobp))
   2620                  (when-let (file (dired-get-filename t t))
   2621                    (push `(,file
   2622                            ,(progn (dired-move-to-filename) (point))
   2623                            . ,(progn (dired-move-to-end-of-filename t) (point)))
   2624                          files))
   2625                  (forward-line))
   2626                (nreverse files)))))))
   2627 
   2628 (autoload 'ibuffer-marked-buffer-names "ibuffer")
   2629 (declare-function ibuffer-map-lines-nomodify "ibuffer")
   2630 
   2631 (defun embark-ibuffer-candidates ()
   2632   "Return marked or all buffers listed in ibuffer buffer.
   2633 If any buffer is marked, return marked buffers; otherwise, return
   2634 all buffers."
   2635   (when (derived-mode-p 'ibuffer-mode)
   2636     (cons 'buffer
   2637           (or (ibuffer-marked-buffer-names)
   2638               (let (buffers)
   2639                 (ibuffer-map-lines-nomodify
   2640                  (lambda (buffer _mark)
   2641                    (push (buffer-name buffer) buffers)))
   2642                 (nreverse buffers))))))
   2643 
   2644 (defun embark-embark-collect-candidates ()
   2645   "Return candidates in Embark Collect buffer.
   2646 This makes `embark-export' work in Embark Collect buffers."
   2647   (when (derived-mode-p 'embark-collect-mode)
   2648     (cons embark--type
   2649           (save-excursion
   2650             (goto-char (point-min))
   2651             (let (all)
   2652               (push (cdr (embark-target-collect-candidate)) all)
   2653               (while (forward-button 1 nil nil t)
   2654                 (push (cdr (embark-target-collect-candidate)) all))
   2655               (nreverse all))))))
   2656 
   2657 (defun embark-completions-buffer-candidates ()
   2658   "Return all candidates in a completions buffer."
   2659   (when (derived-mode-p 'completion-list-mode)
   2660     (cons
   2661      embark--type
   2662      (save-excursion
   2663        (goto-char (point-min))
   2664        (next-completion 1)
   2665        (let (all)
   2666          (while (not (eobp))
   2667            (push (cdr (embark-target-completion-at-point)) all)
   2668            (next-completion 1))
   2669          (nreverse all))))))
   2670 
   2671 (defun embark-custom-candidates ()
   2672   "Return all variables and faces listed in this `Custom-mode' buffer."
   2673   (when (derived-mode-p 'Custom-mode)
   2674     (cons 'symbol ; gets refined to variable or face when acted upon
   2675           (save-excursion
   2676             (goto-char (point-min))
   2677             (let (symbols)
   2678               (while (not (eobp))
   2679                 (when-let (widget (widget-at (point)))
   2680                   (when (eq (car widget) 'custom-visibility)
   2681                     (push
   2682                      `(,(symbol-name
   2683                          (plist-get (cdr (plist-get (cdr widget) :parent))
   2684                                     :value))
   2685                        ,(point)
   2686                        . ,(progn
   2687                             (re-search-forward ":" (line-end-position) 'noerror)
   2688                             (point)))
   2689                      symbols)))
   2690                 (forward-line))
   2691               (nreverse symbols))))))
   2692 
   2693 
   2694 (defun embark-collect--target ()
   2695   "Return the Embark Collect candidate at point.
   2696 This takes into account `embark-transformer-alist'."
   2697   (let ((embark-target-finders '(embark-target-collect-candidate)))
   2698     (car (embark--targets))))
   2699 
   2700 (defun embark--action-command (action)
   2701   "Turn an ACTION into a command to perform the action.
   2702 Returns the name of the command."
   2703   (let ((name (intern (format "embark-action--%s"
   2704                               (embark--command-name action)))))
   2705     (fset name (lambda (arg)
   2706                  (interactive "P")
   2707                  (when-let (target (embark-collect--target))
   2708                    (let ((prefix-arg arg))
   2709                      (embark--act action target)))))
   2710     (when (fboundp action)
   2711       (put name 'function-documentation (documentation action)))
   2712     name))
   2713 
   2714 (defun embark--all-bindings (keymap &optional nested)
   2715   "Return an alist of all bindings in KEYMAP.
   2716 If NESTED is non-nil subkeymaps are not flattened."
   2717   (let (bindings maps)
   2718     (map-keymap
   2719      (lambda (key def)
   2720        (cond
   2721         ((keymapp def)
   2722          (if nested
   2723              (push (cons (vector key) def) maps)
   2724            (dolist (bind (embark--all-bindings def))
   2725              (push (cons (vconcat (vector key) (car bind)) (cdr bind))
   2726                    maps))))
   2727         (def (push (cons (vector key) def) bindings))))
   2728      (keymap-canonicalize keymap))
   2729     (nconc (nreverse bindings) (nreverse maps))))
   2730 
   2731 (defun embark-collect--direct-action-map (type)
   2732   "Return a direct action keymap for targets of given TYPE."
   2733   (let* ((actions (embark--action-keymap type nil))
   2734          (map (make-sparse-keymap)))
   2735     (set-keymap-parent map button-map)
   2736     (pcase-dolist (`(,key . ,cmd) (embark--all-bindings actions))
   2737       (unless (or (equal key [13])
   2738                   (memq cmd '(digit-argument negative-argument)))
   2739         (define-key map key (if (eq cmd 'embark-keymap-help)
   2740                                 #'embark-bindings-at-point
   2741                               (embark--action-command cmd)))))
   2742     map))
   2743 
   2744 (define-minor-mode embark-collect-direct-action-minor-mode
   2745   "Bind type-specific actions directly (without need for `embark-act')."
   2746   :init-value nil
   2747   :lighter " Act"
   2748   (unless (derived-mode-p 'embark-collect-mode)
   2749     (user-error "Not in an Embark Collect buffer"))
   2750   (save-excursion
   2751     (goto-char (point-min))
   2752     (let ((inhibit-read-only t) maps)
   2753       (while (progn
   2754                (when (tabulated-list-get-id)
   2755                  (put-text-property
   2756                   (point) (button-end (point)) 'keymap
   2757                   (if embark-collect-direct-action-minor-mode
   2758                       (when-let ((target (embark-collect--target))
   2759                                  (type (plist-get target :type)))
   2760                         (or (alist-get type maps)
   2761                             (setf (alist-get type maps)
   2762                                   (embark-collect--direct-action-map type)))))))
   2763                (forward-button 1 nil nil t))))))
   2764 
   2765 (define-button-type 'embark-collect-entry
   2766   'face 'embark-collect-candidate
   2767   'action 'embark-collect-choose)
   2768 
   2769 (declare-function outline-toggle-children "outline")
   2770 (define-button-type 'embark-collect-group
   2771   'face 'embark-collect-group-title
   2772   'action (lambda (_) (outline-toggle-children)))
   2773 
   2774 (defun embark--boundaries ()
   2775   "Get current minibuffer completion boundaries."
   2776   (let ((contents (minibuffer-contents))
   2777         (pt (embark--minibuffer-point)))
   2778     (completion-boundaries
   2779      (substring contents 0 pt)
   2780      minibuffer-completion-table
   2781      minibuffer-completion-predicate
   2782      (substring contents pt))))
   2783 
   2784 (defun embark-collect-choose (entry)
   2785   "Run default action on Embark Collect ENTRY."
   2786   (pcase-let ((`(,type ,text ,start . ,end)
   2787                (save-excursion
   2788                  (goto-char entry)
   2789                  (embark-target-collect-candidate))))
   2790     (embark--act (embark--default-action type)
   2791                  (list :target text
   2792                        :type type
   2793                        :bounds (cons start end)))))
   2794 
   2795 (defvar-keymap embark-collect-mode-map
   2796   :doc "Keymap for Embark collect mode."
   2797   :parent tabulated-list-mode-map
   2798   "a" #'embark-act
   2799   "A" #'embark-act-all
   2800   "M-a" #'embark-collect-direct-action-minor-mode
   2801   "E" #'embark-export
   2802   "s" #'isearch-forward
   2803   "n" #'forward-button
   2804   "p" #'backward-button
   2805   "}" 'outline-next-heading
   2806   "{" 'outline-previous-heading
   2807   "<remap> <forward-paragraph>" 'outline-next-heading
   2808   "<remap> <backward-paragraph>" 'outline-previous-heading
   2809   "<remap> <revert-buffer>" #'embark-rerun-collect-or-export)
   2810 
   2811 (defconst embark-collect--outline-string (string #x210000)
   2812   "Special string used for outline headings in Embark Collect buffers.
   2813 Chosen to be extremely unlikely to appear in a candidate.")
   2814 
   2815 (define-derived-mode embark-collect-mode tabulated-list-mode "Embark Collect"
   2816   "List of candidates to be acted on.
   2817 The command `embark-act' is bound `embark-collect-mode-map', but
   2818 you might prefer to change the key binding to match your other
   2819 key binding for it.  Or alternatively you might want to enable the
   2820 embark collect direct action minor mode by adding the function
   2821 `embark-collect-direct-action-minor-mode' to
   2822 `embark-collect-mode-hook'.
   2823 
   2824 Reverting an Embark Collect buffer has slightly unusual behavior
   2825 if the buffer was obtained by running `embark-collect' from
   2826 within a minibuffer completion session.  In that case reverting
   2827 just restarts the completion session, that is, the command that
   2828 opened the minibuffer is run again and the minibuffer contents
   2829 restored.  You can then interact normally with the command,
   2830 perhaps editing the minibuffer contents, and, if you wish, you
   2831 can rerun `embark-collect' to get an updated buffer."
   2832     :interactive nil :abbrev-table nil :syntax-table nil)
   2833 
   2834 (defun embark-collect--metadatum (type metadatum)
   2835   "Get METADATUM for current buffer's candidates.
   2836 For non-minibuffers, assume candidates are of given TYPE."
   2837   (if (minibufferp)
   2838       (or (completion-metadata-get (embark--metadata) metadatum)
   2839           (plist-get completion-extra-properties
   2840                      (intern (format ":%s" metadatum))))
   2841     ;; otherwise fake some metadata for Marginalia users's benefit
   2842     (completion-metadata-get `((category . ,type)) metadatum)))
   2843 
   2844 (defun embark-collect--affixator (type)
   2845   "Get affixation function for current buffer's candidates.
   2846 For non-minibuffers, assume candidates are of given TYPE."
   2847   (or (embark-collect--metadatum type 'affixation-function)
   2848       (let ((annotator
   2849              (or (embark-collect--metadatum type 'annotation-function)
   2850                  (lambda (_) ""))))
   2851         (lambda (candidates)
   2852           (mapcar (lambda (c)
   2853                     (if-let (a (funcall annotator c)) (list c "" a) c))
   2854                   candidates)))))
   2855 
   2856 (defun embark--for-display (string)
   2857   "Return visibly equivalent STRING without display and invisible properties."
   2858   (let ((len (length string)) (pos 0) chunks)
   2859     (while (/= pos len)
   2860       (let ((dis (next-single-property-change pos 'display string len))
   2861             (display (get-text-property pos 'display string)))
   2862         (if (stringp display)
   2863             (progn (push display chunks) (setq pos dis))
   2864           (while (/= pos dis)
   2865             (let ((inv (next-single-property-change pos 'invisible string dis)))
   2866               (unless (get-text-property pos 'invisible string)
   2867                 (unless (and (= pos 0) (= inv len))
   2868                   ;; avoid allocation for full string
   2869                   (push (substring string pos inv) chunks)))
   2870               (setq pos inv))))))
   2871     (if chunks (apply #'concat (nreverse chunks)) string)))
   2872 
   2873 (defun embark-collect--format-entries (candidates grouper)
   2874   "Format CANDIDATES for `tabulated-list-mode' grouped by GROUPER.
   2875 The GROUPER is either nil or a function like the `group-function'
   2876 completion metadatum, that is, a function of two arguments, the
   2877 first of which is a candidate and the second controls what is
   2878 computed: if nil, the title of the group the candidate belongs
   2879 to, and if non-nil, a rewriting of the candidate (useful to
   2880 simplify the candidate so it doesn't repeat the group title, for
   2881 example)."
   2882   (let ((max-width 0)
   2883         (transform
   2884          (if grouper (lambda (cand) (funcall grouper cand t)) #'identity)))
   2885     (setq tabulated-list-entries
   2886           (mapcan
   2887            (lambda (group)
   2888              (cons
   2889               `(nil [(,(concat (propertize embark-collect--outline-string
   2890                                            'invisible t)
   2891                                (format embark-collect-group-format (car group)))
   2892                       type embark-collect-group)
   2893                      ("" skip t)])
   2894               (mapcar
   2895                (pcase-lambda (`(,cand ,prefix ,annotation))
   2896                  (let* ((display (embark--for-display (funcall transform cand)))
   2897                         (length (length annotation))
   2898                         (faces (text-property-not-all
   2899                                 0 length 'face nil annotation)))
   2900                    (setq max-width (max max-width (+ (string-width prefix)
   2901                                                      (string-width display))))
   2902                    (when faces
   2903                      (add-face-text-property 0 length 'default t annotation))
   2904                    `(,cand
   2905                      [(,(propertize display 'line-prefix prefix)
   2906                        type embark-collect-entry)
   2907                       (,annotation
   2908                        skip t
   2909                        ,@(unless faces
   2910                            '(face embark-collect-annotation)))])))
   2911                (cdr group))))
   2912            (if grouper
   2913                (seq-group-by (lambda (item) (funcall grouper (car item) nil))
   2914                              candidates)
   2915              (list (cons "" candidates)))))
   2916     (if (null grouper)
   2917         (pop tabulated-list-entries)
   2918       (setq-local outline-regexp embark-collect--outline-string)
   2919       (outline-minor-mode))
   2920     (setq tabulated-list-format
   2921           `[("Candidate" ,max-width t) ("Annotation" 0 t)])))
   2922 
   2923 (defun embark-collect--update-candidates (buffer)
   2924   "Update candidates for Embark Collect BUFFER."
   2925   (let* ((transformed (embark--maybe-transform-candidates))
   2926          (type (plist-get transformed :orig-type)) ; we need the originals for
   2927          (candidates (plist-get transformed :orig-candidates)) ; default action
   2928          (affixator (embark-collect--affixator type))
   2929          (grouper (embark-collect--metadatum type 'group-function)))
   2930     (when (eq type 'file)
   2931       (let ((dir (buffer-local-value 'default-directory buffer)))
   2932         (setq candidates
   2933               (mapcar (lambda (cand)
   2934                         (let ((rel (file-relative-name cand dir)))
   2935                           (if (string-prefix-p "../" rel) cand rel)))
   2936                       candidates))))
   2937     (setq candidates (funcall affixator candidates))
   2938     (with-current-buffer buffer
   2939       (setq embark--type type)
   2940       (embark-collect--format-entries candidates grouper))
   2941     candidates))
   2942 
   2943 (defun embark--collect (buffer-name)
   2944   "Create an Embark Collect buffer named BUFFER-NAME.
   2945 
   2946 The function `generate-new-buffer-name' is used to ensure the
   2947 buffer has a unique name."
   2948   (let ((buffer (generate-new-buffer buffer-name))
   2949         (rerun (embark--rerun-function #'embark-collect)))
   2950     (with-current-buffer buffer
   2951       ;; we'll run the mode hooks once the buffer is displayed, so
   2952       ;; the hooks can make use of the window
   2953       (delay-mode-hooks (embark-collect-mode)))
   2954 
   2955     (embark--cache-info buffer)
   2956     (unless (embark-collect--update-candidates buffer)
   2957       (user-error "No candidates to collect"))
   2958 
   2959     (with-current-buffer buffer
   2960       (setq tabulated-list-use-header-line nil ; default to no header
   2961             header-line-format nil
   2962             tabulated-list--header-string nil)
   2963       (setq embark--rerun-function rerun))
   2964 
   2965     (let ((window (display-buffer buffer)))
   2966       (with-selected-window window
   2967         (run-mode-hooks)
   2968         (tabulated-list-revert))
   2969       (set-window-dedicated-p window t)
   2970       buffer)))
   2971 
   2972 (defun embark--descriptive-buffer-name (type)
   2973   "Return a descriptive name for an Embark collect or export buffer.
   2974 TYPE should be either `collect' or `export'."
   2975   (format "*Embark %s: %s*"
   2976           (capitalize (symbol-name type))
   2977           (if (minibufferp)
   2978               (format "%s - %s" embark--command
   2979                       (minibuffer-contents-no-properties))
   2980             (buffer-name))))
   2981 
   2982 ;;;###autoload
   2983 (defun embark-collect ()
   2984   "Create an Embark Collect buffer.
   2985 
   2986 To control the display, add an entry to `display-buffer-alist'
   2987 with key \"Embark Collect\".
   2988 
   2989 In Embark Collect buffers `revert-buffer' is remapped to
   2990 `embark-rerun-collect-or-export', which has slightly unusual
   2991 behavior if the buffer was obtained by running `embark-collect'
   2992 from within a minibuffer completion session.  In that case
   2993 rerunning just restarts the completion session, that is, the
   2994 command that opened the minibuffer is run again and the
   2995 minibuffer contents restored.  You can then interact normally with
   2996 the command, perhaps editing the minibuffer contents, and, if you
   2997 wish, you can rerun `embark-collect' to get an updated buffer."
   2998   (interactive)
   2999   (let ((buffer (embark--collect (embark--descriptive-buffer-name 'collect))))
   3000     (when (minibufferp)
   3001       (embark--run-after-command #'pop-to-buffer buffer)
   3002       (embark--quit-and-run #'message nil))))
   3003 
   3004 ;;;###autoload
   3005 (defun embark-live ()
   3006   "Create a live-updating Embark Collect buffer.
   3007 
   3008 To control the display, add an entry to `display-buffer-alist'
   3009 with key \"Embark Live\"."
   3010   (interactive)
   3011   (let ((live-buffer (embark--collect
   3012                       (format "*Embark Live: %s*"
   3013                               (if (minibufferp)
   3014                                   (format "M-x %s" embark--command)
   3015                                 (buffer-name)))))
   3016         (run-collect (make-symbol "run-collect"))
   3017         (stop-collect (make-symbol "stop-collect"))
   3018         timer)
   3019     (setf (symbol-function stop-collect)
   3020           (lambda ()
   3021             (remove-hook 'change-major-mode-hook stop-collect t)
   3022             (remove-hook 'after-change-functions run-collect t)))
   3023     (setf (symbol-function run-collect)
   3024           (lambda (_1 _2 _3)
   3025             (unless timer
   3026               (setq timer
   3027                     (run-with-idle-timer
   3028                      0.05 nil
   3029                      (lambda ()
   3030                        (if (not (buffer-live-p live-buffer))
   3031                            (funcall stop-collect)
   3032                          (embark-collect--update-candidates live-buffer)
   3033                          (with-current-buffer live-buffer
   3034                            ;; TODO figure out why I can't restore point
   3035                            (tabulated-list-print t t))
   3036                          (setq timer nil))))))))
   3037     (add-hook 'after-change-functions run-collect nil t)
   3038     (when (minibufferp)
   3039       (add-hook 'change-major-mode-hook stop-collect nil t))))
   3040 
   3041 (defun embark--rerun-function (kind)
   3042   "Return a rerun function for an export or collect buffer in this context.
   3043 The parameter KIND should be either `embark-export' or `embark-collect'."
   3044   (let ((buffer (or embark--target-buffer (embark--target-buffer)))
   3045         (command embark--command))
   3046     (cl-flet ((rerunner (action)
   3047                 (lambda (&rest _)
   3048                   (quit-window 'kill-buffer)
   3049                   (with-current-buffer
   3050                       (if (buffer-live-p buffer) buffer (current-buffer))
   3051                     (let ((embark--command command))
   3052                       (funcall action))))))
   3053         (if (minibufferp)
   3054           (rerunner
   3055            (let ((input (minibuffer-contents-no-properties)))
   3056              (lambda ()
   3057                (minibuffer-with-setup-hook
   3058                    (lambda ()
   3059                      (delete-minibuffer-contents)
   3060                      (insert input))
   3061                  (setq this-command embark--command)
   3062                  (command-execute embark--command)))))
   3063           (rerunner kind)))))
   3064 
   3065 (defun embark-rerun-collect-or-export ()
   3066   "Rerun the `embark-collect' or `embark-export' that created this buffer."
   3067   (interactive)
   3068   (if embark--rerun-function
   3069       (funcall embark--rerun-function)
   3070     (user-error "No function to rerun collect or export found")))
   3071 
   3072 ;;;###autoload
   3073 (defun embark-export ()
   3074   "Create a type-specific buffer to manage current candidates.
   3075 The variable `embark-exporters-alist' controls how to make the
   3076 buffer for each type of completion.
   3077 
   3078 In Embark Export buffers `revert-buffer' is remapped to
   3079 `embark-rerun-collect-or-export', which has slightly unusual
   3080 behavior if the buffer was obtained by running `embark-export'
   3081 from within a minibuffer completion session.  In that case
   3082 reverting just restarts the completion session, that is, the
   3083 command that opened the minibuffer is run again and the
   3084 minibuffer contents restored.  You can then interact normally
   3085 with the command, perhaps editing the minibuffer contents, and,
   3086 if you wish, you can rerun `embark-export' to get an updated
   3087 buffer."
   3088   (interactive)
   3089   (let* ((transformed (embark--maybe-transform-candidates))
   3090          (candidates (or (plist-get transformed :candidates)
   3091                          (user-error "No candidates for export")))
   3092          (type (plist-get transformed :type)))
   3093     (let ((exporter (or (alist-get type embark-exporters-alist)
   3094                         (alist-get t embark-exporters-alist))))
   3095       (if (eq exporter 'embark-collect)
   3096           (embark-collect)
   3097         (let* ((after embark-after-export-hook)
   3098                (cmd embark--command)
   3099                (name (embark--descriptive-buffer-name 'export))
   3100                (rerun (embark--rerun-function #'embark-export))
   3101                (buffer (save-excursion
   3102                          (funcall exporter candidates)
   3103                          (rename-buffer name t)
   3104                          (current-buffer))))
   3105           (embark--quit-and-run
   3106            (lambda ()
   3107              (pop-to-buffer buffer)
   3108              (setq embark--rerun-function rerun)
   3109              (use-local-map
   3110               (make-composed-keymap
   3111                '(keymap
   3112                  (remap keymap
   3113                         (revert-buffer . embark-rerun-collect-or-export)))
   3114                (current-local-map)))
   3115              (let ((embark-after-export-hook after)
   3116                    (embark--command cmd))
   3117                (run-hooks 'embark-after-export-hook)))))))))
   3118 
   3119 (defmacro embark--export-rename (buffer title &rest body)
   3120   "Run BODY and rename BUFFER to Embark export buffer with TITLE."
   3121   (declare (indent 2))
   3122   (let ((saved (make-symbol "saved")))
   3123     `(let ((,saved (embark-rename-buffer
   3124                     ,buffer " *Embark Saved*" t)))
   3125        ,@body
   3126        (set-buffer (embark-rename-buffer
   3127                     ,buffer ,(format "*Embark Export %s*" title) t))
   3128        (when ,saved (embark-rename-buffer ,saved ,buffer)))))
   3129 
   3130 (defun embark--export-customize (items type pred)
   3131   "Create a customization buffer listing ITEMS.
   3132 TYPE is the items type.
   3133 PRED is a predicate function used to filter the items."
   3134   (custom-buffer-create
   3135    (cl-loop for item in items
   3136             for sym = (intern-soft item)
   3137             when (and sym (funcall pred sym)) collect `(,sym ,type))))
   3138 
   3139 (autoload 'apropos-parse-pattern "apropos")
   3140 (autoload 'apropos-symbols-internal "apropos")
   3141 (defun embark-export-apropos (symbols)
   3142   "Create apropos buffer listing SYMBOLS."
   3143   (embark--export-rename "*Apropos*" "Apropos"
   3144     (apropos-parse-pattern "") ;; Initialize apropos pattern
   3145     ;; HACK: Ensure that order of exported symbols is kept.
   3146     (cl-letf (((symbol-function #'sort) (lambda (list _pred) (nreverse list))))
   3147       (apropos-symbols-internal
   3148        (delq nil (mapcar #'intern-soft symbols))
   3149        (bound-and-true-p apropos-do-all)))))
   3150 
   3151 (defun embark-export-customize-face (faces)
   3152   "Create a customization buffer listing FACES."
   3153   (embark--export-customize faces 'custom-face #'facep))
   3154 
   3155 (defun embark-export-customize-variable (variables)
   3156   "Create a customization buffer listing VARIABLES."
   3157   ;; The widget library serializes/deserializes the values. We advise
   3158   ;; the serialization in order to avoid errors for nonserializable
   3159   ;; variables.
   3160   (cl-letf* ((ht (make-hash-table :test #'equal))
   3161              (orig-read (symbol-function #'read))
   3162              (orig-write (symbol-function 'widget-sexp-value-to-internal))
   3163              ((symbol-function #'read)
   3164               (lambda (&optional str)
   3165                 (condition-case nil
   3166                     (funcall orig-read str)
   3167                   (error (gethash str ht)))))
   3168              ((symbol-function 'widget-sexp-value-to-internal)
   3169               (lambda (widget val)
   3170                 (let ((str (funcall orig-write widget val)))
   3171                   (puthash str val ht)
   3172                   str))))
   3173     (embark--export-customize variables 'custom-variable #'boundp)))
   3174 
   3175 (defun embark-export-ibuffer (buffers)
   3176   "Create an ibuffer buffer listing BUFFERS."
   3177   (ibuffer t "*Embark Export Ibuffer*"
   3178            `((predicate . (member (buffer-name) ',buffers)))))
   3179 
   3180 (autoload 'dired-check-switches "dired")
   3181 (declare-function dired-unadvertise "dired")
   3182 (defvar dired-directory)
   3183 
   3184 (defun embark-export-dired (files)
   3185   "Create a Dired buffer listing FILES."
   3186   (setq files (mapcar #'directory-file-name
   3187                       (cl-remove-if-not #'file-exists-p files)))
   3188   (when (dired-check-switches dired-listing-switches "A" "almost-all")
   3189     (setq files (cl-remove-if
   3190                  (lambda (path)
   3191                    (let ((file (file-name-nondirectory path)))
   3192                      (or (string= file ".") (string= file ".."))))
   3193                  files)))
   3194   (let* ((dir (or (file-name-directory (try-completion "" files)) ""))
   3195          (buf (dired-noselect
   3196                (cons (expand-file-name dir)
   3197                      (mapcar (lambda (file) (string-remove-prefix dir file))
   3198                              files)))))
   3199     ;; unadvertise this buffer to avoid reuse
   3200     (with-current-buffer buf
   3201       (dired-unadvertise (car dired-directory)) ; avoid reuse of this buffer
   3202       (rename-buffer (format "*Embark Export Dired %s*" default-directory)))
   3203     (pop-to-buffer buf)))
   3204 
   3205 (autoload 'package-menu-mode "package")
   3206 (autoload 'package-menu--generate "package")
   3207 
   3208 (defun embark-export-list-packages (packages)
   3209   "Create a package menu mode buffer listing PACKAGES."
   3210   (let ((buf (generate-new-buffer "*Embark Export Packages*")))
   3211     (with-current-buffer buf
   3212       (package-menu-mode)
   3213       (package-menu--generate nil (mapcar #'intern packages)))
   3214     (pop-to-buffer buf)))
   3215 
   3216 (defvar bookmark-alist)
   3217 
   3218 (defun embark-export-bookmarks (bookmarks)
   3219   "Create a `bookmark-bmenu-mode' buffer listing BOOKMARKS."
   3220   (embark--export-rename "*Bookmark List*" "Bookmarks"
   3221     (let ((bookmark-alist
   3222            (cl-remove-if-not
   3223             (lambda (bmark)
   3224               (member (car bmark) bookmarks))
   3225             bookmark-alist)))
   3226       (bookmark-bmenu-list))))
   3227 
   3228 ;;; Multiple target selection
   3229 
   3230 (defface embark-selected '((t (:inherit match)))
   3231   "Face for selected candidates.")
   3232 
   3233 (defvar-local embark--selection nil
   3234   "Buffer local list of selected targets.
   3235 Add or remove elements to this list using the `embark-select'
   3236 action.")
   3237 
   3238 (cl-defun embark--select
   3239     (&key orig-target orig-type bounds &allow-other-keys)
   3240   "Add or remove ORIG-TARGET of given ORIG-TYPE to the selection.
   3241 If BOUNDS are given, also highlight the target when selecting it."
   3242   (cl-flet ((multi-type (x) (car (get-text-property 0 'multi-category x))))
   3243     (if-let* ((existing (seq-find
   3244                          (pcase-lambda (`(,cand . ,ov))
   3245                            (and
   3246                             (equal cand orig-target)
   3247                             (if (and bounds ov)
   3248                                 (and (= (car bounds) (overlay-start ov))
   3249                                      (= (cdr bounds) (overlay-end ov)))
   3250                               (let ((cand-type (multi-type cand)))
   3251                                 (or (eq cand-type orig-type)
   3252                                     (eq cand-type (multi-type orig-target)))))))
   3253                          embark--selection)))
   3254         (progn
   3255           (when (cdr existing) (delete-overlay (cdr existing)))
   3256           (setq embark--selection (delq existing embark--selection)))
   3257       (let ((target (copy-sequence orig-target)) overlay)
   3258         (when bounds
   3259           (setq overlay (make-overlay (car bounds) (cdr bounds)))
   3260           (overlay-put overlay 'face 'embark-selected)
   3261           (overlay-put overlay 'priority 1001))
   3262         (add-text-properties 0 (length orig-target)
   3263                              `(multi-category ,(cons orig-type orig-target))
   3264                              target)
   3265         (push (cons target overlay) embark--selection)))))
   3266 
   3267 (defalias 'embark-select #'ignore
   3268   "Add or remove the target from the current buffer's selection.
   3269 You can act on all selected targets at once with `embark-act-all'.")
   3270 
   3271 (defun embark-selected-candidates ()
   3272   "Return currently selected candidates in the buffer."
   3273   (when embark--selection
   3274     (cl-flet ((unwrap (x) (get-text-property 0 'multi-category x)))
   3275       (let* ((first-type (car (unwrap (caar embark--selection))))
   3276              (same (cl-every (lambda (item)
   3277                                (eq (car (unwrap (car item))) first-type))
   3278                              embark--selection))
   3279              (extract (if same
   3280                           (pcase-lambda (`(,cand . ,overlay))
   3281                             (cons (cdr (unwrap cand)) overlay))
   3282                         #'identity)))
   3283         (cons
   3284          (if same first-type 'multi-category)
   3285          (nreverse
   3286           (mapcar
   3287            (lambda (item)
   3288              (pcase-let ((`(,cand . ,ov) (funcall extract item)))
   3289                (if ov `(,cand ,(overlay-start ov) . ,(overlay-end ov)) cand)))
   3290            embark--selection)))))))
   3291 
   3292 ;;; Integration with external packages, mostly completion UIs
   3293 
   3294 ;; marginalia
   3295 
   3296 ;; Ensure that the Marginalia cache is reset, such that
   3297 ;; `embark-toggle-variable-value' updates the display (See #540).
   3298 (with-eval-after-load 'marginalia
   3299   (push 'marginalia--cache-reset (alist-get :always embark-post-action-hooks)))
   3300 
   3301 ;; vertico
   3302 
   3303 (declare-function vertico--candidate "ext:vertico")
   3304 (declare-function vertico--update "ext:vertico")
   3305 (declare-function vertico--remove-face "ext:vertico")
   3306 (defvar vertico--input)
   3307 (defvar vertico--candidates)
   3308 (defvar vertico--base)
   3309 
   3310 (defun embark--vertico-selected ()
   3311   "Target the currently selected item in Vertico.
   3312 Return the category metadatum as the type of the target."
   3313   (when vertico--input
   3314     ;; Force candidate computation, if candidates are not yet available.
   3315     (vertico--update)
   3316     (cons (completion-metadata-get (embark--metadata) 'category)
   3317           (vertico--candidate))))
   3318 
   3319 (defun embark--vertico-candidates ()
   3320   "Collect the current Vertico candidates.
   3321 Return the category metadatum as the type of the candidates."
   3322   (when vertico--input
   3323     ;; Force candidate computation, if candidates are not yet available.
   3324     (vertico--update)
   3325     (cons (completion-metadata-get (embark--metadata) 'category)
   3326           vertico--candidates)))
   3327 
   3328 (defun embark--vertico-indicator ()
   3329   "Embark indicator highlighting the current Vertico candidate."
   3330   (let ((fr face-remapping-alist))
   3331     (lambda (&optional keymap _targets _prefix)
   3332       (when vertico--input
   3333         (setq-local face-remapping-alist
   3334                     (if keymap
   3335                         (cons '(vertico-current . embark-target) fr)
   3336                       fr))))))
   3337 
   3338 (with-eval-after-load 'vertico
   3339   (cl-defmethod vertico--format-candidate
   3340     :around (cand prefix suffix index start &context (embark--selection cons))
   3341     (when (cl-find (concat vertico--base (nth index vertico--candidates))
   3342                    embark--selection
   3343                    :test #'equal :key #'car)
   3344       (setq cand (copy-sequence cand))
   3345       (add-face-text-property 0 (length cand) 'embark-selected t cand))
   3346     (cl-call-next-method cand prefix suffix index start))
   3347   (add-hook 'embark-indicators #'embark--vertico-indicator)
   3348   (add-hook 'embark-target-finders #'embark--vertico-selected)
   3349   (add-hook 'embark-candidate-collectors #'embark--vertico-candidates)
   3350   (remove-hook 'embark-candidate-collectors #'embark-selected-candidates)
   3351   (add-hook 'embark-candidate-collectors #'embark-selected-candidates))
   3352 
   3353 ;; ivy
   3354 
   3355 (declare-function ivy--expand-file-name "ext:ivy")
   3356 (declare-function ivy-state-current "ext:ivy")
   3357 (defvar ivy-text)
   3358 (defvar ivy-last)
   3359 (defvar ivy--old-cands) ; this stores the current candidates :)
   3360 (defvar ivy--length)
   3361 
   3362 (defun embark--ivy-selected ()
   3363   "Target the currently selected item in Ivy.
   3364 Return the category metadatum as the type of the target."
   3365   ;; my favorite way of detecting Ivy
   3366   (when (memq 'ivy--queue-exhibit post-command-hook)
   3367     (cons
   3368      (completion-metadata-get (embark--metadata) 'category)
   3369      (ivy--expand-file-name
   3370       (if (and (> ivy--length 0)
   3371                (stringp (ivy-state-current ivy-last)))
   3372           (ivy-state-current ivy-last)
   3373         ivy-text)))))
   3374 
   3375 (defun embark--ivy-candidates ()
   3376   "Return all current Ivy candidates."
   3377   ;; my favorite way of detecting Ivy
   3378   (when (memq 'ivy--queue-exhibit post-command-hook)
   3379     (cons
   3380      ;; swiper-isearch uses swiper-isearch-function as a completion
   3381      ;; table, but it doesn't understand metadata queries
   3382      (ignore-errors
   3383        (completion-metadata-get (embark--metadata) 'category))
   3384      ivy--old-cands)))
   3385 
   3386 (with-eval-after-load 'ivy
   3387   (add-hook 'embark-target-finders #'embark--ivy-selected)
   3388   (add-hook 'embark-candidate-collectors #'embark--ivy-candidates)
   3389   (remove-hook 'embark-candidate-collectors #'embark-selected-candidates)
   3390   (add-hook 'embark-candidate-collectors #'embark-selected-candidates))
   3391 
   3392 ;;; Custom actions
   3393 
   3394 (defvar embark-separator-history nil
   3395   "Input history for the separators used by some embark commands.
   3396 The commands that prompt for a string separator are
   3397 `embark-insert' and `embark-copy-as-kill'.")
   3398 
   3399 (defun embark-keymap-help ()
   3400   "Prompt for an action to perform or command to become and run it."
   3401   (interactive)
   3402   (user-error "Not meant to be called directly"))
   3403 
   3404 (defun embark-toggle-quit ()
   3405   "Toggle whether the following action quits the minibuffer."
   3406   (interactive)
   3407   (when (minibufferp)
   3408     (setq embark--toggle-quit (not embark--toggle-quit))
   3409     (if (consp embark-quit-after-action)
   3410         (message "Will %sobey embark-quit-after-action."
   3411                  (if embark--toggle-quit "dis" ""))
   3412       (message
   3413        "Will %squit minibuffer after action"
   3414        (if (eq embark--toggle-quit embark-quit-after-action) "not " "")))))
   3415 
   3416 (defun embark--separator (strings)
   3417   "Return a separator to join the STRINGS together.
   3418 With a prefix argument, prompt the user (unless STRINGS has 0 or
   3419 1 elements, in which case a separator is not needed)."
   3420   (if (and current-prefix-arg (cdr strings))
   3421       (read-string "Separator: " nil 'embark-separator-history)
   3422     "\n"))
   3423 
   3424 (defun embark-copy-as-kill (strings)
   3425   "Join STRINGS and save on the `kill-ring'.
   3426 With a prefix argument, prompt for the separator to join the
   3427 STRINGS, which defaults to a newline."
   3428   (kill-new (string-join strings (embark--separator strings))))
   3429 
   3430 (defun embark-insert (strings)
   3431   "Join STRINGS and insert the result at point.
   3432 With a prefix argument, prompt for the separator to join the
   3433 STRINGS, which defaults to a newline.
   3434 
   3435 Some whitespace is also inserted if necessary to avoid having the
   3436 inserted string blend into the existing buffer text.  More
   3437 precisely:
   3438 
   3439 1. If the inserted string does not contain newlines, a space may
   3440 be added before or after it as needed to avoid inserting a word
   3441 constituent character next to an existing word constituent.
   3442 
   3443 2. For a multiline inserted string, newlines may be added before
   3444 or after as needed to ensure the inserted string is on lines of
   3445 its own."
   3446   (let ((multiline (seq-some (lambda (s) (string-match-p "\n" s)) strings))
   3447         (separator (embark--separator strings)))
   3448     (cl-labels ((maybe-space ()
   3449                   (and (looking-at "\\w") (looking-back "\\w" 1)
   3450                        (insert " ")))
   3451                 (maybe-newline ()
   3452                   (or (looking-back "^[ \t]*" 40) (looking-at "\n\n")
   3453                       (newline-and-indent)))
   3454                 (maybe-whitespace ()
   3455                   (if multiline (maybe-newline) (maybe-space)))
   3456                 (ins-string ()
   3457                   (let ((start (point)))
   3458                     (insert (string-join strings separator))
   3459                     (save-excursion (goto-char start) (maybe-whitespace))
   3460                     (when (looking-back "\n" 1) (delete-char -1))
   3461                     (save-excursion (maybe-whitespace)))))
   3462       (if buffer-read-only
   3463           (with-selected-window (other-window-for-scrolling)
   3464             (ins-string))
   3465         (ins-string)))))
   3466 
   3467 ;; For Emacs 28 dired-jump will be moved to dired.el, but it seems
   3468 ;; that since it already has an autoload in Emacs 28, this next
   3469 ;; autoload is ignored.
   3470 (autoload 'dired-jump "dired-x" nil t)
   3471 
   3472 (defun embark-dired-jump (file &optional other-window)
   3473   "Open Dired buffer in directory containing FILE and move to its line.
   3474 When called with a prefix argument OTHER-WINDOW, open Dired in other window."
   3475   (interactive "fJump to Dired file: \nP")
   3476   (dired-jump other-window file))
   3477 
   3478 (defun embark--read-from-history (prompt candidates &optional category)
   3479   "Read with completion from list of history CANDIDATES of CATEGORY.
   3480 Sorting and history are disabled.  PROMPT is the prompt message."
   3481   (completing-read prompt
   3482                    (embark--with-category category candidates)
   3483                    nil t nil t))
   3484 
   3485 (defun embark-kill-ring-remove (text)
   3486   "Remove TEXT from `kill-ring'."
   3487   (interactive (list (embark--read-from-history
   3488                       "Remove from kill-ring: " kill-ring 'kill-ring)))
   3489   (embark-history-remove text)
   3490   (setq kill-ring (delete text kill-ring)))
   3491 
   3492 (defvar recentf-list)
   3493 (defun embark-recentf-remove (file)
   3494   "Remove FILE from the list of recent files."
   3495   (interactive (list (embark--read-from-history
   3496                       "Remove recent file: " recentf-list 'file)))
   3497   (embark-history-remove (expand-file-name file))
   3498   (embark-history-remove (abbreviate-file-name file))
   3499   (when (and (boundp 'recentf-list) (fboundp 'recentf-expand-file-name))
   3500     (setq recentf-list (delete (recentf-expand-file-name file) recentf-list))))
   3501 
   3502 (defun embark-history-remove (str)
   3503   "Remove STR from `minibuffer-history-variable'.
   3504 Many completion UIs sort by history position.  This command can be used
   3505 to remove entries from the history, such that they are not sorted closer
   3506 to the top."
   3507   (interactive (list (embark--read-from-history
   3508                       "Remove history item: "
   3509                       (if (eq minibuffer-history-variable t)
   3510                           (user-error "No minibuffer history")
   3511                         (symbol-value minibuffer-history-variable)))))
   3512   (unless (eq minibuffer-history-variable t)
   3513     (set minibuffer-history-variable
   3514          (delete str (symbol-value minibuffer-history-variable)))))
   3515 
   3516 (defvar xref-backend-functions)
   3517 
   3518 (defun embark-find-definition (symbol)
   3519   "Find definition of Emacs Lisp SYMBOL."
   3520   (interactive "sSymbol: ")
   3521   (let ((xref-backend-functions (lambda () 'elisp)))
   3522     (xref-find-definitions symbol)))
   3523 
   3524 (defun embark-info-lookup-symbol (symbol)
   3525   "Display the definition of SYMBOL, from the Elisp manual."
   3526   (interactive "SSymbol: ")
   3527   (info-lookup-symbol symbol 'emacs-lisp-mode))
   3528 
   3529 (defun embark-rename-buffer (buffer newname &optional unique)
   3530   "Rename BUFFER to NEWNAME, optionally making it UNIQUE.
   3531 Interactively, you can set UNIQUE with a prefix argument.
   3532 Returns the new name actually used."
   3533   (interactive "bBuffer: \nBRename %s to: \nP")
   3534   (when-let ((buf (get-buffer buffer)))
   3535     (with-current-buffer buf
   3536       (rename-buffer newname unique))))
   3537 
   3538 (defun embark--package-url (pkg)
   3539   "Return homepage for package PKG."
   3540   (when-let (desc (embark--package-desc pkg))
   3541     (alist-get :url (package-desc-extras desc))))
   3542 
   3543 (defun embark--prompt-for-package ()
   3544   "Prompt user for a package name."
   3545   ;; this code is taken from the interactive spec of describe-package
   3546   (unless package--initialized
   3547     (package-initialize t))
   3548   (intern
   3549    (completing-read "Package: "
   3550                     (append (mapcar #'car package-alist)
   3551                             (mapcar #'car package-archive-contents)
   3552                             (mapcar #'car package--builtins)))))
   3553 
   3554 (defun embark-browse-package-url (pkg)
   3555   "Open homepage for package PKG with `browse-url'."
   3556   (interactive (list (embark--prompt-for-package)))
   3557   (if-let ((url (embark--package-url pkg)))
   3558       (browse-url url)
   3559     (user-error "No homepage found for `%s'" pkg)))
   3560 
   3561 (defun embark-save-package-url (pkg)
   3562   "Save URL of homepage for package PKG on the `kill-ring'."
   3563   (interactive (list (embark--prompt-for-package)))
   3564   (if-let ((url (embark--package-url pkg)))
   3565       (kill-new url)
   3566     (user-error "No homepage found for `%s'" pkg)))
   3567 
   3568 (defun embark-save-variable-value (var)
   3569   "Save value of VAR in the `kill-ring'."
   3570   (interactive "SVariable: ")
   3571   (kill-new (string-trim (pp-to-string (symbol-value var)))))
   3572 
   3573 (defun embark-insert-variable-value (var)
   3574   "Insert value of VAR."
   3575   (interactive "SVariable: ")
   3576   (insert (string-trim (pp-to-string (symbol-value var)))))
   3577 
   3578 (defun embark-toggle-variable (var &optional local)
   3579   "Toggle value of boolean variable VAR.
   3580 If prefix LOCAL is non-nil make variable local."
   3581   (interactive "SVariable: \nP")
   3582   (let ((val (symbol-value var)))
   3583     (unless (memq val '(nil t))
   3584       (user-error "Not a boolean variable"))
   3585     (when local
   3586       (make-local-variable var))
   3587     (funcall (or (get var 'custom-set) 'set) var (not val))))
   3588 
   3589 (defun embark-insert-relative-path (file)
   3590   "Insert relative path to FILE.
   3591 The insert path is relative to `default-directory'."
   3592   (interactive "FFile: ")
   3593   (insert (file-relative-name (substitute-in-file-name file))))
   3594 
   3595 (defun embark-save-relative-path (file)
   3596   "Save the relative path to FILE in the kill ring.
   3597 The insert path is relative to `default-directory'."
   3598   (interactive "FFile: ")
   3599   (kill-new (file-relative-name (substitute-in-file-name file))))
   3600 
   3601 (defun embark-shell-command-on-buffer (buffer command &optional replace)
   3602   "Run shell COMMAND on contents of BUFFER.
   3603 Called with \\[universal-argument], replace contents of buffer
   3604 with command output.  For replacement behavior see
   3605 `shell-command-dont-erase-buffer' setting."
   3606   (interactive
   3607    (list
   3608     (read-buffer "Buffer: " nil t)
   3609     (read-shell-command "Shell command: ")
   3610     current-prefix-arg))
   3611   (with-current-buffer buffer
   3612     (shell-command-on-region (point-min) (point-max)
   3613                              command
   3614                              (and replace (current-buffer)))))
   3615 
   3616 (defun embark-open-externally (file)
   3617   "Open FILE using system's default application."
   3618   (interactive "fOpen: ")
   3619   (if (and (eq system-type 'windows-nt)
   3620            (fboundp 'w32-shell-execute))
   3621       (w32-shell-execute "open" file)
   3622     (call-process (pcase system-type
   3623                     ('darwin "open")
   3624                     ('cygwin "cygstart")
   3625                     (_ "xdg-open"))
   3626                   nil 0 nil
   3627                   (expand-file-name file))))
   3628 
   3629 (defun embark-bury-buffer (buf)
   3630   "Bury buffer BUF."
   3631   (interactive "bBuffer: ")
   3632   (if-let (win (get-buffer-window buf))
   3633       (with-selected-window win
   3634         (bury-buffer))
   3635     (bury-buffer)))
   3636 
   3637 (defun embark-kill-buffer-and-window (buf)
   3638   "Kill buffer BUF and delete its window."
   3639   (interactive "bBuffer: ")
   3640   (when-let (buf (get-buffer buf))
   3641     (if-let (win (get-buffer-window buf))
   3642         (with-selected-window win
   3643           (kill-buffer-and-window))
   3644       (kill-buffer buf))))
   3645 
   3646 (defun embark-save-unicode-character (char)
   3647   "Save Unicode character CHAR to kill ring."
   3648   (interactive
   3649    (list (read-char-by-name "Insert character  (Unicode name or hex): ")))
   3650   (kill-new (format "%c" char)))
   3651 
   3652 (defun embark-isearch ()
   3653   "Prompt for string in the minibuffer and start isearch.
   3654 Unlike isearch, this command reads the string from the
   3655 minibuffer, which means it can be used as an Embark action."
   3656   (interactive)
   3657   (isearch-mode t)
   3658   (isearch-edit-string))
   3659 
   3660 (defun embark-toggle-highlight ()
   3661   "Toggle symbol highlighting using `highlight-symbol-at-point'."
   3662   (interactive)
   3663   (let ((regexp (find-tag-default-as-symbol-regexp))
   3664         (highlighted (cl-find-if #'boundp
   3665                                  '(hi-lock-interactive-lighters
   3666                                    hi-lock-interactive-patterns))))
   3667     (if (and highlighted (assoc regexp (symbol-value highlighted)))
   3668         (unhighlight-regexp regexp)
   3669       (highlight-symbol-at-point))))
   3670 
   3671 (defun embark-next-symbol ()
   3672   "Jump to next occurrence of symbol at point.
   3673 The search respects symbol boundaries."
   3674   (interactive)
   3675   (if-let ((symbol (thing-at-point 'symbol)))
   3676       (let ((regexp (format "\\_<%s\\_>" (regexp-quote symbol))))
   3677         (when (looking-at regexp)
   3678           (forward-symbol 1))
   3679         (unless (re-search-forward regexp nil t)
   3680           (user-error "Symbol `%s' not found" symbol)))
   3681     (user-error "No symbol at point")))
   3682 
   3683 (defun embark-previous-symbol ()
   3684   "Jump to previous occurrence of symbol at point.
   3685 The search respects symbol boundaries."
   3686   (interactive)
   3687   (if-let ((symbol (thing-at-point 'symbol)))
   3688       (let ((regexp (format "\\_<%s\\_>" (regexp-quote symbol))))
   3689         (when (looking-back regexp (- (point) (length symbol)))
   3690           (forward-symbol -1))
   3691         (unless (re-search-backward regexp nil t)
   3692           (user-error "Symbol `%s' not found" symbol)))
   3693     (user-error "No symbol at point")))
   3694 
   3695 (defun embark-compose-mail (address)
   3696   "Compose email to ADDRESS."
   3697   ;; The only reason we cannot use compose-mail directly is its
   3698   ;; interactive specification, which just supllies nil for the
   3699   ;; address (and several other arguments).
   3700   (interactive "sTo: ")
   3701   (compose-mail address))
   3702 
   3703 (autoload 'pp-display-expression "pp")
   3704 
   3705 (defun embark-pp-eval-defun (edebug)
   3706   "Run `eval-defun' and pretty print the result.
   3707 With a prefix argument EDEBUG, instrument the code for debugging."
   3708   (interactive "P")
   3709   (cl-letf (((symbol-function #'eval-expression-print-format)
   3710              (lambda (result)
   3711                (pp-display-expression result "*Pp Eval Output*"))))
   3712     (eval-defun edebug)))
   3713 
   3714 (defun embark-eval-replace ()
   3715   "Evaluate region and replace with evaluated result."
   3716   (interactive)
   3717   (let ((beg (region-beginning))
   3718         (end (region-end)))
   3719     (save-excursion
   3720       (goto-char end)
   3721       (insert (prin1-to-string
   3722                (eval (read (buffer-substring beg end)) lexical-binding)))
   3723       (delete-region beg end))))
   3724 
   3725 (when (< emacs-major-version 29)
   3726   (defun embark-elp-restore-package (prefix)
   3727     "Remove instrumentation from functions with names starting with PREFIX."
   3728     (interactive "SPrefix: ")
   3729     (when (fboundp 'elp-restore-list)
   3730       (elp-restore-list
   3731        (mapcar #'intern
   3732                (all-completions (symbol-name prefix)
   3733                                 obarray 'elp-profilable-p))))))
   3734 
   3735 (defmacro embark--define-hash (algorithm)
   3736   "Define command which computes hash from a string.
   3737 ALGORITHM is the hash algorithm symbol understood by `secure-hash'."
   3738   `(defun ,(intern (format "embark-hash-%s" algorithm)) (str)
   3739      ,(format "Compute %s hash of STR and store it in the kill ring." algorithm)
   3740      (interactive "sString: ")
   3741      (let ((hash (secure-hash ',algorithm str)))
   3742        (kill-new hash)
   3743        (message "%s: %s" ',algorithm hash))))
   3744 
   3745 (embark--define-hash md5)
   3746 (embark--define-hash sha1)
   3747 (embark--define-hash sha224)
   3748 (embark--define-hash sha256)
   3749 (embark--define-hash sha384)
   3750 (embark--define-hash sha512)
   3751 
   3752 (defun embark-encode-url (start end)
   3753   "Properly URI-encode the region between START and END in current buffer."
   3754   (interactive "r")
   3755   (let ((encoded (url-encode-url (buffer-substring-no-properties start end))))
   3756     (delete-region start end)
   3757     (insert encoded)))
   3758 
   3759 (defun embark-decode-url (start end)
   3760   "Decode the URI-encoded region between START and END in current buffer."
   3761   (interactive "r")
   3762   (let ((decoded (url-unhex-string (buffer-substring-no-properties start end))))
   3763     (delete-region start end)
   3764     (insert decoded)))
   3765 
   3766 (defvar epa-replace-original-text)
   3767 (defun embark-epa-decrypt-region (start end)
   3768   "Decrypt region between START and END."
   3769   (interactive "r")
   3770   (let ((epa-replace-original-text t))
   3771     (epa-decrypt-region start end)))
   3772 
   3773 (defvar eww-download-directory)
   3774 (autoload 'eww-download-callback "eww")
   3775 
   3776 (defun embark-download-url (url)
   3777   "Download URL to `eww-download-directory'."
   3778   (interactive "sDownload URL: ")
   3779   (let ((dir eww-download-directory))
   3780     (when (functionp dir) (setq dir (funcall dir)))
   3781     (access-file dir "Download failed")
   3782     (url-retrieve
   3783      url #'eww-download-callback
   3784      (if (>= emacs-major-version 28) (list url dir) (list url)))))
   3785 
   3786 ;;; Setup and pre-action hooks
   3787 
   3788 (defun embark--restart (&rest _)
   3789   "Restart current command with current input.
   3790 Use this to refresh the list of candidates for commands that do
   3791 not handle that themselves."
   3792   (when (minibufferp)
   3793     (embark--become-command embark--command (minibuffer-contents))))
   3794 
   3795 (defun embark--shell-prep (&rest _)
   3796   "Prepare target for use as argument for a shell command.
   3797 This quotes the spaces, inserts an extra space at the beginning
   3798 and leaves the point to the left of it."
   3799   (let ((contents (minibuffer-contents)))
   3800     (delete-minibuffer-contents)
   3801     (insert " " (shell-quote-wildcard-pattern contents))
   3802     (goto-char (minibuffer-prompt-end))))
   3803 
   3804 (defun embark--force-complete (&rest _)
   3805   "Select first minibuffer completion candidate matching target."
   3806   (minibuffer-force-complete))
   3807 
   3808 (cl-defun embark--eval-prep (&key type &allow-other-keys)
   3809   "If target's TYPE is: variable, skip edit; function, wrap in parens."
   3810   (when (memq type '(command function))
   3811     (embark--allow-edit)
   3812     (goto-char (minibuffer-prompt-end))
   3813     (insert "(")
   3814     (goto-char (point-max))
   3815     (insert ")")
   3816     (backward-char)))
   3817 
   3818 (cl-defun embark--beginning-of-target (&key bounds &allow-other-keys)
   3819   "Go to beginning of the target BOUNDS."
   3820   (when (number-or-marker-p bounds)
   3821     (goto-char (car bounds))))
   3822 
   3823 (cl-defun embark--end-of-target (&key bounds &allow-other-keys)
   3824   "Go to end of the target BOUNDS."
   3825   (when (number-or-marker-p bounds)
   3826     (goto-char (cdr bounds))))
   3827 
   3828 (cl-defun embark--mark-target (&rest rest &key run bounds &allow-other-keys)
   3829   "Mark the target if its BOUNDS are known.
   3830 After marking the target, this calls RUN with the REST of its arguments."
   3831   (cond
   3832    ((and bounds run)
   3833     (save-mark-and-excursion
   3834       (set-mark (cdr bounds))
   3835       (goto-char (car bounds))
   3836       (apply run :bounds bounds rest)))
   3837    (bounds ;; used as pre- or post-action hook
   3838     (set-mark (cdr bounds))
   3839     (goto-char (car bounds)))
   3840    (run (apply run rest))))
   3841 
   3842 (cl-defun embark--unmark-target (&rest _)
   3843   "Deactivate the region target."
   3844   (deactivate-mark t))
   3845 
   3846 (cl-defun embark--narrow-to-target
   3847     (&rest rest &key run bounds &allow-other-keys)
   3848   "Narrow buffer to target if its BOUNDS are known.
   3849 Intended for use as an Embark around-action hook.  This function
   3850 runs RUN with the buffer narrowed to given BOUNDS passing along
   3851 the REST of the arguments."
   3852   (if bounds
   3853     (save-excursion
   3854       (save-restriction
   3855         (narrow-to-region (car bounds) (cdr bounds))
   3856         (goto-char (car bounds))
   3857         (apply run :bounds bounds rest)))
   3858     (apply run rest)))
   3859 
   3860 (defun embark--allow-edit (&rest _)
   3861   "Allow editing the target."
   3862   (remove-hook 'post-command-hook #'exit-minibuffer t)
   3863   (remove-hook 'post-command-hook 'ivy-immediate-done t))
   3864 
   3865 (defun embark--ignore-target (&rest _)
   3866   "Ignore the target."
   3867   (let ((contents
   3868          (get-text-property (minibuffer-prompt-end) 'embark--initial-input)))
   3869     (delete-minibuffer-contents)
   3870     (when contents (insert contents)))
   3871   (embark--allow-edit))
   3872 
   3873 (autoload 'xref-push-marker-stack "xref")
   3874 (defun embark--xref-push-marker (&rest _)
   3875   "Push a marker onto the xref marker stack."
   3876   (xref-push-marker-stack))
   3877 
   3878 (cl-defun embark--confirm (&key action target &allow-other-keys)
   3879   "Ask for confirmation before running the ACTION on the TARGET."
   3880   (unless (y-or-n-p (format "Run %s on %s? " action target))
   3881     (user-error "Canceled")))
   3882 
   3883 (defun embark--associated-directory (target type)
   3884   "Return directory associated to TARGET of given TYPE.
   3885 The supported values of TYPE are file, buffer, bookmark and
   3886 library, which have an obvious notion of associated directory."
   3887   (pcase type
   3888     ('file
   3889      (file-name-directory target))
   3890     ('buffer
   3891      (buffer-local-value 'default-directory (get-buffer target)))
   3892     ('bookmark
   3893      (file-name-directory (bookmark-location target)))
   3894     ('library
   3895      (file-name-directory (locate-library target)))))
   3896 
   3897 (autoload 'bookmark-location "bookmark")
   3898 (cl-defun embark--cd (&rest rest &key run target type &allow-other-keys)
   3899   "Run action with `default-directory' set to the directory of TARGET.
   3900 The supported values of TYPE are file, buffer, bookmark and
   3901 library, which have an obvious notion of associated directory.
   3902 The REST of the arguments are also passed to RUN."
   3903   (let ((default-directory
   3904           (or (embark--associated-directory target type) default-directory)))
   3905     (apply run :target target :type type rest)))
   3906 
   3907 (cl-defun embark--save-excursion (&rest rest &key run &allow-other-keys)
   3908   "Run action without moving point.
   3909 This simply calls RUN with the REST of its arguments inside
   3910 `save-excursion'."
   3911   (save-excursion (apply run rest)))
   3912 
   3913 (defun embark--universal-argument (&rest _)
   3914   "Run action with a universal prefix argument."
   3915   (setq prefix-arg '(4)))
   3916 
   3917 ;;; keymaps
   3918 
   3919 (defvar-keymap embark-meta-map
   3920   :doc "Keymap for non-action Embark functions."
   3921   "-" #'negative-argument
   3922   "0" #'digit-argument
   3923   "1" #'digit-argument
   3924   "2" #'digit-argument
   3925   "3" #'digit-argument
   3926   "4" #'digit-argument
   3927   "5" #'digit-argument
   3928   "6" #'digit-argument
   3929   "7" #'digit-argument
   3930   "8" #'digit-argument
   3931   "9" #'digit-argument)
   3932 
   3933 (defvar-keymap embark-general-map
   3934   :doc "Keymap for Embark general actions."
   3935   :parent embark-meta-map
   3936   "i" #'embark-insert
   3937   "w" #'embark-copy-as-kill
   3938   "q" #'embark-toggle-quit
   3939   "E" #'embark-export
   3940   "S" #'embark-collect
   3941   "L" #'embark-live
   3942   "B" #'embark-become
   3943   "A" #'embark-act-all
   3944   "C-s" #'embark-isearch
   3945   "C-SPC" #'mark
   3946   "DEL" #'delete-region
   3947   "SPC" #'embark-select)
   3948 
   3949 (defvar-keymap embark-encode-map
   3950   :doc "Keymap for Embark region encoding actions."
   3951   "r" #'rot13-region
   3952   "." #'morse-region
   3953   "-" #'unmorse-region
   3954   "s" #'studlify-region
   3955   "m" #'embark-hash-md5
   3956   "1" #'embark-hash-sha1
   3957   "2" #'embark-hash-sha256
   3958   "3" #'embark-hash-sha384
   3959   "4" #'embark-hash-sha224
   3960   "5" #'embark-hash-sha512
   3961   "f" #'format-encode-region
   3962   "F" #'format-decode-region
   3963   "b" #'base64-encode-region
   3964   "B" #'base64-decode-region
   3965   "u" #'embark-encode-url
   3966   "U" #'embark-decode-url
   3967   "c" #'epa-encrypt-region
   3968   "C" #'embark-epa-decrypt-region)
   3969 
   3970 (fset 'embark-encode-map embark-encode-map)
   3971 
   3972 (defvar-keymap embark-sort-map
   3973   :doc "Keymap for Embark actions that sort the region"
   3974   "l" #'sort-lines
   3975   "P" #'sort-pages
   3976   "f" #'sort-fields
   3977   "c" #'sort-columns
   3978   "p" #'sort-paragraphs
   3979   "r" #'sort-regexp-fields
   3980   "n" #'sort-numeric-fields)
   3981 
   3982 (fset 'embark-sort-map embark-sort-map)
   3983 
   3984 ;; these will have autoloads in Emacs 28
   3985 (autoload 'calc-grab-sum-down "calc" nil t)
   3986 (autoload 'calc-grab-sum-across "calc" nil t)
   3987 
   3988 ;; this has had an autoload cookie since at least Emacs 26
   3989 ;; but that autoload doesn't seem to work for me
   3990 (autoload 'org-table-convert-region "org-table" nil t)
   3991 
   3992 (defvar-keymap embark-region-map
   3993   :doc "Keymap for Embark actions on the active region."
   3994   :parent embark-general-map
   3995   "u" #'upcase-region
   3996   "l" #'downcase-region
   3997   "c" #'capitalize-region
   3998   "|" #'shell-command-on-region
   3999   "e" #'eval-region
   4000   "<" #'embark-eval-replace
   4001   "a" #'align
   4002   "A" #'align-regexp
   4003   "i" #'indent-rigidly
   4004   "I" #'embark-insert
   4005   "TAB" #'indent-region
   4006   "f" #'fill-region
   4007   "p" #'fill-region-as-paragraph
   4008   "$" #'ispell-region
   4009   "=" #'count-words-region
   4010   "F" #'whitespace-cleanup-region
   4011   "t" #'transpose-regions
   4012   "o" #'org-table-convert-region
   4013   ";" #'comment-or-uncomment-region
   4014   "W" #'write-region
   4015   "+" #'append-to-file
   4016   "m" #'apply-macro-to-region-lines
   4017   "n" #'narrow-to-region
   4018   "*" #'calc-grab-region
   4019   ":" #'calc-grab-sum-down
   4020   "_" #'calc-grab-sum-across
   4021   "r" #'reverse-region
   4022   "d" #'delete-duplicate-lines
   4023   "b" #'browse-url-of-region
   4024   "h" #'shr-render-region
   4025   "'" #'expand-region-abbrevs
   4026   "v" #'vc-region-history
   4027   "R" #'repunctuate-sentences
   4028   "s" 'embark-sort-map
   4029   ">" 'embark-encode-map)
   4030 
   4031 (defvar-keymap embark-vc-file-map
   4032   :doc "Keymap for Embark VC file actions."
   4033   "d" #'vc-delete-file
   4034   "r" #'vc-rename-file
   4035   "i" #'vc-ignore)
   4036 
   4037 (fset 'embark-vc-file-map embark-vc-file-map)
   4038 
   4039 (defvar-keymap embark-file-map
   4040   :doc "Keymap for Embark file actions."
   4041   :parent embark-general-map
   4042   "RET" #'find-file
   4043   "f" #'find-file
   4044   "F" #'find-file-literally
   4045   "o" #'find-file-other-window
   4046   "d" #'delete-file
   4047   "D" #'delete-directory
   4048   "r" #'rename-file
   4049   "c" #'copy-file
   4050   "j" #'embark-dired-jump
   4051   "!" #'shell-command
   4052   "&" #'async-shell-command
   4053   "$" #'eshell
   4054   "<" #'insert-file
   4055   "m" #'chmod
   4056   "=" #'ediff-files
   4057   "+" #'make-directory
   4058   "\\" #'embark-recentf-remove
   4059   "I" #'embark-insert-relative-path
   4060   "W" #'embark-save-relative-path
   4061   "x" #'embark-open-externally
   4062   "e" #'eww-open-file
   4063   "l" #'load-file
   4064   "b" #'byte-compile-file
   4065   "R" #'byte-recompile-directory
   4066   "v" 'embark-vc-file-map)
   4067 
   4068 (defvar-keymap embark-kill-ring-map
   4069   :doc "Keymap for `kill-ring' commands."
   4070   :parent embark-general-map
   4071   "\\" #'embark-kill-ring-remove)
   4072 
   4073 (defvar-keymap embark-url-map
   4074   :doc "Keymap for Embark url actions."
   4075   :parent embark-general-map
   4076   "RET" #'browse-url
   4077   "b" #'browse-url
   4078   "d" #'embark-download-url
   4079   "e" #'eww)
   4080 
   4081 (defvar-keymap embark-email-map
   4082   :doc "Keymap for Embark email actions."
   4083   :parent embark-general-map
   4084   "RET" #'embark-compose-mail
   4085   "c" #'embark-compose-mail)
   4086 
   4087 (defvar-keymap embark-library-map
   4088   :doc "Keymap for operations on Emacs Lisp libraries."
   4089   :parent embark-general-map
   4090   "RET" #'find-library
   4091   "l" #'load-library
   4092   "f" #'find-library
   4093   "h" #'finder-commentary
   4094   "a" #'apropos-library
   4095   "L" #'locate-library
   4096   "m" #'info-display-manual
   4097   "$" #'eshell)
   4098 
   4099 (defvar-keymap embark-buffer-map
   4100   :doc "Keymap for Embark buffer actions."
   4101   :parent embark-general-map
   4102   "RET" #'switch-to-buffer
   4103   "k" #'kill-buffer
   4104   "b" #'switch-to-buffer
   4105   "o" #'switch-to-buffer-other-window
   4106   "z" #'embark-bury-buffer
   4107   "K" #'embark-kill-buffer-and-window
   4108   "r" #'embark-rename-buffer
   4109   "=" #'ediff-buffers
   4110   "|" #'embark-shell-command-on-buffer
   4111   "<" #'insert-buffer
   4112   "$" #'eshell)
   4113 
   4114 (defvar-keymap embark-tab-map
   4115   :doc "Keymap for actions for tab-bar tabs."
   4116   :parent embark-general-map
   4117   "RET" #'tab-bar-select-tab-by-name
   4118   "s" #'tab-bar-select-tab-by-name
   4119   "r" #'tab-bar-rename-tab-by-name
   4120   "k" #'tab-bar-close-tab-by-name)
   4121 
   4122 (defvar-keymap embark-identifier-map
   4123   :doc "Keymap for Embark identifier actions."
   4124   :parent embark-general-map
   4125   "RET" #'xref-find-definitions
   4126   "h" #'display-local-help
   4127   "H" #'embark-toggle-highlight
   4128   "d" #'xref-find-definitions
   4129   "r" #'xref-find-references
   4130   "a" #'xref-find-apropos
   4131   "s" #'info-lookup-symbol
   4132   "n" #'embark-next-symbol
   4133   "p" #'embark-previous-symbol
   4134   "'" #'expand-abbrev
   4135   "$" #'ispell-word
   4136   "o" #'occur)
   4137 
   4138 (defvar-keymap embark-expression-map
   4139   :doc "Keymap for Embark expression actions."
   4140   :parent embark-general-map
   4141   "RET" #'pp-eval-expression
   4142   "e" #'pp-eval-expression
   4143   "<" #'embark-eval-replace
   4144   "m" #'pp-macroexpand-expression
   4145   "TAB" #'indent-region
   4146   "r" #'raise-sexp
   4147   "t" #'transpose-sexps
   4148   "k" #'kill-region
   4149   "u" #'backward-up-list
   4150   "n" #'forward-list
   4151   "p" #'backward-list)
   4152 
   4153 (defvar-keymap embark-defun-map
   4154   :doc "Keymap for Embark defun actions."
   4155   :parent embark-expression-map
   4156   "RET" #'embark-pp-eval-defun
   4157   "e" #'embark-pp-eval-defun
   4158   "c" #'compile-defun
   4159   "l" #'elint-defun
   4160   "D" #'edebug-defun
   4161   "o" #'checkdoc-defun
   4162   "N" #'narrow-to-defun)
   4163 
   4164 ;; Use quoted symbols to avoid byte-compiler warnings.
   4165 (defvar-keymap embark-heading-map
   4166   :doc "Keymap for Embark heading actions."
   4167   :parent embark-general-map
   4168   "RET" 'outline-show-subtree
   4169   "TAB" 'outline-cycle ;; New in Emacs 28!
   4170   "C-SPC" 'outline-mark-subtree
   4171   "n" 'outline-next-visible-heading
   4172   "p" 'outline-previous-visible-heading
   4173   "f" 'outline-forward-same-level
   4174   "b" 'outline-backward-same-level
   4175   "^" 'outline-move-subtree-up
   4176   "v" 'outline-move-subtree-down
   4177   "u" 'outline-up-heading
   4178   "s" 'outline-show-subtree
   4179   "d" 'outline-hide-subtree
   4180   ">" 'outline-demote
   4181   "<" 'outline-promote)
   4182 
   4183 (defvar-keymap embark-symbol-map
   4184   :doc "Keymap for Embark symbol actions."
   4185   :parent embark-identifier-map
   4186   "RET" #'embark-find-definition
   4187   "h" #'describe-symbol
   4188   "s" #'embark-info-lookup-symbol
   4189   "d" #'embark-find-definition
   4190   "e" #'pp-eval-expression
   4191   "a" #'apropos
   4192   "\\" #'embark-history-remove)
   4193 
   4194 (defvar-keymap embark-face-map
   4195   :doc "Keymap for Embark face actions."
   4196   :parent embark-symbol-map
   4197   "h" #'describe-face
   4198   "c" #'customize-face
   4199   "+" #'make-face-bold
   4200   "-" #'make-face-unbold
   4201   "/" #'make-face-italic
   4202   "|" #'make-face-unitalic
   4203   "!" #'invert-face
   4204   "f" #'set-face-foreground
   4205   "b" #'set-face-background)
   4206 
   4207 (defvar-keymap embark-variable-map
   4208   :doc "Keymap for Embark variable actions."
   4209   :parent embark-symbol-map
   4210   "=" #'set-variable
   4211   "c" #'customize-set-variable
   4212   "u" #'customize-variable
   4213   "v" #'embark-save-variable-value
   4214   "<" #'embark-insert-variable-value
   4215   "t" #'embark-toggle-variable)
   4216 
   4217 (defvar-keymap embark-function-map
   4218   :doc "Keymap for Embark function actions."
   4219   :parent embark-symbol-map
   4220   "m" #'elp-instrument-function ;; m=measure
   4221   "M" 'elp-restore-function ;; quoted, not autoloaded
   4222   "k" #'debug-on-entry ;; breaKpoint (running out of letters, really)
   4223   "K" #'cancel-debug-on-entry
   4224   "t" #'trace-function
   4225   "T" 'untrace-function) ;; quoted, not autoloaded
   4226 
   4227 (defvar-keymap embark-command-map
   4228   :doc "Keymap for Embark command actions."
   4229   :parent embark-function-map
   4230   "x" #'execute-extended-command
   4231   "I" #'Info-goto-emacs-command-node
   4232   "b" #'where-is
   4233   "g" #'global-set-key
   4234   "l" #'local-set-key)
   4235 
   4236 (defvar-keymap embark-package-map
   4237   :doc "Keymap for Embark package actions."
   4238   :parent embark-general-map
   4239   "RET" #'describe-package
   4240   "h" #'describe-package
   4241   "i" #'package-install
   4242   "I" #'embark-insert
   4243   "d" #'package-delete
   4244   "r" #'package-reinstall
   4245   "u" #'embark-browse-package-url
   4246   "W" #'embark-save-package-url
   4247   "a" #'package-autoremove
   4248   "g" #'package-refresh-contents
   4249   "m" #'elp-instrument-package ;; m=measure
   4250   "M" (if (fboundp 'embark-elp-restore-package)
   4251         'embark-elp-restore-package
   4252         'elp-restore-package))
   4253 
   4254 (defvar-keymap embark-bookmark-map
   4255   :doc "Keymap for Embark bookmark actions."
   4256   :parent embark-general-map
   4257   "RET" #'bookmark-jump
   4258   "s" #'bookmark-set
   4259   "d" #'bookmark-delete
   4260   "r" #'bookmark-rename
   4261   "R" #'bookmark-relocate
   4262   "l" #'bookmark-locate
   4263   "<" #'bookmark-insert
   4264   "j" #'bookmark-jump
   4265   "o" #'bookmark-jump-other-window
   4266   "f" #'bookmark-jump-other-frame
   4267   "a" 'bookmark-show-annotation
   4268   "e" 'bookmark-edit-annotation
   4269   "$" #'eshell)
   4270 
   4271 (defvar-keymap embark-unicode-name-map
   4272   :doc "Keymap for Embark Unicode name actions."
   4273   :parent embark-general-map
   4274   "RET" #'insert-char
   4275   "I" #'insert-char
   4276   "W" #'embark-save-unicode-character)
   4277 
   4278 (defvar-keymap embark-prose-map
   4279   :doc "Keymap for Embark actions for dealing with prose."
   4280   :parent embark-general-map
   4281   "$" #'ispell-region
   4282   "f" #'fill-region
   4283   "u" #'upcase-region
   4284   "l" #'downcase-region
   4285   "c" #'capitalize-region
   4286   "F" #'whitespace-cleanup-region
   4287   "=" #'count-words-region)
   4288 
   4289 (defvar-keymap embark-sentence-map
   4290   :doc "Keymap for Embark actions for dealing with sentences."
   4291   :parent embark-prose-map
   4292   "t" #'transpose-sentences
   4293   "n" #'forward-sentence
   4294   "p" #'backward-sentence)
   4295 
   4296 (defvar-keymap embark-paragraph-map
   4297   :doc "Keymap for Embark actions for dealing with paragraphs."
   4298   :parent embark-prose-map
   4299   "t" #'transpose-paragraphs
   4300   "n" #'forward-paragraph
   4301   "p" #'backward-paragraph
   4302   "R" #'repunctuate-sentences)
   4303 
   4304 (defvar-keymap embark-become-help-map
   4305   :doc "Keymap for Embark help actions."
   4306   :parent embark-meta-map
   4307   "V" #'apropos-variable
   4308   "U" #'apropos-user-option
   4309   "C" #'apropos-command
   4310   "v" #'describe-variable
   4311   "f" #'describe-function
   4312   "s" #'describe-symbol
   4313   "F" #'describe-face
   4314   "p" #'describe-package
   4315   "i" #'describe-input-method)
   4316 
   4317 (autoload 'recentf-open-files "recentf" nil t)
   4318 
   4319 (defvar-keymap embark-become-file+buffer-map
   4320   :doc "Embark become keymap for files and buffers."
   4321   :parent embark-meta-map
   4322   "f" #'find-file
   4323   "4 f" #'find-file-other-window
   4324   "." #'find-file-at-point
   4325   "p" #'project-find-file
   4326   "r" #'recentf-open-files
   4327   "b" #'switch-to-buffer
   4328   "4 b" #'switch-to-buffer-other-window
   4329   "l" #'locate
   4330   "L" #'find-library
   4331   "v" #'vc-dir)
   4332 
   4333 (defvar-keymap embark-become-shell-command-map
   4334   :doc "Embark become keymap for shell commands."
   4335   :parent embark-meta-map
   4336   "!" #'shell-command
   4337   "&" #'async-shell-command
   4338   "c" #'comint-run
   4339   "t" #'term)
   4340 
   4341 (defvar-keymap embark-become-match-map
   4342   :doc "Embark become keymap for search."
   4343   :parent embark-meta-map
   4344   "o" #'occur
   4345   "k" #'keep-lines
   4346   "f" #'flush-lines
   4347   "c" #'count-matches)
   4348 
   4349 (provide 'embark)
   4350 
   4351 ;; Check that embark-consult is installed. If Embark is used in
   4352 ;; combination with Consult, you should install the integration package,
   4353 ;; such that features like embark-export from consult-grep work as
   4354 ;; expected.
   4355 
   4356 (with-eval-after-load 'consult
   4357   (unless (require 'embark-consult nil 'noerror)
   4358     (warn "The package embark-consult should be installed if you use both Embark and Consult")))
   4359 
   4360 (with-eval-after-load 'org
   4361   (require 'embark-org))
   4362 
   4363 ;;; embark.el ends here