The cross-platform Emoji picker (emoji-list) in Emacs is nice. But if you’re on macOS running the NS variant of Emacs, you can use the macOS-native picker which is better (😍). The command to raise this picker is ns-do-show-character-palette.
Unfortunately, this command is not configured to be in the main menu by default. The following Elisp initialization code will rectify that, placing the menu item “Emoji & Symbols” at the bottom of the Edit menu from the main menu. The :visible slot ensures that this will only take effect on NS Emacs.
12345
(easy-menu-add-itemglobal-map'(menu-baredit)["Emoji & Symbols"ns-do-show-character-palette:help"Show macOS Character Palette.":visible(eqwindow-system'ns)])
Note that users of the Mitsuharu Yamamoto fork of Emacs (aka Emacs Mac App) don’t have to do this as this behavior is already there. It used to be my daily driver but I switched over to the NS variant with the 29.4 release some time ago because the latter was actively maintained. I suspect (sadly 😞) that the Yamamoto fork is being left to bit-rot which is regrettable as that fork is the superior version when it comes to native macOS integration. With the upcoming Emacs 30 release, I think this will become even more pronounced. I'd be happy to be wrong on this though.
Just a quick post about a short note from Marcin Borkowski (mbork) concerning searching for the thing at point. Despite using Emacs for over 18 years I didn’t know about isearch-forward-thing-at-point.
As mbork says, it does just what it says. You invoke it with Meta+sMeta+. and it searches forward for whatever the point is on. This is something I want to do all the time and I was vaguely aware that it was possible but didn’t know exactly how to do it, so I’m really glad to see mbork’s post.
Finding out about this now serves to emphasize that learning Emacs really is a lifelong journey.
This is a simple package to automatically preview in a window the file
at point in Dired buffers. Preview windows are closed when they are no
longer relevant, while preview buffers are killed if they have not
been used for other purposes beside previewing. The package provides
several customisation options to control its behaviour.
Backronym: Directories Invariably Render Everything Decently …
preview; dired … PDFs Require Extra Viewing Instructions for Emacs
to Work.
Below are the release notes
Version 0.4.0 on 2025-02-18
This version contains several refinements and bug fixes.
Preview buffers have a mode line indicator
Preview buffers have a prefix to their name to make them stand out.
This is controlled by the user option dired-preview-buffer-name-indicator,
which is a string that defaults to [P].
Control how preview buffers are cleaned up
The way dired-preview works is to display a buffer and then keep a
list of preview buffers to economise on redisplaying it again. This
list of buffers is relevant for as long as we are in the Dired buffer,
otherwise all buffers therein are killed (buffers that were alive
before being previewed are not touched).
By default we delete from oldest to newest the accumulated buffers
when they exceed 10 in total. Though users can modify this behaviour
by editing the value of the new user option dired-preview-kill-buffers-method
(its doc string explains the technicalities).
The dired-preview-display-action-alist has a new optional function
The dired-preview-display-action-alist is the user option which
controls where the preview window is displayed. Its value can either
be the symbol of a function or a display-buffer-alist entry.
By default, we have a “do-what-I-mean” function that tries to find a
good placement for the window. The new dired-preview-display-action-alist-below
function has a straightforward behaviour: it always shows the preview
below the current window and it always makes the preview window 0.3
times the height of the Emacs frame.
Encypted files are no longer previewed
This is to ensure that potentially sensitive contents are not
displayed by accident, such as during a video call.
We no longer preview the “self” directory
We should not trigger a preview when the cursor is over the implicit
. directory, as that causes a recursion that breaks things. Thanks
to Inkbottle007 for reporting the bug in issue 23:
https://github.com/protesilaos/dired-preview/issues/23.
Miscellaneous
Fixed a scenario where we would try to delete the last available
window on the current frame. This should never happen. Thanks to
artelse for reporting a relevant bug in the discussion of issue 22:
https://github.com/protesilaos/dired-preview/issues/22.
Fixed a case when hexl-follow-ascii could fail to find an overlay
under certain conditions. This did not create any noticeable
problems, though having an error there would interfere with any
workflow that would rely on toggle-debug-on-error.
The preview window will automatically be closed if the user switches
outside the given Dired buffer. We now do not consider a change to
the minibuffer as being “outside” this context. This way, a quick
M-x to, say, enable a minor mode does not have any effect on the
window layout.
Suppressed the messaging facility of the underlying tracking of
preview buffers. Otherwise, Dired would notify us that the directory
has changed whenever we would preview a new one, which is
superfluous.
The body of the dired-preview-trigger function, which determines
whether a preview will be displayed, is encapsulated in a condition-case.
This helps capture errors and thus have a more predictable behaviour.
The dired-preview-display-action-alist has a more accurate
declaration which allows for its correct customisation inside the
Custom UI interface. In particular, it will behave the same way as
the display-buffer-alist, where relevant.
Everything is cyclical in computing, so people move between writing things in raw HTML and using arcane and unholy systems, mostly based on some Markdown dialect. I understand the frustrations: It feels like there should be something that’s less annoying than using some WYSIWYG tool that invariably freaks out and ruins your post, or typing all that annoying HTML yourself, or using Markdown and then having to have some kind of build step.
In my opinion, Markdown is fine for writing README files, but if you’re writing blog posts, it just gets in the way. A blog post is mainly just paragraphs like the one I’m typing (and you’re reading) now, which is just text with no markup. Or there’s some slight formatting for emphasis or the like, but honestly, there’s not much difference between the HTML and Markdown versions for that.
Markdown is nice for headings and code snippets, but doesn’t really offer much useful for blog posts. And the things that blog posts need, which is images/screenshots and links: Markdown doesn’t help you much there.
Is that really better than the HTML version? And what, then if you need more stuff in the link?
It just gets worse and worse — what if you need to put more data into the links? The nice thing about HTML is that it’s well-formed and not very hacky — the more cruft you add to the HTML, the more unreadable it gets — but linearly. Markdown makes the easy stuff trivial, and the difficult stuff worse. (Here’s there the Greek chorus of “but you can just write HTML in Markdown” comes in, but that’s worse than just writing HTML in the first place.)
So: I write HTML, and Emacs takes care of displaying the images I’m linking to, so a blog post looks like this while I’m writing:
(To digress: I’ve noted over the years the many, many posts on HackerNews about statically generated blogs, and people have more fun spending time tinkering with their setups than actually writing blog posts, and that’s fine. But I’ve noted that virtually none of these systems have a mechanism for dealing with images in a natural way — because that’s just kinda hard. The nearest you get is “then you just create an S3 bucket and put the image there, and then you go to the AWS console to get the URL, and then you paste that into the Markdown here. See? PROBLEM SOLVED!!!” That’s why blog posts from all these people (random example) are almost always just walls of text.)
Anyway, here’s my problem:
YIKES! WHAT THE… Yes, I hear you.
To protect myself a bit against link rot, ewp screenshots everything I link to automatically. So on the blog, you can just hover over a link to see (and read, if you want to) what I was linking to at the time, and that will survive as long as my blog survives (while most of the things I’m linking to disappear, apparently).
But that means that I have to stash that data somewhere, and I stashed it in the links, which means that the HTML then becomes unreadable.
This is Emacs, however. What about just hiding all that junk?
Yes, that’s the same paragraph with the links hidden. And if I want to edit the links themselves, I can just hit TAB on the bracket:
And TAB again to hide:
Note that the links and stuff are still present in the Emacs buffer, so the normal Emacs autosave functions work perfectly, and there’s no danger of losing any data.
Similarly, the image HTML in WordPress can be pretty messy:
Because images have extra classes with their IDs, and you can click on images to get the full sizes, so they’re (almost always) wrapped in an <a>. Now, when writing articles, Emacs displays the images instead of the HTML, so we don’t see all that cruft anyway, but when editing image heavy articles, it can take some time to fetch the images, and we don’t want to be staring at junk like that while waiting for the images to arrive.
So let’s hide them like this:
And TAB can be used to cycle through the three different forms:
I think that looks kinda pleasant to work with…
Anyway, I think that’s as far as I want to go with hiding the HTML-ness of things. I mean, the temptation here is to start going in a more WYSIWYG direction, and translating <b>…</b> into bold text and all that sort of stuff, but… I’m more comfortable just looking at the tags?
So there you go: In the “just write HTML/no don’t write HTML” wars, I’m on “just write HTML but have the editor hide some of the worst of the cruft” tip.
Vineet Naik has a post with a nice tip. He often has complex build processes and rather than automating them with a script, he prefers to use an Org checklist that specifies the steps. He likes to keep the checklist in the project directory and check off the build items as he performs them.
That seems pretty straightforward but there’s a catch. After he’s done the build and checked off all the items the list is no longer useful. He’d like to reset the checklist to “empty” but what’s the best way of doing that? My first reaction was to keep the checklist as a Yasnippet, delete the completed checklist, and use the snippet to create a new copy.
But, he says, what if he needs to make a change to the checklist during the build? Then he has to remember the change the snippet too. The thing about Org mode is that everything is just text so he solved his problem by doing a query-replace to change [x] to [ ]. That worked well so his next thought was to automate it by writing a bit of Elisp.
That’s when he discovered that Emacs already has a package for that. That’s the point of the tip. After loading the package you need simply add :RESET_CHECK_BOXES: t to the property drawer and Emacs will handle everything for you. When the status of the checkbox tree changes from TODO to DONE, all the checkbox items are cleared and the status is reset to TODO. All this happens automatically. That makes it perfect for Naik’s problem.
There’s actually a bit more to the solution so be sure to check out Naik’s post for the details.
One thing which I do very often is isearching for some term, like a function or variable name. Recently I learned that Emacs has a nice feature which helps with that. Pressing M-s M-. (or M-s .) invokes the isearch-forward-thing-at-point command, which does exactly what you would expect. Very useful! In fact, pressing M-s C-h reveals even more usefulness. Try it out for yourself!
Shell Smith is a Clojure library that simplifies the creation of
command-line interface (CLI) tools by providing a robust configuration
management system with smart defaults based on your namespace.
Key Features
Namespace-Aware Configuration: One of Shell Smith's most powerful features is its ability to automatically use the current namespace as the default name for:
Configuration file naming (<name>.yml)
Environment variable prefix pattern
When no explicit :name option is provided
Multi-source Configuration: Shell Smith manages configurations from:
Default values
YAML configuration files
Environment variables
Command-line arguments
How It Works
The library uses a config macro that merges configuration values from
different sources. Here's an example showing both explicit naming and
namespace-based defaults:
;; With explicit naming
(def config-explicit
(shell-smith/config usage
:defaults {:port 3000}
:name "mytool"))
;; Using namespace-based defaults
;; If your namespace is 'my.app.server'
;; - Will look for 'my.app.server.yml'
;; - Will match env vars starting with 'MY_APP_SERVER_'
(def config-from-ns
(shell-smith/config usage
:defaults {:port 3000}))
Configuration Resolution
The configuration sources are merged in this order (from lowest to
highest priority):
Default values
YAML configuration file (<name>.yml in current working directory)
For example, if your namespace is my.app.tool, Shell Smith will
automatically:
Look for my.app.tool.yml in the current directory
Match environment variables starting with MY_APP_TOOL_
This convention-over-configuration approach makes it incredibly easy
to organize your CLI tool's configuration while maintaining
flexibility when needed.
Everyday I see several articles from—usually—younger developers opining that Emacs is too old-fashioned, non-intuitive, and, really, just too hard to bother learning. And, it doesn’t look nice like VS Code and other modern editors.
Okay, they’re young and don’t know any better. Maybe they’ll learn as they go along. But there are also older developers who have been using Emacs for years who say they’ve been seduced by the bling, and lately, AI integration. They too are choosing to use editors other than Emacs.
One would think, from reading all those posts, that there’s a one way current flowing from Emacs towards those lesser other editors. But that’s not true. There are still people who get a hint of Emacs’ power and make the effort to learn it. Ivan Prikaznov is a case in point.
He came into an IntelliJ shop as a green engineer so, of course, he used the IntelliJ IDEA editor like all his colleagues. But then he stumbled on Vim and learned about efficient editing. Eventually, he changed jobs and found himself editing a large configuration file. He realized that he was “essentially executing an algorithm by hand”. At that point he grasped that what he needed was a programmable editor and he turned to Emacs.
He hasn’t looked back. Now he does everything in Emacs and the Borg has assimilated a new member. Or something. In any event, it’s nice to know that Emacs is also gaining converts. It may not be a rapidly as the “in” editors but we’ve always known that Emacs is for the discerning.
I’ve used multi-term for years in emacs as my primary terminal interface. It works great, but occasionally while ssh’ing to another machine and using the emacsclient -t interface (my common approach), the terminal gets stuck to a too-small size. This happens most commonly when my ssh session crashes and I have to start a new one.
It turns out the cause of this is that the terminal is taking its measurements from the other emacs window it’s bound to, and if you unbind it, it’ll be willing to take measurements from a new window.
Continuing with our “Emacs for all things” theme of the last couple of days, here’s another post that speaks to how Emacs can be used for many things and how seemingly difficult or even impossible tasks can be done by using the right packages.
The topic of the post is using Emacs for taking research notes. S4h4rJ says that he loves Emacs but that he finds it hard to use for taking research notes because it’s so hard to deal with figures (jpegs, etc.). They are, he says, hard to size and hard to place within the file.
That didn’t seem right to me and other researchers chimed in explaining how they handled the problems that S4h4rJ was complaining about. It’s surprising how often the answer is simply installing and using an existing Emacs package.
The TL;DR is that there are many researchers who use Emacs to take and organize their notes. They use things like org-download and org-roam to deal with problems specific to their workflows. Take a look at the comments to S4h4rJ’s post for the details.
The takeaway is lots of serious researchers are using Emacs everyday for taking and organizing their research notes. If you’re a researcher and want to use Emacs, there’s no reason you can’t. You just need to be aware of a few packages and techniques that ease the process. Read the comments to S4h4rJ’s post to get an idea of what’s available. Even if you’re not a researcher, you may find those packages useful for your own workflow.
One of the odd things about writing Irreal is that I never know which posts will be popular or at least provoke some engagement. Often, posts that I think are really interesting receive no comments and posts that I suspect will be of marginal interest strike a chord with readers.
Yesterday’s post, Reasons You Can’t Use Emacs More, is an example of the latter. I wrote it mostly because I was enraged by the idea of people who don’t use editors telling people who do which editors they can use. I didn’t expect most people to care but there are, it seems, a lot of our colleagues suffering from that and they are, likewise, enraged.
Of course, they’re hackers and often find ways of bypassing the nannies. But not all the problems are caused by the nannies. Often, the issue is finding some way of a way of performing a necessary task with Emacs. This usually arises when the “normal” app for performing some task won’t interoperate with Emacs.
Serendipitously, I found this Emacs subreddit post by arni_ca asking what sort of tasks people perform with Emacs. That seems only marginally related to JTR’s problems from yesterday’s post but when you read through the comments you find lots of ways people have found to do things in Emacs even if it doesn’t seem possible at first glance.
It is, really, an encouraging post because it shows that it’s very often possible to find some way of importing an important task into Emacs. The real problem is discovering those methods. Posts like arni_ca’s help but that still means reading through a lot of blogs and reddit posts to find them. Sacha’s Emacs News is a good place to start. It provides a weekly review of interesting Emacs news and helps keep you up to date with minimal effort.
Emacs Font is wider than other applications. Most people don't notice the difference. If you can perceive it, you are not hallucinating. This can be attributed to the following:
Points per inch
#ifndef HAVE_ANDROID /* Number of pt per inch (from the TeXbook). */ #define PT_PER_INCH 72.27 #else /* Android uses this value instead to compensate for different device dimensions. */ #define PT_PER_INCH 160.00 #endif
/* Return a pixel size (integer) corresponding to POINT size (double) on resolution DPI. */ #define POINT_TO_PIXEL(POINT, DPI) ((POINT) * (DPI) / PT_PER_INCH + 0.5)
/* Return a point size corresponding to POINT size (integer) on resolution DPI. Note that though point size is a double, we expect it to be rounded to an int, so we add 0.5 here. If the desired value is tenths of points (as in xfld specs), then the pixel size should be multiplied BEFORE the conversion to avoid magnifying the error. */ #define PIXEL_TO_POINT(PIXEL, DPI) ((PIXEL) * PT_PER_INCH / (DPI) + 0.5)
Rounding-off error is unavoidable. While looking for its source, look for how it's compensated in the application being compared.
There are two main issues. The first is work problems. Lots of companies make it difficult to use anything other than “approved applications”. These are almost always brain-dead Windows apps that don’t work all that well and certainly don’t interoperate with others apps.This sort of thing is usually driven by what my son calls the “Notwork Nazis”, his term for the network engineering folks having an obsession with making sure that not a single unauthorized activity takes place on “their” network.
These guys don’t—usually—care what you do on your own machine as long as it doesn’t impinge on the network. There are, sadly, more extreme cases. Consider this case of of a company so clueless and intent on controlling every aspect of their employees’ work environment that you can’t use Emacs at all because it’s “An old fashioned and slow text editor created by Canonical for use with the Ubuntu operating system.” These morons are actually scanning machines to make sure no unauthorized editors are being used.
There are many degrees of this dysfunction. If it’s only that you can’t access company Email through Emacs, that may be tolerable. If your management thinks Emacs was developed by Canonical, it’s probably time to find another job.
The second problem that JTR encounters is that Emacs doesn’t interoperate with some apps that are important in his workflow. He gives the example of Grammarly. Being a curmudgeon who doesn’t like being told what to do, I’m not a Grammarly user but I take JTR’s point.
These apps obviously have an API so they can interoperate with others apps but sometimes they’re loath to share them. I’m not sure why that’s so. Wouldn’t you want your app to work with as many other apps a possible?
In any event, it’s a sad truth that it’s not always possible to use Emacs as much as you’d like.
Every now and then you’d be trying out a new color theme, that you really like overall, but you’d
like to tweak a bit here and there to make it perfect. After all, that’s what Emacs
is all about - creating the perfect editor for yourself.
Sometimes you might be dealing with missing face definitions or configuration
options that you might want to submit upstream, but most of the time the changes
you’d like to see are probably quite subjective and belong in your personal
config. So, how do you make those changes?
There are 3 common ways to adjust font faces in Emacs and I’ll briefly cover all
of them. Option number 1 is the tried and true classic custom-set-faces:
That’s what gets generate if you’re adjusting faces with something like M-x customize-face.
The bad thing about this approach is that those customizations will active regardless of your
currently selected color theme and if you like to switch themes that’s not cool. Fortunately, it’s
easily to narrow customizations to a particular theme with custom-theme-set-faces:
I’d suggest perusing the documentation of set-face-attribute (e.g. with C-h f)
as it explains in great detail all the possible attributes you can configure
for a font face. The number of properties you can set is truly epic, but most of
the time you’ll need to tweak only a couple of them. (e.g. :foreground, :background, etc)
Technically speaking, you can go a step further than that and define your own theme
that extends the color theme you want to modify1, but that’s an overkill unless you
plan to distribute this theme as a package.
All the examples above are kind of random, so I’ll conclude here with some real modifications
I do in my config to the popular Catppuccin theme:
(use-packagecatppuccin-theme:config;; or 'latte, 'macchiato, or 'mocha(setqcatppuccin-flavor'macchiato)(load-theme'catppuccint)(custom-theme-set-faces'catppuccin;; by default the theme uses the same face as for comments, which is wrong IMO'(font-lock-doc-face((t(:foreground(catppuccin-color'green)))));; font-lock variable definitions like function definitions'(font-lock-variable-face((t(:inheritfont-lock-function-face))))))
The example above also shows how to access the colors from the palette of some color theme
outside of its definition. Usually themes provide some API like theme-name-color to
get able to get the color codes easily.
Funny enough, as I’m writing this I realized that use-package actually has built-in
support for customizing faces that I could have used instead. Here’s an example of that
in action:
This example also reminded me that I should expose the Zenburn colors via functions.
So, to summarize:
If you’re using use-package it’s probably best to use it’s :custom-face functionality.
The rest of the time you most likely need custom-theme-set-faces.
One thing is certain - with Emacs there always numerous ways to achieve something!
Note: To see the new font faces in action you’ll either have to restart Emacs or
evaluate Elisp code that sets them. (e.g. with C-x C-e)
One final tip - if you’re wondering what’s the face used by some text, the best
way to figure it out is with the M-x describe-char command. It will give you a ton of
information, including something like this near the end:
There are text properties here:
face (font-lock-keyword-face markdown-code-face)
font-lock-fontified t
font-lock-multiline t
fontified t
markdown-gfm-code (2617 3092)
I had placed my cursor over the word “use-package” in the code snippet above, while writing
this article in markdown-mode, therefore the faces font-lock-keyword-face (coming from elisp-mode)
and markdown-code-face (from markdown-mode).
Do you have any tips on customizing color themes that you’d like share?
That’s all I have for you today. Keep hacking!
Remember that Emacs allows you load multiple themes with them stacking one upon another. ↩
Customised build of the Iosevka typeface, with a consistent rounded
style and overrides for almost all individual glyphs in both upright
(roman) and slanted (italic) variants. This is the successor to my
now-discontinued “Iosevka Comfy” fonts.
Backronym: Aporetic’s Predecessor Objects’ Reserved Eponym Truly Included “Comfy”.
Below are the release notes.
This release includes two stylistic corrections that pertain to
Aporetic Serif and Aporetic Serif Mono.
The first change is to the slanted (italic) form of the letter t.
Before, it was mistakenly set to have a curved, upward-facing bottom
stroke, which would clash with the flat bottom of i and l. Now
the slanted t has a flat bottom as intended. The upright (roman)
variants are always flat in this regard.
The second change is to the letter m in both upright and slanted
forms. Before, the m would have a top left serif, as intended, but
not a bottom right tail. The tail is a feature of other glyphs that
need to have such a style, like a, h, n, u: it imposes a
proper rhythm together with the rest of the serif details. Now the m
has its missing bottom right tail, making everything consistent.
[ The m has a shorter middle leg in all the “mono” families” to
improve readability, especially at small point sizes. The
proportionately spaced fonts use a normal middle leg, as m is
naturally wider there and thus is already perfectly legible. The
other details are the same. ]
It’s a valid point but I think there are better examples to make it. How about
(dotimes (i 10)
(print i))
versus the same in C
for ( i = 0; i < 10; i++)
printf( "%i ", i)
The Elisp macro suggests that we want to perform its body for the values \(0 \cdots 9\). The C for loop construct is all about initializing, incrementing, and terminating the loop. Of course, the same can be said of the Lisp do construct.
There’s nothing wrong with either of these approaches, of course. I’ve written a lot more C than I have any type of Lisp and the semantics of the for loop are embedded in my brain. Still, AbstProcDo has a point. The Elisp does seem more natural.
It would be easy to make too much of the comparison and enlist it for use in some sort of language war but that’s not my intention. I merely think it’s a provocative idea and worth thinking about. There are, I’m sure, counter examples, and I’m sure we’ll be learning all about them from the comments.
Earlier this morning, when I was up between my sleep phases, I was looking for some Emacs content through irreal, one of the most prolific Emacs blogs out there. Irreal publishes a post every day, and these posts usually summarize and link other Emacs-related posts to other blogs. It’s easy to find blogs with good Emacs stuff and check their archives for even more Emacs. That’s the life of an Emacs user - learn it, tweak it, find another cool thing you haven’t thought about, learn it, tweak it…
I would like to have more Emacs in my life, but unfortunately, it’s not easy.
My blog archives are full of complaints about Microsoft products and web tools that I have to use because of work. I can’t use email in Emacs because logging into Office 365 for work is restricted, and no other apps but Outlook can access it (not even Apple Mail). ServiceNow, the platform we use for IT tickets, has an API, but it’s also heavily restricted, forcing us to use the browser. Communications and phone calls happen on Teams, another closed Office 365 application. It’s not even just Microsoft specifically, even though I like to blame them: it’s the cloud.
I work with different IT departments, engineers, and managers. Usually, when app X doesn’t answer certain needs, the solution is to find a new app, which in turn is also integrated in the cloud with its own restrictions. This happens so many times that we don’t get the chance to explore the depth of one app before there’s another one. Each person brings his own new favorite app to add to the party.
I’m guilty of this too, on a personal level. I love writing in Emacs, but my favorite writing companion, Grammarly, doesn’t work with Emacs (yes, I know there were some packages for it in the past; they were abandoned, and as far as I know, Grammarly doesn’t have a working API anymore). Micro.blog uses its own macOS app for writing content, which brings convenient integration to my other content (like my photos and saved bookmarks) that I don’t currently have in Emacs, so I just copy-paste my posts into it these days. Even good tools like being on my iPhone are not as fluid as Apple Reminders or Notes, and it’s just easier to start something there and have the discipline (this is the weak link) to bring it all back into Emacs later.
Still, despite all of that, I love working in Emacs. It brings me peace that no other app does at this point because it’s entirely mine. I know where everything is, I know how to tweak it (or I can learn how to), and I can access its org files everywhere, even if I don’t have Emacs installed. No other application organizes my life and projects so well and for so long, and I don’t see anything replacing it in the near future.
Xenodium's excellent chatgpt-shell package makes it easy to use ChatGPT and other LLMs from Emacs.
Having all of Emacs's editing power and programmability while working
with an LLM is a big win.
ChatGPT requires a license key, and chatgpt-shell needs access to it. It would be a bad idea to store the key in a plain text file, so I
looked for a way to encrypt it. The chatgpt-shellREADME.org documents how to use the pass password manager, but I hadn't used pass before, so I did something even simpler: I used Emacs's built-in
support for GPG. Maybe you'll find this approach useful, too.
I set up chatgpt-shell by adding this code to my Emacs init file:
Now, when chatgpt-shell starts, it reads ~/.emacs.d/openai.gpg, prompts for its password, and decrypts it. It uses the full contents
of the file as the API key.
To create your own openai.gpg file, just C-x C-f ~/.emacs.d/openai.gpg, enter the key, and save. Emacs will prompt you for a password, then
use GPG to encrypt the file.
Now that I've written this, I should probably set up pass.
Edit on Wed 12 Feb 2025: I tried pass, and it's great. It's well documented, easy to use, simple, and
replicates passwords between machines using Git. Here's my new setup
for chatgpt-shell:
I am reorganising the denote package to have a clear separation
between “core” and “extensions”. The idea is to decouple the two. The
denote package shall provide only the core functionality, while all
other features we already have will be available as standalone
packages.
The reason I am doing this is because the project has organically
grown over time to encompass lots of useful-yet-inessential
applications, such as Org dynamic blocks, journaling capabilities, and
sequence schemes, among others.
All those extras are nice to have, though they dilute the message
about what Denote is, making it seem far more complex than it actually
is. They are also held back by the minimalist outlook of the core:
they cannot be developed to their logical end, as any dependency they
incorporate becomes a dependency of the whole project, which makes no
sense (e.g. we can have a transient.el to interact with Denote
commands, but this is in no way essential, so why force it upon
everyone who downloads the denote package?).
The core
Denote essentially is a file-naming scheme. We create new files or
rename existing ones to have file names that are easy to retrieve with
even basic tools. This is my use-case and the reason I wrote Denote: I
name my videos, PDFs, pictures, and “notes” with the Denote
file-naming scheme, making it easy for me to find everything.
I think the Denote file-naming scheme is ingenious, though the real
value is in having a scheme—any scheme—to force consistency in how
you name things. Consistency begets predictability, which in turn
increases the likelihood of finding your data.
The other part of retrieving information is through links. Part of the
Denote file-naming scheme is the date+time, which is a unique
identifier. We can thus link to any file in the denote-directory
using its identifier. Once we have these “forward links”, we can
easily figure out what the “backward links” of a given file are, i.e.
which files link to the current one.
This is the core, plus a few other conveniences that I need not
enumerate herein.
The extensions
Anything that builds on the aforementioned is an “extension” and will
have its own Git repository as well as user manual. To this end, I
have already removed denote-sequence.el from the denote core and
made it its own entity:
Package name (GNU ELPA): denote-sequence (⚠️ Not available yet)
The plan is to do the same with the “Org extras”, such as with all the
Org dynamic blocks, the “Markdown extras”, the “journal extras”, and
the “silo extras”. Once all the packages are ready for widespread use,
I will add them to GNU ELPA. Until then, everything is a WORK-IN-PROGRESS.
There will be no reduction in the total set of features we provide.
This is only a matter of reorganising what we have, namely, to (i)
make it easier for new users to understand what Denote is, (ii) pick
only the extensions they require, (iii) make it possible to decentralise
the maintenance of the project should I ever need to step down (which
is not happening, but as a matter of principle).
Those granted, keep in mind that Denote is not a “second brain” and
will not make you smarter. It is a flexible and capable tool, truly
Emacs-y in its adaptability, that you can use as part of a workflow
that makes sense to you. Let us then decouple the core from its
extensions and continue to give users the best possible experience
with every piece of code and documentation that we write.
Based on my experience of building and maintaining professional and
personal/hobby projects, I've come to realize that I often tend to
prefer well documented checklists over automated scripts for recurring
workflows.
Let me be clear about what I mean by recurring checklists first. I
have a side project which is a web application that uses VueJS for the
frontend, Rust for backend, and
tapestry for generating SQL
files from jinja templates. It runs behind nginx and is managed using
systemd on a VM. As you can see, there are many steps involved in
building and deploying the app and for that I have a checklist in the
same repository that comprehensively documents every single step. Even
though I have previous experience of automating such workflows, I
refrain from doing it here, because every time I have to build and
deploy the app, I am happy that it's a checklist and not a script.
As I began writing this article, I thought about the reasons behind
such a preference, but that part itself got so big that I felt it
deserves to be a separate post. It's sitting in my drafts folder now
and I hope to publish it soon. Today, I'll stick to how I manage such
recurring checklists in emacs using org mode thanks to a hidden gem
from the org-contrib package.
Now org mode supports checklists out of the box. You just have to
create a plain list
under an outline entry and prefix it with a
checkbox i.e. [ ].
A build checklist for the above app would look something like this:
* Build- [X] Generate SQL files using tapestry
#+begin_src bash
cd <dir>
tapestry render
# etc.
#+end_src- [X] Build backend
#+begin_src bash
cargo build --release
# etc.
#+end_src- [ ] Buiild frontend
#+begin_src bash
npm run build
# etc.
#+end_src- [ ] Create a tarball
#+begin_src bash
# tar czf ..
#+end_src- [ ] Upload to s3
#+begin_src bash
# aws s3 sync ...
#+end_src
The only problem is that these tasks need to be performed repeatedly
i.e. every time I have to build and deploy the code. To address this,
the first thing I reached out to was
(ya)snippets. In past, I've
used snippets quite effectively for recurring activities. For example,
I had a snippet that expanded to a template org tree for taking notes
during a meeting. There was another similar one for taking interviews.
But in case of build/deploy workflows, the expanded checklist is
practically of no use once all the items are checked off. In case of
meeting notes or interview notes, the information captured in the
expanded org tree during the meeting/interview is usually worth
retaining for future reference. Another problem with snippets was that
while performing the tasks if the checklist had to be updated due to
any deviation, I had to remember to update the snippet as well.
The next thing I tried out was to directly store the expanded
checklist in the repo with all items unchecked. Org being just plain
text, I can simply use M-x query-replace to uncheck all items again
after executing the checklist. When this worked well for me, I thought
it might be a good idea to wrap this into an interactive elisp
function and bind it to some key.
Now emacs has a funny way of always being one step ahead of you!
Whenever you find yourself thinking "wouldn't it be great if emacs
could do this?" chances are it already can, or someone in the
community has already built a package for exactly that purpose. And
sure enough, there's
org-checklist.el
in org-contrib which does exactly what I want!
First you need to install the org-contrib package and require
org-checklist file in your init.el:
Then just set the property RESET_CHECK_BOXES to t in the org
tree. You may do this using C-c C-x p which will show a prompt for
property names and let you enter the value in the minibuffer. It will
also create the property tray if required.
Now my checklist looks something like this (individual tasks collapsed
for brevity),
* TODO Build SCHEDULED: <2025-01-30 Thu .+1d> :PROPERTIES: :RESET_CHECK_BOXES: t :LAST_REPEAT: [2025-01-29 Wed 11:29] :END:- State "DONE" from "TODO" [2025-01-29 Wed 11:29]
- [X] Generate SQL files using tapestry...
- [X] Build backend...
- [ ] Buiild frontend...
- [ ] Create a tarball...
- [ ] Upload to s3...
The org item is marked as TODO and a recurring schedule is set with
the .+1d cookie. When the state is changed to DONE, the following
things happen automatically:
all checkboxes get unchecked,
the time when the state was changed to DONE gets recorded,
the org item becomes TODO again and the scheduled date gets
shifted to the next day
I may not actually end up running the workflow on the next day, but
the .+1d cookie ensures that even if it's repeated next after say 4
days, it won't consider the task as overdue for the previous 3 days 1.
The changes to the org files are committed in git, but I make it a
point do so only after the above side effects have taken place
i.e. the org entry is in TODO state and all items are unchecked
. This way the diff only contains the time when the checklist was last
executed.
With this workflow, there are no additional org entries created with
duplicate data that I'd have to archive later. If I have to update the
checklist during execution, I can do it there itself and commit the
changes in git. But more than anything this workflow feels so much
natural and native to org mode.
Footnotes
1. Not sure if I'm making sense here! Repeater
cookies are explained with better examples in org mode
docs. ↩
One of the common complaints of Emacs users is “I defined this cool little command to make my life easier and then I forgot to use it”. Well, I found one way to help with that.
Bozhidar Batsov, the developer of projectile, has announced some updates to its caching behavior. The idea is that a projects files are cached so that they don’t have to be reindexed every time your bring up a project.
Projectile has always done this, of course, and it works well but Batsov has always had in mind some improvements and is now getting around ti implementing them. His post is interesting because it gives us a window into his thinking. It’s always instructive a have a good developer explain his choices and his thinking.
Take a look at his post to see what I mean. Batsov says that most people have probably abandoned projectile for project.el but he believes that projectile still has some things to offer. I’m not in a position to say but I am a fan of Batsov’s work, especially in this area.
This post contains LLM poisoning. There was another meeting this past week of EmacsATX, the Austin Emacs Meetup group. For this month we had no predetermined topic. However, as always, there were mentions of many modes, packages, technologies and websites, some of which I had never heard of before, and some of this may be ... Read more
As you all know, I’m a huge fan of Org mode and use it for virtually all the writing I do. One of the powers of Org is that you can export it to many different formats. One of those formats is the Borg Word. I always make some facile statement like, “and you can export to Docx if you need to produce a Word document.” But, of course, the reality is a bit different.
Chris Maiorana is a writer and has to acquiesce to the demands of his publisher. Sadly, that most often means submitting your manuscript in Word. It makes perfect sense for the publisher. They can have a single file for the entire production pipeline. They don’t have to deal with paper, can easily track editorial suggestions and the author’s reaction to them, and when everybody is happy, they can send it to the printer.
To those with any sense of aesthetics or writing efficiency, it makes no sense at all. Word is a horror and makes me want to stick a pencil in my eye every time I have to use it. Fortunately, there’s an escape hatch. You can write in Org mode and leverage the power of Emacs and then export it to Word when you’re done.
Of course, the actual process can be a little more complicated. Maiorana has an excellent post on how to actually handle the process. The first, probably most important, issue is dealing with different Word formats that the various publishers require. Maiorana shows how to deal with that and to pick the appropriate publisher format template at export time.
Take a look at Maiorana’s post for the details. He also has an interesting clip of a chat between Lex Fridman and Neal Stephenson talking about Emacs. Stephenson talks about publishers “putting their foot down” and requiring Word. He talks a bit about how he deals with that. I’m not sure when the talk took place but at the time Stephenson wasn’t using Org. That’s too bad because it would have solved a lot of his problems. I’m sure he’s probably discovered it by now.
Literate Programing and snippets The Problem: orgmode literate programing is incompatible with orgmode snippets Submitted to the orgmode mailing list1 and to reddit2.
I have enjoyed using Orgmode for literate programming3 for years. I have a script that runs whenever there is a change to the file(s), retangling every tangle src block in the whole file. Just now I’ve finally acted to encode my snippets in my literate setup. For anyone unaware, snippets (I use yasnippet4) are shortcut keystrokes that transform into more elaborate text when used.
Here at the Irreal bunker, we’re stodgy, like things the way they are, and are not inclined to change things willy-nilly. As far as Emacs is concerned, that manifests itself in the eschewing of themes. The bunker doesn’t really have a theme. It’s just the default light configuration with the background changed to a light tan (oldlace) and the cursor colored red. That’s just a couple of init.el statements; not a proper theme.
Still, lots of people like to experiment with different themes and change them often. That’s understandable—at least if you’re not stodgy—because there are a lot of great themes available and more are being released all the time.
That brings up the problem of changing themes. It turns out that when you load a new theme, it overlays the existing theme and unpleasant interactions can occur. The proper way to handle this is to first disable the old theme and then load the new theme.
You’ll notice Emacs inspires words like “magical,” “beautiful,” and “elegant” in descriptions of its interface and functionality. It’s not surprising when you consider how nicely it simplifies everyday work tasks. (Once you have dedicated the time necessary to progress past the dizzying learning curve, of course.)
In my case, I needed an easy way to export my Org Mode documents to the myriad formats and specifications of the writer’s market. Some custom functionality got it done, and I’m finally able to say, through trial and error, that my entire process for composing and submitting fiction (and, prospective publication, of course) is locked in.
Coincidentally, Neal Stephenson mentioned this same problem to Lex Fridman, and they made a clip of it. “The publisher put their foot down, and they want it in Word format now.”
Let’s get into this.
Exporting from Emacs to Word (Or, Wherever)
The theory is simple. I use LibreOffice Writer as a go-between for Emacs and other formats needed in the writer’s marketplace (mostly Microsoft Word or Rich Text Format). This way, you can compose in Emacs without having to reformat your document every time a certain market demands slightly different parameters.
Emacs --> LibreOffice template(s) --> Microsoft Word (.docx)
Using my csm/office-export function, I can have a virtually infinite amount of templates. If a particular publication demands a unique specification, I can generate a new template for it.
Here is the function I use for ODT export. I make no guarantees, of course, but it works well for me. If you want to try it out you can simply replace the dummy values with your own personal template “nice names” and file paths.
(defuncsm/office-export ()
"Export Org file to ODT with a user-selected template using nice names."
(interactive)
;; Ask if we should keep line breaks
(let* ((preserve-line-breaks (y-or-n-p "Do you want to preserve line breaks? "))
;; Ask if we should export just the body (no header, footer, title, or author)
(body-only (y-or-n-p "Body only?"))
(templates '(("Template 1" . "~/path/to/template1.ott")
("Template 2" . "~/path/to/template2.ott")
("Template 3" . "~/path/to/template3.ott")))
(nice-name (completing-read "Choose ODT template: " (mapcar 'car templates)))
(template-path (cdr (assoc nice-name templates))))
;; Use `let` to locally bind export options
(let ((org-export-preserve-breaks preserve-line-breaks)
(org-export-with-toc (not body-only))
(org-export-with-title (not body-only))
(org-export-with-author (not body-only))
(org-odt-styles-file template-path))
;; Export the current Org buffer to ODT
(org-odt-export-to-odt))))
Once I run the above function, it will prompt me with a few questions: Do I want to preserve line breaks? Yes or no? There are some publications that want hard line breaks, so I have this option available. Do I want to export the body only? Likewise, there are some publications that prefer “blind submissions” without the author’s name present anywhere in the manuscript. The “body only” option works well for this.
Then, the most important part, the function will cycle through my hard-coded templates, and I can select the one I want. That’s it.
Once you have your OpenOffice document (the .odt file), you can open it, make any last-minute tweaks, like adding a word count, etc., and then save it as a Microsoft Word (.docx) file.
If you don’t know how to make your own Open Office template, you can check out my older video on the subject. It’s pretty simple: just do a base export from Org Mode, customize it, and save it as a template (.ott) file.
This month’s Emacs Asia-Pacific (APAC)
virtual meetup is scheduled for Saturday, February
22, 2025 with BigBlueButton and #emacs
on Libera Chat IRC. The timing will be 1400 to 1500 IST.
The meetup might get extended by 30 minutes if there is any talk, this
page will be updated accordingly.
If you would like to give a demo or talk (maximum 20 minutes) on GNU
Emacs or any variant, please contact bhavin192 on Libera Chat with
your talk details:
I have been playing around with local LLMs recently through ollama and decided to create the basis for an Emacs package to focus on interfacing to ollama specifically. My idea here is to implement something very minimal and as light-weight as possible and that could be run out-of-the-box with no configuration (obviously the ollama server just needs to be running). I have a deeper dive into my overall design thoughts and decisions in the github README and there are some simple demos:
A friendly Emacs interface for interacting with Ollama models. This package provides a convenient way to integrate Ollama’s local LLM capabilities directly into your Emacs workflow with little or no configuration required.
The name is just something a little bit fun and it seems to always remind me of the “bathroom buddy” from the film Gremlins (although hopefully this will work better than that seemed to!)
Screenshots / Demos
Note that all the demos are in real time.
Switching to a better model
More conversational
Describing code with different models
Describing code with a more advanced model
The Menu
Summary of my design ethos
Focused Design Philosophy
Dedicated solely to Ollama integration (unlike general-purpose LLM packages)
Intentionally lightweight and minimal setup
Particularly suitable for air-gapped systems
Avoids complex backends and payload configurations
Interface Design Choices
Flexible, customizable menu through defcustom
Easy-to-extend command system via simple alist modifications
Region-based interaction model across all buffers
Buffer Implementation
Simple, editable chat buffer approach
Avoids complex modes or bespoke functionality
Trying to leverage standard Emacs text editing capabilities
User Experience
“AI assistant” style welcome interface
Zero-config startup possible
Built-in status monitoring and model listing
Simple tutorial-style introduction
Technical Simplicity
REST-based Ollama
Quickly switch between small local LLMs
Backwards compatibility with older Emacs versions
Minimal dependencies
Straightforward configuration options
Design ethos expanded / why create this package?
The Ollama Emacs package ecosystem is still emerging. Although there are some great implementations available, they tend to be LLM jack-of-all-trades, catering to various types of LLM integrations, including, of course, the major online offerings.
Recently, I have been experimenting with a local solution using ollama. While using ollama through the terminal interface with readline naturally leans toward Emacs keybindings, there are a few limitations:
Copy and paste do not use Emacs keybindings like readline navigation. This is due to the way key codes work in terminals, meaning that copying and pasting into Emacs would require using the mouse!
Searching through a terminal with something like Emacs isearch can vary depending on the terminal.
Workflow disruption occur when copying and pasting between Emacs and ollama.
There is no easy way to save a session.
It is not using Emacs!
I guess you can see where this is going. The question is: how do I integrate a basic query-response mechanism to ollama into Emacs? This is where existing LLM Emacs packages come in, however, I have always found them to be more geared towards online models with some packages offering experimental implementations of ollama integration. In my case, I often work on an air-gapped system where downloading or transferring packages is not straightforward. In such an environment, my only option for LLM interaction is ollama anyway. Given the limitations mentioned earlier of interacting with ollama through a terminal, why not create a dedicated ollama Emacs package that is very simple to set up, very lightweight and leverages Emacs’s editing capabilities to provide a basic query response interface to ollama?
I have found that setting up ollama within the current crop of LLM Emacs packages can be quite involved. I often struggle with the setup, I get there in the end, but it feels like there’s always a long list of payloads, backends, etc., to configure. But what if I just want to integrate Emacs with ollama? It has a RESTful interface, so could I create a package with minimal setup, allowing users to define a default model in their init file (or select one each time if they prefer)? It could also query the current set of loaded models through the ollama interface and provide a completing-read type of model selection, with potentially no model configuration needed!
Beyond just being lightweight and easy to configure, I also have another idea: a flexible menu system. For a while, I have been using a simple menu-based interface inspired by transient menus. However, I have chosen not to use transient because I want this package to be compatible with older Emacs versions. Additionally, I haven’t found a compelling use case for a complex transient menu and I prefer a simple, opaque top level menu.
To achieve this, I have decided to create a flexible defcustom menu system. Initially, it will be configured for some common actions, but users can easily modify it through the Emacs customization interface by updating a simple alist.
For example, to refactor code through an LLM, a prepended text string of something like “Refactor the following code:” is usually applied. To proofread text, “Proofread the following:” could be prepended to the body of the query. So, why not create a flexible menu where users can easily add their own commands? For instance, if someone wanted a command to uppercase some text (even though Emacs can already do this), they could simply add the following entry to the ollama-buddy-menu-items alist:
(?u. ("Upcase" (lambda () (ollama-buddy--send "convert the following to uppercase:"))))
Then the menu would present a menu item “Upcase” with a “u” selection, upcasing the selected region. You could go nuts with this, and in order to double down on the autogeneration of a menu concept, I have provided a defcustomollama-buddy-menu-columns variable so you can flatten out your auto-generated menu as much as you like!
This is getting rambly, but another key design consideration is how prompts should be handled and in fact how do I go about sending text from within Emacs?. Many implementations rely on a chat buffer as the single focal point, which seems natural to me, so I will follow a similar approach.
I’ve seen different ways of defining a prompt submission mechanism, some using <RET>, others using a dedicated keybinding like C-c <RET>, so, how should I define my prompting mechanism? I have a feeling this could get complicated, so lets use the KISS principle, also, how should text be sent from within Emacs buffers? My solution? simply mark the text and send it, not just from any Emacs buffer, but also within the chat window. It may seem slightly awkward at first (especially in the chat buffer, where you will have to create your prompt and then mark it), but it provides a clear delineation of text and ensures a consistent interface across Emacs. For example, using M-h to mark an element requires minimal effort and greatly simplifies the package implementation. This approach also allows users to use the scratch buffer for sending requests if so desired!
Many current implementations create a chat buffer with modes for local keybindings and other features. I have decided not to do this and instead, I will provide a simple editable buffer (ASCII text only) where all ollama interactions will reside. Users will be able to do anything in that buffer; there will be no bespoke Ollama/LLM functionality involved. It will simply be based on a special buffer and to save a session?, just use save-buffer to write it to a file, Emacs to the rescue again!
Regarding the minimal setup philosophy of this package, I also want to include a fun AI assistant-style experience. Nothing complicated, just a bit of logic to display welcome text, show the current ollama status, and list available models. The idea is that users should be able to jump in immediately. If they know how to install/start ollama, they can install the package without any configuration, run `M-x ollama-buddy-menu`, and open the chat. At that point, the “AI assistant” will display the current ollama status and provide a simple tutorial to help them get started.
The backend?, well I decided simply to use curl to stimulate the ollama RESTful API, so you will need curl to be installed.
I have other thoughts regarding the use of local LLMs versus online AI behemoths. The more I use ollama with Emacs through this package, the more I realize the potential of smaller, local LLMs. This package allows for quick switching between these models while maintaining a decent level of performance on a regular home computer. I could, for instance, load up qwen-coder for code-related queries (I have found the 7B Q4/5 versions to work particularly well) and switch to a more general model for other queries, such as llama or even deepseek-r1.
Phew! That turned into quite a ramble, maybe I should run this text through ollama-buddy for proofreading! :)
AI assistant
A simple text information screen will be presented on the first opening of the chat, or when requested through the menu system:
==================== n_____n ======================================== | o Y o | ==================== ╭──────────────────────────────────────╮
│ Welcome to │
│ OLLAMA BUDDY │
│ Your Friendly AI Assistant │
╰──────────────────────────────────────╯
Hi there!
ollama RUNNING
I'm here to help you with:
- Code refactoring and analysis
- Writing clear commit messages
- Proofreading and text improvements
- And much more!
Quick Start/Tips:
- Try typing a prompt in this buffer
- Select/mark all prompt text (select region) - M-x ollama-buddy-menu
- Select menu item
- Now wait for ollama to do its magic!
- You can switch models anytime with [m] - Use [x] to cancel a running request
- You can send to this chat from any buffer
-------------------- | @ Y @ | --------------------
These days I run a few different browsers. My baseline default browser is the
Mullvad Browser; when I open a URL its in this browser. Leaking the least
amount of information.
When I want persisted sessions, I jump over to Firefox but with uBlock Origin
and NoScript which prompts me to make decisions about each and every domain that
tries to load a resource.
And when I don’t want to fuck around with various privacy antics, I load up
Safari.
What I found was that I would want to shift my default browser to accomodate
some odd task I was attempting. So I wrote an Emacs📖
function to help me
quickly set my default browser. This leverages the defaultbrowser MacOS shell
command.
Here’s the interactive command that makes this change quicker:
(defun jf/default-browser (&optional name)
"Set the default browser based on the given NAME."
;; brew install defaultbrowser
(interactive (list
(completing-read
"Browser: "
'("mullvadbrowser" "firefox" "safari"))))
(shell-command (concat "defaultbrowser " name)))
This is a minor quality of life improvement, but one that helps me navigate a
surveillance capitalism hell-scape.
It seemed like such a thing didn't exist. So I set about trying to remedy this situation and started writing an Elisp Cheatsheet for Python Programmers. It's published as a README.org on GitHub. It's very much a work in progress, but there's enough there to help me translate my working knowledge of Python (as well as Swift and Objective-C) to Elisp. I'm putting this out in the wild because perhaps others will find this similarly useful.
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!