Skip to content

I did not grok Embark for a long time #761

@MartinDrees

Description

@MartinDrees

I’ve been using Emacs for ~4 years and switched to the Vertico+Consult+Marginalia+Orderless+Embark stack about a year ago. The first four improved my workflows right away, but Embark took a long time to click. It seemed powerful but was overwhelming. I hadn’t used Helm or Ivy before, so I didn’t have a mental model for “actions on candidates.”

The main resources I leaned on were the README and Karthink's blog post. While both are excellent, they can be a bit much for beginners—due to information overload, lots of custom Emacs Lisp. The naming of Embark is in my opinion also quite suboptimal due to its complexity.

I’d like to share two applications of Embark that have no obvious replacement and helped me finally grok its power by demonstrating the generality of Embark by example.


1. Copy any file path to the kill ring

Use consult-fd to find a file, then run (embark-act)copy (w).

Here, Embark makes consult-fd more general. Now it is not just a file picker, but a selector for any file that can then be acted on. This pattern applies beyond consult-fd to many other sources.


2. Run a program on multiple files across directories

Say you want to run:

my-program file1 file2 file3 ...

…where the files are scattered across different subdirectories.

  • Use consult-fd to find and select the files
  • Run (embark-act)export (E) to export them to a Dired buffer
  • Mark the files as needed (manually, by regex, etc.), then run copy (w)
  • Call your shell program and paste the copied list as arguments

Alternatively:

  • Use (embark-act-all) (A)
  • Then C-u w to copy all candidates with a custom separator (e.g., " ")

If you often run the same program, you can define a custom function to run it on marked files in Dired:

(defun run-my-program ()
  "Call external program 'my-program' with all marked files in Dired.
If no files are marked, use the current file."
  (interactive)
  (let* ((files (dired-get-marked-files))
         (command (concat "my-program "
                          (mapconcat #'shell-quote-argument files " "))))
    (message "Running: %s" command)
    (let ((display-buffer-alist '(("\\*my-program\\*" . ((display-buffer-no-window))))))
      (async-shell-command command "*my-program*"))))

At first glance this has nothing to do with Embark—but Embark makes this kind of function more general by offering consistent entry points into buffers like dired.


Once I understood this general power that Embark enables, all the other features made more sense too. Especially contextual actions at point ("right-click"), and embark-bindings (C-h) as a scalable prefix-help.

For beginners, I recommend:

  • Start using embark-act (C-.)
  • Learn copy (w), export (E), and embark-bindings (C-h)
  • From there, you can explore more

Hope this helps others trying to grok Embark!

Thanks for building this fantastic tool!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions