Irreal: A Priestly View Of Emacs

Priests and other religious leaders of various persuasions have been known to use Emacs. It’s not common, of course, but Irreal has mentioned a couple of them—most recently Randy Ridenour—but in almost 16 years, I can’t remember more than two.

Until now. MykhailoKazarian is a priest in the Orthodox Church of Ukraine and is far from a casual Emacs users. Rather than using Emacs to write his sermons, papers, and keep church records, Father Mykhailo is an actual coder who’s worked with Pascal, Python, and Java.

Due to the current difficulties in the Ukraine, Father Mykhailo has had to work with less than ideal conditions, including poor Internet connections and—what some would call—under powered hardware. Through it all he’s been an Emacs user. He says he’s still an Emacs user in 2025 and has a long post on why.

One of the things you often hear about Emacs is that it’s bloated, needs a lot of memory, and won’t run reasonably on anything but the most powerful hardware. Put aside, for the moment, the history of Emacs that puts the lie to that claim, Father Mykhailo is running Emacs on a Raspberry Pi—sometimes, when conditions warrant, powered by an automobile battery—and still manages to enjoy the many benefit that Emacs offers.

Father Mykhailo’s post goes into a lot of detail on why he’s still using Emacs after 20 years and plans to keep on using it. Take a look at his post for a deeper dive.

-1:-- A Priestly View Of Emacs (Post Irreal)--L0--C0--2025-09-17T16:04:27.000Z

James Cherti: Emacs quick-fasd: Integrate Fasd for fast file and directory navigation

The quick-fasd Emacs package integrates the Fasd tool into the Emacs environment. Fasd is a command-line utility that provides fast access to frequently used files and directories.

After installing quick-fasd and enabling quick-fasd-mode:

  • All visited files and directories are automatically added to the Fasd database. (quick-fasd-mode registers hooks in find-file-hook and dired-mode-hook to add visited files and directories to the Fasd database automatically.)
  • The quick-fasd-find-path function prompts for input and presents candidates from the Fasd index. For example, recently accessed files can be opened, and frequently used directories can be visited without leaving Emacs.
  • When invoked from the minibuffer, quick-fasd-find-path appends the selected path, simplifying completion.

If this package improves the workflow, consider supporting the project by ⭐ starring quick-fasd.el on GitHub so that more Emacs users can benefit from it.

Requirements

  • The fasd command line tool.

Installation

  1. If you haven’t already done so, add MELPA repository to your Emacs configuration.
  2. Add the following code to your Emacs init file to install easysession from MELPA:
(use-package quick-fasd
  :ensure t
  :bind (("C-x C-d" . quick-fasd-find-path)
         :map minibuffer-local-completion-map
         ("C-x C-d" . quick-fasd-find-path))

  :config
  (quick-fasd-mode))

Links

-1:-- Emacs quick-fasd: Integrate Fasd for fast file and directory navigation (Post James Cherti)--L0--C0--2025-09-17T15:34:50.000Z

Sacha Chua: Getting a Google Docs draft ready for Mailchimp via Emacs and Org Mode

I've been volunteering to help with the Bike Brigade newsletter. I like that there are people who are out there helping improve food security by delivering food bank hampers to recipients. Collecting information for the newsletter also helps me feel more appreciation for the lively Toronto biking scene, even though I still can't make it out to most events. The general workflow is:

  1. collect info
  2. draft the newsletter somewhere other volunteers can give feedback on
  3. convert the newsletter to Mailchimp
  4. send a test message
  5. make any edits requested
  6. schedule the email campaign

We have the Mailchimp Essentials plan, so I can't just export HTML for the whole newsletter. Someday I should experiment with services that might let me generate the whole newsletter from Emacs. That would be neat. Anyway, with Mailchimp's block-based editor, at least I can paste in HTML code for the text/buttons. That way, I don't have to change colours or define links by hand.

The logistics volunteers coordinate via Slack, so a Slack Canvas seemed like a good way to draft the newsletter. I've previously written about my workflow for copying blocks from a Slack Canvas and then using Emacs to transform the rich text, including recolouring the links in the section with light text on a dark background. However, copying rich text from a Slack Canvas turned out to be unreliable. Sometimes it would copy what I wanted, and sometimes nothing would get copied. There was no way to export HTML from the Slack Canvas, either.

I switched to using Google Docs for the drafts. It was a little less convenient to add items from Slack messages and I couldn't easily right-click to download the images that I pasted in. It was more reliable in terms of copying, but only if I used xclip to save the clipboard into a file instead of trying to do the whole thing in memory.

I finally got to spend a little time automating a new workflow. This time I exported the Google Doc as a zip that had the HTML file and all the images in a subdirectory. The HTML source is not very pleasant to work with. It has lots of extra markup I don't need. Here's what an entry looks like:

2025-09-17_09-22-35.png
Figure 1: Exported HTML for an entry

Things I wanted to do with the HTML:

  • Remove the google.com/url redirection for the links. Mailchimp will add its own redirection for click-tracking, but at least the links can look simpler when I paste them in.
  • Remove all the extra classes and styles.
  • Turn [ call to action ] into fancier Mailchimp buttons.

Also, instead of transforming one block at a time, I decided to make an Org Mode document with all the different blocks I needed. That way, I could copy and paste things in quick succession.

Here's what the result looks like. It makes a table of contents, adds the sign-up block, and adds the different links and blocks I need to paste into Mailchimp.

2025-09-17_10-03-27.png
Figure 2: Screenshot of newsletter Org file with blocks for easy copying

I need to copy and paste the image filenames into the upload dialog on Mailchimp, so I use my custom Org Mode link type for copying to the clipboard. For the HTML code, I use #+begin_src html ... #+end_src instead of #+begin_export html ... #+end_export so that I can use Embark and embark-org to quickly copy the contents of the source block. (That doesn't work for export blocks yet.) I have C-. bound to embark-act, the source block is detected by the functions that embark-org.el added to embark-target-finders, and the c binding in embark-org-src-block-map calls embark-org-copy-block-contents. So all I need to do is C-. c in a block to copy its contents.

Here's the code to process the newsletter draft
(defun my-brigade-process-latest-newsletter-draft (date)
  "Create an Org file with the HTML for different blocks."
  (interactive (list (if current-prefix-arg (org-read-date nil t nil "Date: ")
                       (org-read-date nil t "+Sun"))))
  (when (stringp date) (setq date (date-to-time date)))
  (let ((default-directory "~/Downloads/newsletter")
        file
        dom
        sections)
    (call-process "unzip" nil nil nil "-o" (my-latest-file "~/Downloads" "\\.zip$"))
    (setq file (my-latest-file default-directory))
    (with-temp-buffer
      (insert-file-contents-literally file)
      (goto-char (point-min))
      (my-transform-html '(my-brigade-save-newsletter-images) (buffer-string))
      (setq dom (my-brigade-simplify-html (libxml-parse-html-region (point-min) (point-max))))
      (setq sections
            (my-html-group-by-tag
             'h1
             (dom-children
              (dom-by-tag
               dom'body)))))
    (with-current-buffer (get-buffer-create "*newsletter*")
      (erase-buffer)
      (org-mode)
      (insert
       (format-time-string "%B %-e, %Y" date) "\n"
       "* In this e-mail\n#+begin_src html\n"
       "<p>Hi Bike Brigaders! Here’s what's happening this week, with quick signup links. In this e-mail:</p>"
       (my-transform-html
        '(my-brigade-remove-meta-recursively
          my-brigade-just-headings)
        (copy-tree dom))
       "\n#+end_src\n\n")
      (insert "* Sign-up block\n\n#+begin_src html\n"
              (my-brigade-copy-signup-block date)
              "\n#+end_src\n\n")
      (dolist (sec '("Bike Brigade" "In our community"))
        (insert "* " sec "\n"
                (mapconcat
                 (lambda (group)
                   (let* ((item (apply 'dom-node 'div nil
                                       (append
                                        (list (dom-node 'h2 nil (car group)))
                                        (cdr group))))
                          (image (my-brigade-image (car group))))
                     (format "** %s\n\n%s\n%s\n\n#+begin_src html\n%s\n#+end_src\n\n"
                             (car group)
                             (if image (org-link-make-string (concat "copy:" image)) "")
                             (or (my-html-last-link-href item) "")
                             (my-transform-html
                              (delq nil
                                    (list
                                     'my-transform-html-remove-images
                                     'my-transform-html-remove-italics
                                     'my-brigade-simplify-html
                                     'my-brigade-format-buttons
                                     (when (string= sec "In our community")
                                       'my-brigade-recolor-recursively)))
                              item))))
                 (my-html-group-by-tag 'h2 (cdr (assoc sec sections 'string=)))
                 "")))
      (insert "* Other updates\n"
              (format "#+begin_src html\n%s\n#+end_src\n\n"
                      (my-transform-html
                       '(my-transform-html-remove-images
                         my-transform-html-remove-italics
                         my-brigade-simplify-html)
                       (car (cdr (assoc "Other updates" sections 'string=))))))
      (goto-char (point-min))
      (display-buffer (current-buffer)))))

(defun my-html-group-by-tag (tag dom-list)
  "Use TAG to divide DOM-LIST into sections. Return an alist of (section . children)."
  (let (section-name current-section results)
    (dolist (node dom-list)
      (if (and (eq (dom-tag node) tag)
               (not (string= (string-trim (dom-texts node)) "")))
          (progn
            (when current-section
              (push (cons section-name (nreverse current-section))  results)
              (setq current-section nil))
            (setq section-name (string-trim (dom-texts node))))
        (when section-name
          (push node current-section))))
    (when current-section
      (push (cons section-name (reverse current-section))  results)
      (setq current-section nil))
    (nreverse results)))

(defun my-html-last-link-href (node)
  "Return the last link HREF in NODE."
  (dom-attr (car (last (dom-by-tag node 'a))) 'href))

(defun my-brigade-image (heading)
  "Find the latest image related to HEADING."
  (car
   (nreverse
    (directory-files my-brigade-newsletter-images-directory
                        t (regexp-quote (my-brigade-newsletter-heading-to-image-file-name heading))))))

Some of the functions it uses are in my config, particularly the section on Transforming HTML clipboard contents with Emacs to smooth out Mailchimp annoyances: dates, images, comments, colours.

Along the way, I learned that svg-print is a good way to turn document object models back into HTML.

When I saw two more events and one additional link that I wanted to include, I was glad I already had this code sorted out. It made it easy to paste the images and details into the Google Doc, reformat it slightly, and get the info through the process so that it ended up in the newsletter with a usefully-named image and correctly-coloured links.

I think this is a good combination of Google Docs for getting other people's feedback and letting them edit, and Org Mode for keeping myself sane as I turn it into whatever Mailchimp wants.

My next step for improving this workflow might be to check out other e-mail providers in case I can get Emacs to make the whole template. That way, I don't have to keep switching between applications and using the mouse to duplicate blocks and edit the code.

This is part of my Emacs configuration.
View org source for this post

You can comment on Mastodon or e-mail me at sacha@sachachua.com.

-1:-- Getting a Google Docs draft ready for Mailchimp via Emacs and Org Mode (Post Sacha Chua)--L0--C0--2025-09-17T14:07:10.000Z

Irreal: Entering Dates In Calc With Org

Marcin Borkowski (mbork) has an interesting post on entering dates in Calc mode. The short version is that he often enters dates in Calc but it’s a painful exercise. He’d much rather enter them the same way you do in Org mode, which is intuitive and flexible. That flexibility comes at the cost of being complicated but that’s mostly because there are so many easy ways to specify a date.

Naturally, mbork wanted to be able to enter Calc dates in the user friendly Org mode way. That turns out to be surprisingly easy. After the boilerplate it’s just a couple of lines of code plus another line to bind a key sequence to the function in the Calc key map. Read mbork’s post to see what I mean about easy.

What struck me most about the post was his mention of org-read-date, which Org uses to read dates. It’s incredibly flexible and, as mbork shows, usable in non-Org contexts. Take a look at the doc string for org-read-date to see what I mean. Even though I spend a huge amount of time in Org mode and enter a lot of date/time stamps and even though I’ve read the documentation on entering dates in Org, I didn’t remember how powerful the function is. Take a look at the doc string to see all the ways you can specify dates.

This is just another example of Emacs’ extensibility. Mbork had a problem and was able to solve it by gluing together a couple of existing Emacs functions that nominally had nothing to do with each other.

-1:-- Entering Dates In Calc With Org (Post Irreal)--L0--C0--2025-09-16T16:31:09.000Z

Magnus: Listing buffers by tab using consult and bufferlo

I've gotten into the habit of using tabs, via tab-bar, to organise my buffers when I have multiple projects open at once. Each project has its own tab. There's nothing fancy here (yet), I simply open a new tab manually before opening a new project.

A while ago I added bufferlo to my config to help with getting consult-buffer to organise buffers (somewhat) by tab. I copied the configuration from the bufferlo README and started using it. It took me a little while to notice that the behaviour wasn't quite what I wanted. It seemed like one buffer "leaked" from another tab.

2025-09-16-buffer-leakage.png
Figure 1: Example of buffer leakage

In the image above all files in ~/.emacs.d should be listed under Other Buffers, but one has been brought over into the tab for the Sider project.

After a bit of experimenting I realised that

  1. the buffer that leaks is the one I'm in when creating the new tab, and
  2. my function for creating a new tab doesn't work the way I thought.

My function for creating a new tab looked like this

(lambda ()
  (interactive)
  (tab-new)
  (dashboard-open))

and it turns out that tab-new shows the current buffer in the new tab which in turn caused bufferlo to associate it to the wrong tab. From what I can see there's no way to tell tab-new to open a specific buffer in the newly created tab. I tried the following

(lambda ()
  (interactive)
  (with-current-buffer dashboard-buffer-name
    (tab-new)))

hoping that the dashboard would open in the new tab. It didn't, it was still the active buffer that popped up in the new tab.

In the end I resorted to use bufferlo-remove to simply remove the current buffer from the new tab.

(lambda ()
  (interactive)
  (tab-new)
  (bufferlo-remove (current-buffer))
  (dashboard-open))

No more leakage and consult-buffer works like I wanted it to.

-1:-- Listing buffers by tab using consult and bufferlo (Post Magnus)--L0--C0--2025-09-16T06:29:00.000Z

George Huebner: Speedier elisp-refs-* with Dumb Grep

Helpful is a fantastic Emacs package that drastically improves the builtin help-mode. One of the particularly nice features is finding references to a particular symbol. Unfortunately it can be painfully slow in practice due to actually parsing every loaded Elisp file:

Emacs Lisp
(require 'benchmark)
(benchmark-elapse (elisp-refs-function #'car))
24.001221

Instead of walking the ASTs of every file, why not do a regex search?

It sacrifices correctness (and completely ignores the type of the symbol), but it turns out to be orders of magnitude faster in practice. Bonus points for using a fast tool like ripgrep and extra bonus points for completing the work asynchronously so as not to block Emacs’s main thread.

I don’t mean to denigrate elisp-refs; the author clearly has put a lot of thought into performance and it’s only natural that using an approach that heavily cuts corners together with a tool implemented in optimized machine code instead of Elisp (which is especially hampered by GC performance) will lead to faster results.

I’m a ripgrep junkie and I prefer it for grokking most codebases, but the speed comes at the cost of having to sift through many false positives.

I use the wonderful deadgrep package to do just that:

Emacs Lisp
(when (locate-library "deadgrep")
  (require 'deadgrep)
  (fset 'deadgrep--arguments-orig (symbol-function #'deadgrep--arguments))
  (define-advice helpful--all-references (:override (button) fysh/use-deadgrep)
    (cl-letf* (((symbol-function 'deadgrep--arguments)
                (lambda (&rest args)
                  `("--follow" "--type=elisp" "--type=gzip" "--search-zip" ,@(butlast (apply #'deadgrep--arguments-orig args)) ,lisp-directory ,(-first (lambda (p) (string-suffix-p "/share/emacs/site-lisp" p)) load-path)))))
      (deadgrep (symbol-name (button-get button 'symbol)) default-directory))))

The code is quite hacky because deadgrep is not designed to allow passing multiple directories in a single search, but this gets the job done.

Emacs Lisp
(with-temp-buffer
  (let ((button (make-button (point-min) (point-max)))
        (time-to-draw)
        (time-to-completion))
    (button-put button 'symbol #'car)

    (setq time-to-completion (benchmark-elapse
                               (setq time-to-draw (benchmark-elapse (helpful--all-references button)))
                               (while deadgrep--running (sit-for 0.1 'nodisp))))
    (format "Time to first draw: %s\nTime to completion: %s" time-to-draw time-to-completion)))
Time to first draw: 0.084542
Time to completion: 38.184606

In this pathological case the total time is slower than using elisp-refs-function because there are almost four times as many matches because of comments/docstrings and partial matches like mapcar or car-safe (including symbols that aren’t functions like byte-car). The major difference is that while the performance of elisp-refs-* functions1 are roughly constant regardless of the total number of references to a symbol, using ripgrep is significantly faster for terms with fewer than 10k matches (not to mention that you can browse the results immediately).

If you want to remove the partial matches, you could use the following advice instead:

Emacs Lisp
(define-advice helpful--all-references (:override (button) fysh/use-deadgrep)
  (cl-letf* (((symbol-function 'deadgrep--arguments)
              (lambda (&rest args)
                `("--follow" "--type=elisp" "--type=gzip" "--search-zip" ,@(butlast (apply #'deadgrep--arguments-orig args) 3) "--no-fixed-strings" "--" ,(car args) ,lisp-directory ,(-first (lambda (p) (string-suffix-p "/share/emacs/site-lisp" p)) load-path)))))
    (deadgrep (format "(\\(|#?'| )(%s) " (symbol-name (button-get button 'symbol))) default-directory)))

This unfortunately will highlight the entire match instead of just the capturing group, so I prefer not to use it (althgough the speed is mostly the same, if not a bit faster).


  1. elisp-refs-symbol is faster than its counterparts due to reduced implementation complexity ↩︎

-1:-- Speedier elisp-refs-* with Dumb Grep (Post George Huebner)--L0--C0--2025-09-15T18:53:39.000Z

Marcin Borkowski: Entering dates in Emacs Calc

I perform date arithmetic pretty often in Emacs Calc. One problem I’ve always had with that is that entering date forms is very far from ergonomic. (To be fair to Calc, once you get used to how Org mode allows to enter dates, basically any other way of entering them feels slow and inconvenient. This is what Org manual says about it: “The actions of the date/time prompt may seem complex, but I assure you they will grow on you, and you will start getting annoyed by pretty much any other way of entering a date/time out there” – and boy, is it true!) So, it occurred to me that it would be great to be able to use the Org date prompt in Calc. Of course, this is Emacs, so it shouldn’t be difficult, right?
-1:-- Entering dates in Emacs Calc (Post Marcin Borkowski)--L0--C0--2025-09-15T16:41:13.000Z

Irreal: Extensibility In Lisp And Emacs

Joe Marshall has a nice post on Why Lisp Still Matters. He observes that Lisp tends to attract the very best programmers but the reason for that and the reason for Lisp’s enduring success is its extensibility. As Marshall says, the thing about Lisp is that it’s based on the Lambda calculus, which means, among other things, that the language can be extended in terms of itself. In practical terms, that means that you can use macros to define new syntax and provide the semantics of that new syntax with some functions.

All of this is fairly well known and Marshall has a good exposition of the argument in his post. As I was reading it, it popped into my mind that it’s the same with Emacs. It’s not—just—a matter of Emacs being written in Lisp. The similarity is based on their extensibility. Like Lisp, if you need some new Emacs functionality it’s easy to build it yourself using the language the Emacs itself is written in. As with any Lisp, you can even extend Emacs’ Lisp language if you need to.

A lot of Emacs’ extensibility is, of course, enabled by it’s being written in Elisp. That fact should give pause to all those who are always agitating for Emacs to be rewritten in Java, Javascript, Python, Ruby, or whatever. I doubt every much that we’d have the same level of extensibility if that were to happen.

-1:-- Extensibility In Lisp And Emacs (Post Irreal)--L0--C0--2025-09-15T15:42:20.000Z

Sacha Chua: 2025-09-15 Emacs news

There were lots of Emacs-related discussions on Hacker News, mainly because of two posts about Emacs's extensibility: an Org Mode example and a completion example. This guide on connecting to databases from Org Mode Babel blocks started a few discussions. There were a couple of Emacs Carnival posts on obscure packages, too. Also, if you want to present at EmacsConf 2025 (great way to meet like-minded folks), please send your proposal in by this Friday (Sept 19). Thanks!

Links from reddit.com/r/emacs, r/orgmode, r/spacemacs, r/planetemacs, Mastodon #emacs, Bluesky #emacs, Hacker News, lobste.rs, programming.dev, lemmy.world, lemmy.ml, planet.emacslife.com, YouTube, the Emacs NEWS file, Emacs Calendar, and emacs-devel. Thanks to Andrés Ramírez for emacs-devel links. Do you have an Emacs-related link or announcement? Please e-mail me at sacha@sachachua.com. Thank you!

View org source for this post

You can comment on Mastodon or e-mail me at sacha@sachachua.com.

-1:-- 2025-09-15 Emacs news (Post Sacha Chua)--L0--C0--2025-09-15T13:16:01.000Z

Jeremy Friesen: Dynamic Org-Mode Block to List Books Read

Jenny and I are participating in our local library’s reading challenge. We formed our own team, with the goal of the team reading 100 books.

On I read Reading about the reading life: September 12, 2025 edition, in which the author draws attention to a man who read 3,599 books and hand-recorded each book read; all books having come from public libraries. Memorialized in What Dan Read.

I found Dan’s dedication inspiring—a simple bit of note taking sustained over the decades. That list, creating a bit of imortality, with its longitudinal insight into the intersection of individual curiosity, collection curation, and the currents of culture.

Drawing on that inspiration, I started thinking about my personal habits that I’m establishing. Namely writing journal entries then printing those out each month. I also use Org-Mode 📖 to track my reading. I have a single Org-Mode document that:

  • Tracks when I started, completed/abandoned reading a book.
  • Any quotes that I’ve gathered from that book.
  • Additional notes around the read.

I wrote about some of this in Re-Wiring My Epigraphs Functionality to Leverage My Bibliography File

So, drawing inspiration from Dan, I wrote an Emacs 📖 function: org-dblock-write:books-finished. That function conforms to the Dynamic Block API and I simply drop it into my Org-Mode document at some point within the month’s entries.

What it does:

  • Determine the month and year for the block
  • Query my Bibliography for books I finished reading
  • Insert into the document a list of those books, as links to those books

This way, when I print my monthly journal, I’ll have a list of books I finished that month.

Code for org-dblock-write:books-finished

-1:-- Dynamic Org-Mode Block to List Books Read (Post Jeremy Friesen)--L0--C0--2025-09-14T20:20:33.000Z

Irreal: How To Reveal You’re An Emacs User Without Saying So

Here’s a bit of humor that I’ve had sitting in one of my browser tabs for some time. Over on the Emacs subreddit, Hlorri asks you to Tell me you use emacs (without telling me you use emacs). Although meant to be humorous—and many of the answers are humorous—a lot of them reveal important things about Emacs.

The most common humorous answer involves the strength of the user’s pinky. A typical example is, “I thumb wrestle with my pinky.” Another, that I really liked and could relate to was, “My editor’s config file is older than some of my co-workers.” Several offerings involved the wearing away of the text on the CTRL key.

Among the answers that weren’t so much funny as telling were:

  • I expect to get things done in a single app.
  • I cannot use essentially any other piece of software without accidentally opening 10 print dialogs or new blank documents/tabs at some point. (and several variations on this theme)
  • There’s a mixture of awe, confusion, and mystery when I pair program with co-workers.
  • Whenever someone wants to give me any “advice” I frown.
  • I interactively do right what other people write programs to do wrong.
  • I use the same program for e-mails, coding, calendar and keeping notes (and probably much more).
  • I write utilities in elisp instead of bash.
  • You mean your code editor doesn’t have a media player, or a planner, or its own window manager?

And a bunch more. Take a look at Hlorri’s post to see them all.

-1:-- How To Reveal You’re An Emacs User Without Saying So (Post Irreal)--L0--C0--2025-09-14T15:02:42.000Z

Alvaro Ramirez: Introducing acp.el

I recently shared my early Emacs experiments with ACP, the Agent Client Protocol now supported by Gemini CLI and Claude Code LLM agents.

While we can already run these agents from Emacs with the likes of vterm, I'm keen to offer an Emacs-native alternative to drive them. To do that, I'm working an a new package: agent-shell (more on this to be shared soon). While this new Emacs agent shell has an opinionated user experience, it uses ACP under the hood. Being a protocol, it's entirely UI-agnostic. For this, I now have an early version available of the acp.el library.

acp.el implements Agent Client Protocol for Emacs lisp as per agentclientprotocol.com. While this library is in its infancy, it's enabling me to carry on with my agent-shell work. acp.el lives as a separate library, is UI-agnostic, and can be used by Emacs package authors to build the their desired ACP-powered agent experience.

You can instantiate an ACP client and send a request as follows:

(setq client (acp-make-client :command "gemini"
                              :command-params '("--experimental-acp")
                              :environment-variables (when api-key
                                                       (list (format "GEMINI_API_KEY=%s" "your-api-key")))))

(acp-send-request
 :client client
 :request (acp-make-initialize-request :protocol-version 1)
 :on-success (lambda (response)
               (message "Initialize success: %s" response))
 :on-failure (lambda (error)
               (message "Initialize failed: %s" error)))
((protocolVersion . 1)
 (authMethods . [((id . oauth-personal)
                  (name . Log in with Google)
                  (description . :null))
                 ((id . gemini-api-key)
                  (name . Use Gemini API key)
                  (description . Requires setting the `GEMINI_API_KEY` environment variable))
                 ((id . vertex-ai)
                  (name . Vertex AI)
                  (description . :null))])
 (agentCapabilities (loadSession . :false)
                    (promptCapabilities (image . t)
                                        (audio . t)
                                        (embeddedContext . t))))

I'm new at using ACP myself, so I've added a special logging buffer to acp.el which enables me to inspect traffic and learn about the exchanges between clients and agents. You can enable logging with:

(setq acp-logging-enabled t)

Look out for the *acp traffic* buffer, which looks a little like this:

If you're keen to experiment with ACP in Emacs lisp and build agent-agnostic packages, take a look at acp.el (now on GitHub). As mentioned, it's early days for this library, but it's a start. Please file issues and feature requests. If you build anything on top of acp.el, lemme know. I'd love to see it in action.

Make this work possible

I'm working on two new Emacs packages: acp.el (introduced in this post) and agent-shell (I'll soon share more about that). Please help me make development of these packages sustainable. These packages take time and effort, but also cost me money as I have to pay for LLM tokens throughout testing and development. Please help fund it.

-1:-- Introducing acp.el (Post Alvaro Ramirez)--L0--C0--2025-09-14T00:00:00.000Z

Sacha Chua: Emacs and dom.el: quick notes on parsing HTML and turning DOMs back into HTML

libxml-parse-html-region turns HTML into a DOM (document object model). There's also xml-parse-file and xml-parse-region. xml-parse-string actually parses the character data at point and returns it as a string instead of parsing a string as a parameter. If you have a string and you want to parse it, insert it into a temporary buffer and use libxml-parse-html-region or xml-parse-region.

(let ((s "<span>Hello world</span>")
      dom)
  (setq dom
        (with-temp-buffer
          (insert s)
          (libxml-parse-html-region))))
(html nil (body nil (span nil Hello world)))

Then you can use functions like dom-by-tag, dom-search, dom-attr, dom-children, etc. If you need to make a deep copy of the DOM, you can use copy-tree.

Turning the DOM back into HTML can be a little tricky. By default, dom-print escapes & in attributes, which could mess up things like href:

  (with-temp-buffer
    (dom-print (dom-node 'a '((href . "https://example.com?a=b&c=d"))))
     (buffer-string))
  <a href="https://example.com?a=b&amp;c=d" />

shr-dom-print handles & correctly, but it adds spaces in between elements. Also, you need to escape HTML entities in text, maybe with org-html-encode-plain-text.

  (with-temp-buffer
    (shr-dom-print
      (dom-node 'p nil
                (dom-node 'span nil "hello")
                (dom-node 'span nil "world")
                (dom-node 'a '((href . "https://example.com?a=b&c=d"))
                          (org-html-encode-plain-text "text & stuff"))))
    (buffer-string))
  <p> <span>hello</span> <span>world</span> <a href="https://example.com?a=b&c=d">text &amp; stuff</a></p>

svg-print does the right thing when it comes to href and tags, but you need to escape HTML entities yourself as usual.

(with-temp-buffer
  (svg-print
   (dom-node 'p nil
             (dom-node 'span nil "hello")
             (dom-node 'span nil "world")
             (dom-node 'a '((href . "https://example.com?a=b&c=d"))
                       (org-html-encode-plain-text "text & stuff"))))
  (buffer-string))
  <p><span>hello</span><span>world</span><a href="https://example.com?a=b&c=d">text &amp; stuff</a></p>

Looks like I'll be using svg-print for more than just SVGs.

Relevant Emacs info pages:

View org source for this post

You can e-mail me at sacha@sachachua.com.

-1:-- Emacs and dom.el: quick notes on parsing HTML and turning DOMs back into HTML (Post Sacha Chua)--L0--C0--2025-09-13T15:12:57.000Z

localauthor: Managing Emacs Tabs with 'tab-sets.el'

——————————————————————————————

In Emacs, my text editor of choice, tab-bar-mode lets you replicate something like the experience of using tabs in a web browser. For me, this means opening a lot of tabs with notes, lists, drafts, etc., such that my tab bar becomes a visual buffet of whatever documents are pertinent to the task at hand, be it writing, teaching, coding, whatever.

This works great for me, on a project by project basis. But what if I want to switch to another task or project? What is to become of the perfectly curated set of tabs I have open?

The problem of tab proliferation is a distinctly modern one. Raise your hand if the top of your web browser looks like a graveyard of articles you’ve been meaning to read since the last time your computer crashed. Many browsers have solved this issue by allowing users to save and restore groups of tabs under meaningful names, like “Research Project” or “Articles I Still Won’t Read.” But who does that? (Ok, I do…)

As far as I know,™ Emacs does not offer any built-in way to save and restore a beautifully curated row of tabs. There are many options for saving and restoring activities, workspaces, and frame/buffer configurations. But none that do exactly what I want, namely, allow me to save and later re-open a set of tabs, one file per tab, in a specific order.

So, I wrote tab-sets.el.

I find tab-sets most useful for teaching and writing.

For example: I sometimes teach the same class several times in a week. I therefore often found myself repeating the process of finding and re-opening all the files that I wanted to reference for that class, mostly lecture notes and slides (exported with org-reveal). Because these files can be spread out across my file system, finding and re-opening them is rarely as simple as navigating to a dedicated directory.

Now, with tab-sets.el, I can use a single command, tab-sets-save, to save the current frame’s tabs under a meaningful name, say, “Week 1 Class”, and safely close the frame. When it’s time to teach the same class again, I can call tab-sets-open, select “Week 1 Class,” and find a brand new frame displaying all the tabs exactly as they were when I saved them.

The same process works for quickly returning to a writing project.

A few niceties include:

  • minibuffer annotations, offering a preview of each tab set
  • optional integration with bookmarks.el, meaning tab sets are accessible as standard bookmarks, through list-bookmarks
  • optional integration with embark, meaning you can open, rename, or delete a tab set right from the minibuffer

This package isn’t published anywhere, so install directly, however you want or know how. For example:

(use-package tab-sets
  :ensure nil
  :vc (:url "https://github.com/localauthor/tab-sets")
  :custom
  (tab-sets-data-file "~/.emacs.d/var/tab-sets.eld")
  :config
  (tab-sets-setup-embark))
-1:-- Managing Emacs Tabs with 'tab-sets.el' (Post localauthor)--L0--C0--2025-09-12T22:53:00.000Z

Irreal: Semantic Line Breaks

Over at sembr.org, Mattt has an interesting post on what he calls semantic line breaks. The idea, as he expresses it, is

Semantic Line Breaks describe a set of conventions for using insensitive vertical whitespace to structure prose along semantic boundaries.

That sounds a little abstract but in practice it means adding a line break after each sentence and after logical breaks in the text. Here’s a more accessible description:

When writing text with a compatible markup language, add a line break after each substantial unit of thought.

There’s a specification at the link that specifies where the line breaks could/should occur.

The point of all this is that it makes it easier for the author or editors to read the input text while at the same time not affecting the way the text is rendered at output time. That works because of the way many markup languages—including, of course, Org mode—work. Take a look at the sembr.org site for the details and the precise specifications.

This seems like something that might be useful for many writers but, personally, I find that using visual-line-mode is enough for me. It shows all the text on screen by default and although it doesn’t break lines at semantically significant places, the semantic structure of the text comes through clearly for me.

But you may be different. If you find that adding an occasional line break helps make the meaning of your text clearer than by all means add them. It won’t affect the formatting of the output and it may help you and any editors you have in the process to parse the input.

-1:-- Semantic Line Breaks (Post Irreal)--L0--C0--2025-09-11T16:08:09.000Z

Protesilaos Stavrou: Prot Asks: port19 about RSI, keyboard ergonomics, dictation tools, and geriatric nursing

Raw link: https://www.youtube.com/watch?v=ZRC7cIGCC7A

In this video I talk to port19 about repetitive strain injury related to computer usage. I am introduced to the experience port19 went through, with pain in the hands and fingers. I ask about the computing setup that first contributed to the problem and learn how keyboard-driven it was. port19 covers the progression to a split mechanical keyboard, learning about specialised exercises to work out the relevant muscles, as well as reading about research on the psychosomatic factors involved. We eventually get to the topic of the custom keyboard port19 uses right now (the ZSA Voyager) and talk about all the details involved, from the weight of the switches to the typing angle, the use of layers to access certain characters, and the placement of modifier keys. To have a complete picture of the ergonomics port19 has considered, I also ask about the overall desk setup and the computer use overall. Once we cover this topic, we discuss how dictation software makes it easier to avoid the keyboard altogether while still being productive: port19 explains the relevant setup with ffmpeg and whisper program of OpenAI and shares the script for it. Towards the end of our talk, I ask port19 about the switch away from the IT sector into geriatric nursing. I learn about how things are in that field and what the experience is like.

Links from port19

About “Prot Asks”

In this new video series, I talk to anybody who is interested to have a video call with me (so do contact me if you want!). The topics cover anything related to Emacs, technology, and life in general. More here: https://protesilaos.com/prot-asks/.

-1:-- Prot Asks: port19 about RSI, keyboard ergonomics, dictation tools, and geriatric nursing (Post Protesilaos Stavrou)--L0--C0--2025-09-11T00:00:00.000Z

Irreal: Numeri

Roman Numerals. On the one hand, it’s hard to understand why anyone cares anymore. Some, like the late Rich Stevens considered them an anachronistic barbarism and labeled his books “Volume 1, 2, …” rather than the more conventional “Volume I, II, …”. Others continue to label volumes with the conventional Roman numerals and, of course, there’s all those buildings with their erection date labeled, of course, with Roman numerals on their facade.

It used to be that everyone learned how to read and write Roman numerals in School but, according to a teenager of my acquaintance, that’s no longer the case. Were it not for their ubiquitousness on the front of buildings and multivolume books, I’d be happy so see them disappear from our milieu but for the time being, it seems useful to be able to at least read them.

Really, it’s not much of an effort. There are only 7 symbols and they are combined in a regular way to form all the numbers that we’re apt to see today. It’s true that there’s more than one way to form some numbers but all of them are easy to decipher. It’s hard to see how anyone with more than a couple of brain cells to rub together would take more than 15 minutes to completely master the system.

Still, Common Lisp is famous for having functions to convert between Arabic and Roman numerals. That’s less true for Emacs Lisp but there are, apparently, some functions spread across a couple of packages to do the job. Charles Choi doesn’t like that so he wrote a package to provide the capability in a single package.

I suppose, if you squint hard enough, you can imagine cases where you might want to do this sort of thing programmatically but, really, it’s mostly too easy to do manually to need a function. Still, if you do have a need to do this programmatically, Choi has got you covered.

-1:-- Numeri (Post Irreal)--L0--C0--2025-09-10T15:47:32.000Z

James Dyer: Debugging Software Breakage with Git Stash and Emacs

We’ve all been there, your code was working perfectly from a clean checkout, but after making a bunch of changes across multiple files, something has broken. The dreaded question arises! which change caused the break? This is the story of how a debugging session led me to discover gaps in Emacs’ VC mode and ultimately create a custom solution.

I started with a clean, working codebase. After implementing several features across different files, my software suddenly stopped working. The classic debugging nightmare, multiple changes, one (or more) breaking changes, and no clear path to the culprit.

My debugging strategy as always is methodical. Over many years of software engineering I have learnt that you just need to figure out a systematic approach and then just get on with it!

  1. Start from the known-good base version
  2. Gradually reintroduce changes from my working set
  3. Test after each addition to identify the breaking point

Git stash turned out to be perfect for this workflow. Firstly I stashed all my changes, giving me a clean working directory to start from. My plan was to selectively apply portions of the stash, testing after each addition.

Using Emacs’ built-in VC mode, I could use vc-git-stash-show to display my stashed changes in a diff buffer. From there, I could navigate through the files and selectively apply hunks using Emacs’ diff mode commands. This gave me fine-grained control over which changes to reintroduce.

As I progressed through applying changes, I realised that I would really like to keep an eye on what changes remained in my stash compared to my current working directory, basically like a dynamic diff to be regenerated after each application (like typically on an individual file using ediff). This would allow me to keep an eye on likely culprits as I move through the hunking process.

In pure Git, this is straightforward:

git diff stash@{0}

But Emacs’ VC mode doesn’t provide a command for this specific operation (I have found this not to be uncommon for Emacs vc-mode, but I still like it anyways!)

Generally I think, Emacs’ VC interface is designed to be VCS agnostic, which is both a strength and a limitation. While it provides excellent abstractions for common operations like vc-diff, it doesn’t expose Git specific features like comparing against stash references.

The available VC commands were:

  • vc-diff - compares working directory with HEAD or between revisions
  • vc-git-stash-show - shows the diff of a stash

But no “diff working directory against stash” command

Now, it’s worth noting that Magit, does apparently provide this functionality, but I prefer to run on air-gapped systems (yes, that again!) where installing external packages isn’t always practical or desired. In such environments, I lean heavily on Emacs’ built-in functionality and augment it with custom elisp when needed which is probably something I suspect I am likely to do in this case.

I had an initial eshell idea on how to accomplish this!, for example you can redirect command line output to Emacs buffers using the #<buffer name> syntax, so lets try that!

I tried:

git diff stash@{0} > #<buffer *git-diff*> && diff-mode

This almost worked, but I encountered a timer error related to eshell’s command chaining.

and then I tried:

git diff stash@{0} > #<buffer *git-stash-diff*> ; diff-mode

After some experimentation, I still couldn’t quite get eshell to generate a buffer from a command and then initiate a mode. Of course I could just jump to the buffer and run it myself, but generally I wanted a solution to be easily repeatable.

Right, lets scrap the eshell idea and lets fall back on my tried and tested method of writing a defun in elisp!:

(defun my-git-diff-stash (stash-ref)
  "Diff working directory against specified stash"
  (interactive "sStash reference (e.g., 0, 1, 2): ")
  (let ((buffer (get-buffer-create "*git-stash-diff*")))
    (with-current-buffer buffer
      (erase-buffer)
      (call-process "git" nil buffer t "diff" (format "stash@{%s}" stash-ref))
      (diff-mode)
      (goto-char (point-min)))
    (switch-to-buffer buffer)))

This function:

  • Prompts for a stash reference (defaulting to numeric input like 0, 1, 2)
  • Creates a dedicated buffer for the diff
  • Runs git diff against the specified stash
  • Automatically applies diff-mode for syntax highlighting
  • Opens the buffer and positions the cursor at the beginning

The final step was to bind this command to the VC prefix map:

(define-key vc-prefix-map (kbd "S") 'my-git-diff-stash)

“S” is currently used for a regex search of some kind which I currently don’t understand and hence am not using.

Now I can use C-x v S to quickly diff my working directory against any stash (although who knows when I will need this again!)

With this in place, my debugging workflow became smoother

  1. Stash all changes
  2. Apply changes incrementally using vc-git-stash-show
  3. Test the software after each addition
  4. When it still works, check what remains C-x v S
  5. Continue applying changes from the remaining diff
  6. When it breaks, I have a good idea of the breaking issue

This experience taught me several valuable lessons:

  1. VC mode’s limitations: While Emacs’ VC interface is excellent for common operations, specialized Git workflows sometimes require custom solutions.

  2. The value of built-in solutions: Working in air-gapped environments has taught me to maximize Emacs’ built-in capabilities before reaching for external packages. While Magit would have solved this problem out of the box, building the solution myself using VC mode and custom elisp keeps dependencies minimal and increases my understanding of both Git and Emacs internals.

  3. Eshell’s power: The ability to redirect command output directly to Emacs buffers is incredibly useful, even if it has some quirks with command chaining and in the end I never really got it to work, but it is in my brain more concretely now as this blog post now exists!

  4. Integration matters: Binding custom functions to standard keymaps makes them feel like native features.

-1:-- Debugging Software Breakage with Git Stash and Emacs (Post James Dyer)--L0--C0--2025-09-10T07:00:00.000Z

Irreal: Obscure Emacs Packages

It’s September so there’s a new Emacs Carnival. This month the topic is Obscure Emacs Packages. I have to admit that when I first saw the topic I wasn’t too hopeful that it would be interesting but, of course, I felt the same about the “Elevator Pitch” topic and we all know how obsessed I ended up being with that.

Now that I’ve read my first post for the new topic, tusharhero’s Obscure Emacs Packages, I guessing that I’m going to end up loving this topic too. Tusharhero’s post actually lists 4 obscure packages—none of which I was familiar with—that many Irreal readers might find useful.

By all means, take a look at his post for all the details but I want to mention two of them that I think could be particularly useful. The first is Tinee that is an implementation of Emacs Everywhere specifically for Wayland, which isn’t supported by Emacs Everywhere. The package was written by Tusharhero himself who says it’s not as full featured as Emacs Everywhere but if you’re an Emacs user on a Wayland system, it seems definitely worth taking a look at.

The other package is Emacs Reader by Divya Ranjan. It aims to be a complete replacement for PDF-tools and DocView. It’s still in the early stages but Tusharhero says it has “RIDICULOUSLY better performance and smoothness and responsiveness in comparison to both PDF tools and DocView.” It’s still early days for this package but if it lives up to its promise, it will be a package that almost everyone will want.

Take a look at Tusharhero’s post and see if there’s anything there for you.

-1:-- Obscure Emacs Packages (Post Irreal)--L0--C0--2025-09-09T16:43:45.000Z

Alvaro Ramirez: So you want ACP (Agent Client Protocol) for Emacs?

Last week, I was delighted to see the Zed editor shipping beta support for their Claude Code integration. Being an Emacs enthusiast, you may wonder about my excitement. In their demo, the Zed team mentioned the integration is now possible thanks to Agent Client Protocol (ACP), which they developed in collaboration with Google. This is great news for Emacs users, as it opens the possibilities for deeper native agent integrations in our beloved editor. You can think of ACP as LSP but for LLM agents.

While I have a bunch of LLM models integrated into chatgpt-shell (including local ones), I've yet to make much headway into enabling the models to access smarter context (ie. filesystem or local tools), beyond my initial tool calling experiment.

Somehow, I wasn't super excited about tool calling, as it felt like these integrations would fall short when compared to more advanced agents like Anthropic's Claude Code or Google's Gemini CLI. In fact, I haven't been that enthusiastic about these agents, since they offered relatively little API surface to enable deeper Emacs integration (which is where I live!). That is, until ACP came along.

With ACP in mind, I'm much more likely to get on board with Emacs-agent integrations. I can now delegate all that complex agent logic to external tools and focus on building a great Emacs experience I'd be happy with.

And with that, I had an initial go at prototyping a bare minimum but with enough UX shell goodies to get me excited about it. I chose Gemini for this prototype. You can see it all in its minimal glory:

So how badly do you want ACP support in your beloved Emacs?

While getting the initials kinda working was relatively straightforward (with everything I already know about building chatgpt-shell), adding support for all ACP features with a delightfully polished Emacs experience will take a bunch of effort. While I'm excited about the prospects, dedicating a chunk of my time to make this happen isn't super feasible. You may have noticed more Emacs-related work/posts from me lately. This is currently possible because I've gone full indie dev. The flexibility is great, but doing Emacs things isn't exactly gonna help pay the bills unless interested folks help fund/support the effort.

My shell packages have quite a few enthusiastic users who more often than not, are using my package to talk to paid cloud services from the likes of OpenAI, Anthropic, or Google. I'm looking at you folks! I understand you're sending money to these companies who are providing you with a great service, but also remember the lovely Emacs integrations you use, which also need funding (much more than these well-funded commercial entities). While I'm a fan of chat-like Emacs shells for LLM/agents and would like to build a new agent shell, I also want to dedicate a chunk of this effort to building a UX-agnostic ACP Emacs library (acp.el). This library could be leveraged by me or any other Emacs package author.

So how badly do you want ACP support in your beloved Emacs? Enough to take your wallets out and help fund it?

-1:-- So you want ACP (Agent Client Protocol) for Emacs? (Post Alvaro Ramirez)--L0--C0--2025-09-09T00:00:00.000Z

Marcin Borkowski: Emacs Artist clock

A few months ago I mentioned Artist mode. It seems that at least one person liked that post enough to mention it (thanks!), even if indirectly. That very post also mentioned svg-clock, which is a cute analog clock displayed directly in Emacs. Of course, my immediate thought was, why not create an ASCII-art analog clock using Artist mode?
-1:-- Emacs Artist clock (Post Marcin Borkowski)--L0--C0--2025-09-08T17:24:48.000Z

Charles Choi: Announcing Numeri - an Emacs package for Roman number translation

It all started with Super Bowl LIX. “What number is that?” Sure, that answer could be solved with a Google search, or even worse, burning petrol to fuel some LLM query. Being an Emacs user, I was certain someone had already solved the problem of translation to Roman numbers. Indeed this was the case but the answer was in two separate packages, both included in Emacs:

  • Roman to Hindu-Arabic number translation was covered by the command rst-roman-to-arabic in the reStructuredText (rst) package.
  • Hindu-Arabic to Roman number translation was covered by the command org-export-number-to-roman in the Org export (ox) package.

“Hunh” I thought, seems like I’d never recall that these two packages have the commands that would do the job for me. I’d have a much better chance of using them if they were in a single package whose name I could remember.

So begat numeri, a new package that wraps both of the above commands, now available on MELPA.

There are two commands of note:

  • numeri-arabic-to-roman

    This command will accept either an Arabic integer number selected as a region or input via mini-buffer prompt and convert it to its Roman equivalent. The result is copied into the kill-ring.

  • numeri-roman-to-arabic

    This command will accept either a Roman integer number selected as a region or input via mini-buffer prompt and convert it to its Arabic equivalent. The result is copied into the kill-ring.

Closing Thoughts

I have no expectations on how useful folks will find numeri. Regardless, there is delight in knowing that for even the most esoteric of problems, there’s a non-zero chance that someone has already solved it in Emacs.

-1:-- Announcing Numeri - an Emacs package for Roman number translation (Post Charles Choi)--L0--C0--2025-09-08T17:00:00.000Z

Irreal: Emacs Bankruptcy

In the developer world, we often talk about two types of bankruptcy:

Email Bankruptcy
This is when we have so many unread emails that we simply give up, delete them all, and start over.
Emacs Bankruptcy
This is when our Emacs configuration becomes so big and complicated that we no longer understand it and start over by deleting our configuration and beginning again with a blank slate.

My Anglo-Saxon upbringing pretty much guaranteed that I’d be resistant to either of these. I’m far too anal to leave any email unread or at least scanned. It’s not really much of an issue today since, unlike the old days, I can access and read my email from wherever I am. That and my zero inbox policy ensure that I never get behind with Email.

As for my Emacs configuration, it’s almost 20 years old and while it has grown and had some minor changes, I’ve never felt the need—or even the urge—to quit and start over. It is, in short, an organic entity that grows and changes in step with my needs. Why would I want to abandon it and start over?

All this discussion is in reaction to a video by TrepidTurtle on the Emacs subreddit about Emacs bankruptcy. TrepidTurtle views Emacs bankruptcy as a natural and common process in our Emacs life. He says, for example, that he was aghast to discover that his Emacs configuration was over 2000 lines long and remedied that by deleting his entire Emacs environment—packages and all—and starting over from scratch. Implicit in his argument is the belief that a minimalist configuration is better.

I don’t understand that. My configuration is 2055 lines and while there may be some cruft most of it is carefully curated packages, settings, and bespoke functions that I’ve developed over my Emacs career. Why would I want to delete all that work?

As for having a minimalist configuration, I add things as I need them or think they will enhance my workflow. I see nothing ipso facto virtuous about having a minimal configuration.

Still, people’s opinions differ and you may be sympathetic to the idea of starting over. If so, take a look at TrepidTurtle’s video for some ideas as to how to do that.

-1:-- Emacs Bankruptcy (Post Irreal)--L0--C0--2025-09-08T15:54:07.000Z

Sacha Chua: 2025-09-08 Emacs news

There was lots of conversation around Why Rewriting Emacs Is Hard this week, with threads on Reddit, HN, and lobste.rs. Also, if you want to present at EmacsConf 2025 (great way to meet like-minded folks), please send your proposal in by next Friday (Sept 19). Thanks!

Links from reddit.com/r/emacs, r/orgmode, r/spacemacs, r/planetemacs, Mastodon #emacs, Bluesky #emacs, Hacker News, lobste.rs, programming.dev, lemmy.world, lemmy.ml, planet.emacslife.com, YouTube, the Emacs NEWS file, Emacs Calendar, and emacs-devel. Thanks to Andrés Ramírez for emacs-devel links. Do you have an Emacs-related link or announcement? Please e-mail me at sacha@sachachua.com. Thank you!

View org source for this post

You can e-mail me at sacha@sachachua.com.

-1:-- 2025-09-08 Emacs news (Post Sacha Chua)--L0--C0--2025-09-08T13:32:03.000Z

tusharhero: Obscure Emacs packages

~590 words. ~2 minutes.

This is my second submission to the Emacs Carnival (my first one was emacs elevator pitch). The theme this time around is about obscure emacs packages. I figure I will just talk about the obscure packages I use.

Org Custom Cookies

homepage

This package by gsingh93 allows you to define your own custom cookies for org-mode. This was the first package I ever contributed to :).

I no longer use it though. I think I had used it to add a counter cookie for the number of subheadings of an org heading.

Yeetube

homepage

This package by Thanos Apollo allows you to search for YouTube videos and play them through mpv (which uses yt-dlp under the hood). As we all know, YouTube is a demonic proprietary website but unfortunately a lot of videos are only available on YouTube. So as much as I would like to only rely on Peertube and friends, I can't.

Yeetube directly parses the search results from the search page HTML, this is what differentiates it from tools like ytfzf which rely on the invidious api to get the search results. The problem with invidious is that because YouTube keeps blocking them, there is no guarantee that the instance you use now will work reliably tomorrow. AFAIK, ytfzf also used to directly parse the YouTube search result pages, I am not sure why they stopped.

And after parsing the search results, it displays them in a neat table with THUMBNAILS! And it also allows you to control mpv from within Emacs.

tinee: tinee is not emacs everywhere

homepage

This time the author is me! The package name is a homage to the venerable emacs-everywhere package. Of which tinee is just a simple substitute on Wayland.

For those who don't know what emacs-everywhere or tinee are supposed to do, they allow you to use Emacs to write everywhere on your computer. This is done by binding a key to tinee/emacs-everywhere in your desktop environment, which then opens up a small emacs frame for you to type what you want, after you are done, it automatically sends the content into the proper place.

Emacs Reader

homepage

This is a very ambitious project by Divya Ranjan. It aims to completely replace PDF-tools and DocView.

It uses MuPDF in the backend via a dynamic module.

Currently, it is still in very initial stages but we already have:

  • RIDICULOUSLY better performance and smoothness and responsiveness in comparison to both PDF tools and DocView.
  • All formats supported by MuPDF (not just PDFs, EPUBs, and stuff too).
  • multithreaded rendering of the documents
  • dark-mode
  • imenu and outline
  • bookmarks and saveplace support

Currently, we are trying to implement text related features.

-1:-- Obscure Emacs packages (Post tusharhero)--L0--C0--2025-09-08T04:00:00.000Z

Irreal: Must Have Emacs Packages In 2025

A few years ago, starting in 2016, I wrote a series of articles (1, 2, 3) about my favorite Emacs packages and tips. Reading them now, almost ten years later, I find they’ve aged well. I still use everything on the list and my “can’t live without” packages are pretty much the same. I didn’t include Org mode or Magit because, even then, they were given must haves.

I was reminded of all this when I saw a post on the Emacs subreddit from macro_. The post asked what are the must have Emacs packages in August 2025? Once you get past the usual ankle biting, the answers are revealing. Although consult and Ivy were mentioned frequently there seemed to me be less emphasis on actual editing and more on things like LLM and LSP. For example, no one mentioned Steve Purcell’s indispensable whole-line-or-region. I use it many, many times everyday—probably more than any other package.

Still there are plenty of good suggestions in the comments and they are well worth taking a look at. Everybody’s opinion will differ, of course, but I find it really useful to see what others think and why they think it. Sometimes they even convince me to try out one of their favorites. Take a look at the comments and see if there’s anything there that might improve your workflow.

-1:-- Must Have Emacs Packages In 2025 (Post Irreal)--L0--C0--2025-09-07T16:36:21.000Z

Protesilaos Stavrou: Prot Asks: Greg about Emacs, Android, dogs, fishing, cycling, and Pennsylvania

Raw link: https://www.youtube.com/watch?v=8iovwdREt1o

In this video, I talk to Greg about a number of topics ranging from the technical work one does in Emacs to outdoors activities in Pennsylvania. Our discussion starts with the topic of Emacs, where I learn that Greg has been working professionally with software for twenty years. In Greg’s experience, one of the advantages of using Emacs for work is that you do not need to change your tools when you switch jobs or work with different programming languages. We then discuss Greg’s attempt to use Emacs on Android, as there now is an official build for that platform. We briefly touch on the Clojure programming language and also talk about ways of learning to program. Once we cover these technical issues, we switch to the outdoor activities that Greg enjoys: cycling, fishing, and just being outside with his dog. I learn from Greg a few things about fishing and we eventually comment on a lot of more profound insights about natural experiences in general. Our final comments revolve around the appreciation of the comments, in light of a politics essay I published recently titled “When your country is a theme park”: https://protesilaos.com/politics/2025-09-02-when-your-country-is-a-theme-park/.

About “Prot Asks”

In this new video series, I talk to anybody who is interested to have a video call with me (so do contact me if you want!). The topics cover anything related to Emacs, technology, and life in general. More here: https://protesilaos.com/prot-asks/.

-1:-- Prot Asks: Greg about Emacs, Android, dogs, fishing, cycling, and Pennsylvania (Post Protesilaos Stavrou)--L0--C0--2025-09-07T00:00:00.000Z

Protesilaos Stavrou: Emacs: show-font version 1.0.0

This package lets you preview a font inside of Emacs. It does so in three ways:

  • Prompt for a font on the system and display it in a buffer.
  • List all known fonts in a buffer, with a short preview for each.
  • Provide a major mode to preview a font whose file is among the installed ones.

Sources:

Below are the release notes.


Version 1.0.0 on 2025-09-07

This major update introduces support for fonts that cover more than the Latin script. It also expands the available functionality with quality-of-life refinements.

Support for Arabic, Chinese, Greek, Japanese, Korean, Russian

The commands show-font-tabulated (alias show-font-list) and show-font-select-preview can now generate a preview for fonts that are optimised to display the aforementioned languages. Each language provides its own user option to control the sample text it displays. The naming pattern show-font-LANGUAGE-sample.

Of those, I only know Greek and thus wrote the value of show-font-greek-sample, namely: "Πρωτεσίλαος ο φιλόσοφος του οποίου τα έργα βρίθουν αστειισμών". For the others I used translation software to get the equivalent of "Protesilaos does not read LANGUAGE". Please let me know if there are any mistakes in this regard. I was thinking of writing something a bit more funny, but was concerned the joke may not translate well.

Checking for language support among known families

While I have written functions that test if a given font can display a range of characters, this approach is computationally intensive if we need to check for many code points across multiple fonts.

The alternative is to maintain lists of known font families that are meant to work with the given language. Those generally support Latin as well, but the idea is to let them shine in the language they are meant to be used for.

For example, here is how we know that a font family is meant to display Arabic script:

(defconst show-font-arabic-families
  '("AlArabiya" "AlBattar" "AlHor" "AlManzomah" "AlYarmook"
    "Dimnah" "Hani" "Haramain" "Hor" "Kayrawan" "Khalid" "Mashq"
    "Nagham" "Noto Kufi Arabic" "Noto Naskh Arabic" "Noto Sans Arabic"
    "Rehan" "Sharjah" "Sindbad")
  "List of families that specialise in Arabic.
Also see `show-font-greek-families' for the rationale of grouping font
families in distinct variables.")

The list is not exhaustive and I am always eager to expand it. Just let me know.

I learnt about these font families through trial and error by (i) installing them on my Debian system and (ii) searching online for common samples of them. Do apt search -n fonts- to check the relevant packages.

Support for music notation, mathematics, and other symbols

As with the natural languages, there are some fonts that specialise in displaying symbols. For example, MathJax has a bunch of fonts for showing those fancy formulas in the processed output of LaTeX documents. Again, there is a defconst for each of those types of font listing the known families. The concomitant user options are:

  • show-font-mathematics-sample
  • show-font-music-sample
  • show-font-symbols-sample

Problematic fonts are hidden from the list view

The show-font-hidden-families lists the fonts that are not known to cause problems. They do not render properly any of the supported samples and I am not sure even when they claim to support a certain set of characters (e.g. show-font--displays-latin-p returns non-nil). If you think there is a mistake here, please contact me.

Show a full preview from the list view

While in the buffer produced by show-font-tabulated (alias show-font-list), type RET to get a complete preview of the font family of the current line. This is the same as invoking the command show-font-select-preview and then selecting the given family.

The command called by that key binding is show-font-tabulated-select-preview. A hint of it is also shown in the tabulated list header.

Quickly copy the name of the font in the list view

As above, type w in the tabulated view to copy the name of the font family to the kill-ring. The command is show-font-tabulated-copy-name and there is also a hint of it in the tabulated list header.

-1:-- Emacs: show-font version 1.0.0 (Post Protesilaos Stavrou)--L0--C0--2025-09-07T00:00:00.000Z

Irreal: Hacking Emacs File Completion

James Dyer has another in his series of posts describing the sanding down of his workflow. This time he troubleshoots and resolves a problem with minibuffer file completion. His specific problem was that he didn’t like the way fuzzy file completion was working.

The default behavior was to have whatever he entered match any file name that had the same letters in the same order even if they weren’t consecutive. What he wanted was to match any files whose name had a substring that matched his input.

As usual, Emacs has you covered. There’s a completion-styles parameter that you can set to get the exact behavior he wanted. Except it didn’t work. It turned out that another function in the call path was resetting completion-styles to the behavior he was trying to avoid.

It wasn’t too hard to fix this and you see how he did it in his post. There was another small issue that he also fixed. Again, see Dyer’s post.

The meat of his post for me was his three conclusions at the end:

  1. The source code is always easily available and you can solve most problems by looking to see what is actually happening.
  2. Be wary of local versus global settings.
  3. With Emacs, there’s always another way. If you don’t like the way something works, Emacs probably provides another way of achieving the same end.

Most people probably aren’t going to care about the issue Dyer was fixing—at least I don’t care about it—but the point is that whatever Emacs is doing that’s not quite right for you, it’s almost always pretty easy to fix it.

-1:-- Hacking Emacs File Completion (Post Irreal)--L0--C0--2025-09-06T14:06:41.000Z

James Dyer: Customizing Emacs Completion: From Fido's Fuzzy Matching to Literal Substring

For my completion framework, I’m currently using fido-mode, and more recently, fido-vertical-mode. However, I’m scratching yet another itch in my ongoing quest to be more efficient in Emacs, specifically to jump to files more quickly. I explored this in a previous post where I enhanced the recentf functionality to work through completing-read in a predictable order, but what about the completing-read interface itself?

This happens to me often in Emacs, there is a subconscious functional annoyance which eventually bubbles to the surface and this case the surface bubble revolves around fido’s fuzzy matching behaviour. Simply put, I don’t like it!

While it can be helpful for discovering files and commands you partially remember, sometimes you know exactly what you’re looking for and want a more literal, predictable search experience, in fact for me now, I would say it is not just sometimes, but always!. The fuzzy matching is finding too many candidates when I type in a few characters and really I want a contiguous input string to be literally matched.

This post chronicles my journey from fido’s flex matching to a custom setup that provides literal substring matching, perfect for when you know what you want and just want to type it directly.

Hang on a sec, can’t I just change the completion style?, this should be easy!

(setq completion-styles '(substring basic))

But that has no effect!, boooo!

Anyways, that was a quick attempt at a fix, in the meantime lets explore flex a little bit more and icomplete (which is the underpinning completion technology of fido) and see if we cam come up with a robust solution.

Fido-mode use what’s called “flex” completion by default. This means that when you type abc, it will match files like a_long_b_filename_c.txt because it finds the letters a, b, and c in that order, even with other characters between them.

While this flexibility is powerful, it can be frustrating when you want to search for a specific substring. If you’re looking for a file named project-abc-config.txt, you might expect typing abc to prioritize that match, but flex matching might show you a_big_collection.txt first instead.

So back to my initial attempt at a fix by setting the completion-styles variable. The substring style matches your input as a contiguous block anywhere within candidates, while basic does prefix matching. This seemed like exactly what I wanted, I just need to find a way to set it and to make it stick.

After some digging into the source code, I found the culprit in icomplete.el. The icomplete--fido-mode-setup function contains the following:

(defun icomplete--fido-mode-setup ()
  "Setup `fido-mode''s minibuffer."
  (when (and icomplete-mode (icomplete-simple-completing-p))
    ;; ... other settings ...
    (setq-local completion-styles '(flex)  ; This line forces flex!
                completion-flex-nospace nil
                ;; ... more settings ...
                )))

This function runs every time you enter the minibuffer, forcibly overriding any completion-styles setting you might have configured. This explains why my setq had no effect, fido was resetting it on every use!

Rather than fight fido’s opinionated behaviour, I could instead switch to icomplete-vertical-mode, which provides a similar interface but respects the standard completion configuration.

(icomplete-vertical-mode 1)

;; scroll list rather than rotating
(setq icomplete-scroll t)

;; Make completion case-insensitive
(setq completion-ignore-case t)
(setq read-file-name-completion-ignore-case t)
(setq read-buffer-completion-ignore-case t)

(with-eval-after-load 'icomplete
  (setq completion-styles '(substring basic partial-completion emacs22)))

This gave me the literal substring matching I wanted and I think I have managed to set up everything else to the way fido comes out of the box.

However, there was one more hurdle.

By default, icomplete-vertical-mode requires you to explicitly select a completion before submitting with C-m (Enter) which is a keybinding I had grown accustomed to using in fido. This adds an extra confirmation step that fido-mode doesn’t have. There is a way around this however and that is to adapt to the keybinding C-j which typically is more of a do literal action then exit type of thing, where C-m is more of just a simple Enter/action. I am willing to adapt to this keybinding.

So this works pretty well for me really, but can I not just get completion-styles to stick for fido?, even though I have a solution I really want to see if I can adjust fido’s default functionality.

Well simply I used an advice function to wrap around the original fido setup function and set up the completion-styles local variable after fido has done its thing:

(defun my-fido-completion-styles-advice (&rest _args)
  "Override completion styles after fido setup."
  (when (and fido-mode (icomplete-simple-completing-p))
    (setq-local completion-styles '(substring basic partial-completion))))

(advice-add 'icomplete--fido-mode-setup :after #'my-fido-completion-styles-advice)

Now I have two options for using completion in Emacs the way I want it and now I can find files, or anything else for that matter much more quickly.

This journey taught me several important lessons about Emacs customization:

  1. Read the source: When configuration variables don’t seem to work as expected, the source code often reveals why.

  2. Local vs. global settings: Fido uses setq-local to override settings per-buffer, which is why global setq calls don’t work.

  3. There’s always another way: Emacs’ flexibility means there are usually multiple approaches to achieving the same goal.

While fido-mode’s fuzzy matching is excellent for discovery and exploration, I just wanted the predictability of literal substring matching and with a small advice function, you can have the best of both worlds!

-1:-- Customizing Emacs Completion: From Fido's Fuzzy Matching to Literal Substring (Post James Dyer)--L0--C0--2025-09-05T09:06:00.000Z

Thomas Ingram: Minimal Debian 13 and LaTeX Install

In honor of the release of Debian 13 Trixie I've treated myself to a fresh install of Debian. In the spirit of minimalism I've started with a completely bare base-system, opting to skip all graphical desktops for my initial install. I enjoy the process of starting with essentially a Linux server and only installing packages as I actually need them. Doing this highlights the applications I rely on, and in turn the software those apps rely on. In other words dependencies.

Now I'll admit this is mostly a fun exercise that appeals to my brain in particular. For the most part extra software is not a big issue, and it is better to have a working computer than a few less bytes on a hard drive. I just find a minimal setup satisfying. At one point I was an Arch Linux user, it is what it is.

The tradeoffs of software minimalism were highlighted for me when I installed mpd (Music Player Daemon). mpd has a lot of dependencies and a few that I found unnecessary. I will likely never need to play Commodore 64 music files (libsidplayfp6), but that is also what makes mpd great. It is a flexible tool you can throw anything at. Still I was a little more annoyed to see JavaScript libraries installed just to show the documentation pages (Sphinx).

If I was a python programmer I likely would have never noticed because Sphinx is a dependency for nearly every *python-doc package. For me though mpd is the only package that requires these dependencies. It's just a few extra bytes, I can live with it. Perhaps someday I'll be in the woods completely offline and need to consult a local copy of the mpd docs. In that moment I'll be so thankful. I might not even consider that Sphinx definitely has export options that does not require JavaScript libraries.

Of course this is not a real deal breaker. I could build mpd myself, or build a custom deb package. I could switch back to Arch Linux. Better yet I could switch to Gentoo and spend all my days compiling packages. No, I use Debian because I like Debian. I like the philosophy, stability, and cooperative spirit of the project. Debian maintainers are making sane choices that makes stuff work with reasonable defaults that supports a huge range of use cases.

With all that in mind, lets talk about LaTeX.

1. Installing LaTeX on Debian

To build LaTeX documents we need to install the TeX Live distribution. A full install of the texlive packages is huge and includes thousands of TeX packages. Majority of which I will never use and don't want to install. The problem is to compile Org-mode documents we need several packages that are only included in the extensive texlive-latex-extra and texlive-pictures packages.

1.1. Installing LaTeX the Normal Way

sudo apt install texlive texlive-latex-extra texlive-pictures texlive-science

You can see the list of TeX packages each of these installs in the package descriptions. Run apt info to see the full list. The texlive-latex-extra lists around 1,500 packages. I need ~3.

apt info texlive-latex-extra

1.2. Manual TeX Live Install

If you really want a minimal install the best option would be to just manually install texlive and the packages you want. You can do that by following the instructions on tug.org/texlive/, That is probably the right way to circumvent installing every Debian texlive package. Once installed you'll be able to manage your whole texlive install with the included package manager tlmgr (TeX Live Manager).

1.3. Mixed Install with apt and tlmgr

The method I used was a little more chaotic. I installed the base texlive system via apt. This gives us all the critical stuff for building basic documents (pdflatex, tlmgr) with minimal effort.

apt install texlive

After that I go to my documents and start trying to build them. Even for a basic Org to LaTeX document there are several TeX packages that will be missing. The compile warning will call out the missing package *.sty and then I can install it with tlmgr.

ERROR: LaTeX Error: File `wrapfig.sty' not found.

--- TeX said ---
./test.tex:9:  ==> Fatal error occurred, no output PDF file produced!

On Debian the texlive package manager tlmgr is included with the base texlive install. The Debian maintainers have explicitly recommend not to use this tool1, because it may install TeX packages are incompatible with the deb package versions. So please do this at your own risk and do NOT pester Debian volunteers if your TeX install breaks!

One benefit of this mixed setup is the tlmgr tool is forced into --user mode. This means all packages are installed locally in your home directory. For my use case that is perfect. If something breaks I can always delete the directory and fall back to an apt install. By default packages are stored in ~/texmf/, and can be changed by setting the TEXMFHOME environment variable. In my ~/.bashrc I have this set:

export TEXMFHOME=$HOME/.config/texlive/

Then initialize our tlmgr folder with:

source ~/.bashrc    # Ensure your $TEXMFHOME is set
echo $TEXMFHOME
tlmgr init-usertree

Now we can install the couple missing dependences needed for Org LaTeX export via tlmgr. Once you've installed all the packages reported in your LaTeX compile errors you should be all set going forward.

tlmgr install warpfig rotating ulem capt-of

Again this is a hack-y solution, but currently I only have ~10 packages manually installed. That is in comparison to the hundreds of packages included in all of texlive. This solution may become more fragile over time as Debian stable drifts further out of date with current TeX Live releases. Although I suspect most popular TeX packages are pretty stable and slow moving.

Footnotes:

1

See /usr/share/doc/texlive-base/README.tlmgr-on-Debian.md

-1:-- Minimal Debian 13 and LaTeX Install (Post Thomas Ingram)--L0--C0--2025-09-05T04:00:00.000Z

Amin Bandali: Prot Asks me about EmacsConf, Debian, GNU, Internet Archive, and Canada

Earlier today I joined Prot for an episode of his Prot Asks series, where he talks to folks about Emacs and life in general. We talked about free software, free knowledge, the importance of community and the commons, and life in Canada.

See the episode’s page on Prot’s website for the video recording, Prot’s summary of our chat, and the links I shared after our call. You can also watch the recording embedded below.

I really enjoyed our chat today and time went by very quickly. Thanks again for having me, Prot!

Take care, and so long for now.

The video recording is Copyright © 2025 Protesilaos Stavrou and Amin Bandali, and is licensed under CC BY-SA 4.0.

-1:-- Prot Asks me about EmacsConf, Debian, GNU, Internet Archive, and Canada (Post Amin Bandali)--L0--C0--2025-09-03T22:58:58.000Z

Rahul Juliato: Quickly switching between git status files buffers in Emacs

When I'm deep into developing a feature, I don't want to think about whether a file is already open in a buffer, or if I need to search the whole project to find it.

I just want to jump straight to the files I'm actively working on, the ones that Git tells me are modified, untracked, or even renamed.

Emacs already gives us great defaults for different contexts:

C-x b (switch-to-buffer) → jump between open buffers.

C-x p b (project-switch-to-buffer) → jump between buffers in the current project.

C-x p f (project-find-file) → find any file inside the project.

Each of these has its value and time. But in the middle of a coding session, when iterating fast on a feature, none of them give me what I want: a list of just the files I've touched.

That's the itch that led me to write this command.

The Function and Binding

(defun emacs-solo/switch-git-status-buffer ()
  "Parse git status from an expanded path and switch to a file.
The completion candidates include the Git status of each file."
  (interactive)
  (require 'vc-git)
  (let ((repo-root (vc-git-root default-directory)))
	(if (not repo-root)
		(message "Not inside a Git repository.")
	  (let* ((expanded-root (expand-file-name repo-root))
			 (command-to-run (format "git -C %s status --porcelain=v1"
									 (shell-quote-argument expanded-root)))
			 (cmd-output (shell-command-to-string command-to-run))
			 (target-files
			  (let (files)
				(dolist (line (split-string cmd-output "\n" t) (nreverse files))
				  (when (> (length line) 3)
					(let ((status (substring line 0 2))
						  (path-info (substring line 3)))
					  ;; Handle rename specially
					  (if (string-match "^R" status)
						  (let* ((paths (split-string path-info " -> " t))
								 (new-path (cadr paths)))
							(when new-path
							  (push (cons (format "R %s" new-path) new-path) files)))
						;; Modified or untracked
						(when (or (string-match "M" status)
								  (string-match "\?\?" status))
						  (push (cons (format "%s %s" status path-info) path-info) files)))))))))
		(if (not target-files)
			(message "No modified or renamed files found.")
		  (let* ((candidates target-files)
				 (selection (completing-read "Switch to buffer (Git modified): "
											 (mapcar #'car candidates) nil t)))
			(when selection
			  (let ((file-path (cdr (assoc selection candidates))))
				(when file-path
				  (find-file (expand-file-name file-path expanded-root)))))))))))

(global-set-key (kbd "C-x C-g") 'emacs-solo/switch-git-status-buffer)

The command parses git status --porcelain=v1, collects the interesting files, and offers them through completing-read. This means it works with whichever completion frontend you already use, and it switches to the selected file's buffer (opening it first if it isn't already open).

Completion in Action

Here's how it looks in different completion UIs:

Plain completion buffer completion-example

Fido completion-example

Fido vertical completion-example

Icomplete vertical completion-example

Vertico completion-example

No matter which you prefer, you get a filtered list of just the files that matter right now.

Why emacs-solo?

This command is part of my emacs-solo project, a collection of Emacs enhancements that stick to built-in tools and minimal glue code.

The goal is to show how far we can go without depending on a huge package ecosystem, while still making day-to-day workflows smoother.

Conclusion

When I'm developing a feature, I care about the files I've just modified, created, or moved.

This command scratches exactly that itch: fast navigation to Git-relevant files, without worrying if they're open or buried somewhere in the project tree.

Give it a try, and check out emacs-solo for more small, practical commands like this one. 🚀

Edit:

2025-09-04: Fixed the global binding to emacs-solo/switch-git-status-buffer, as pointed by u/jplindstrom on r/emacs (reddit).

-1:-- Quickly switching between git status files buffers in Emacs (Post Rahul Juliato)--L0--C0--2025-09-03T20:11:00.000Z

Please note that planet.emacslife.com aggregates blogs, and blog authors might mention or link to nonfree things. To add a feed to this page, please e-mail the RSS or ATOM feed URL to sacha@sachachua.com . Thank you!