Org Mode requests: [FR] ox-md: Verbatim link export
-1:-- [FR] ox-md: Verbatim link export (Post Org Mode requests)--L0--C0--2026-05-12T06:19:11.000Z
-1:-- [FR] ox-md: Verbatim link export (Post Org Mode requests)--L0--C0--2026-05-12T06:19:11.000Z
For ages I’ve had “add prepl support to CIDER” sitting somewhere in the back of my head. CIDER is built firmly around nREPL, but prepl ships with Clojure itself, and the appeal of dropping the external REPL server requirement is obvious. Recently, as part of a broader internals cleanup “mini-project” in CIDER, I finally sat down and put a prototype together: cider#3899.
The good news is that the prototype sort of worked. The bad news is that the more I poked at it, the more I kept running into the same pattern. CIDER assumes ops, sessions, request ids, and a whole structured protocol that prepl simply doesn’t have. The amount of CIDER code that would need to grow “is this nREPL or prepl?” branches added up quickly, and I’d be papering over prepl’s limitations in dozens of subtle places. The exercise was fun, but it ended up reaffirming my long-standing belief that nREPL is a much better fit for editor tooling than prepl is.
The exercise did leave me thinking though. What if, instead of bolting prepl onto CIDER, I built a small standalone client in the spirit of inf-clojure and monroe? Something tiny and focused that doesn’t have to pretend to be CIDER, and where prepl’s quirks would be the design rather than something to work around.
Conveniently, I was on vacation in Portugal at the time, where I spent a few
days in Porto, and the name pretty much picked itself.
Port was born. It kept us firmly in the
land of fun, drink-inspired Clojure-on-editor names: CIDER,
Calva (after Calvados, the apple brandy), and now Port (the
famous fortified wine). The protocol Port talks to is prepl, over a TCP
port, so the pun was hard to pass up.
This time around I didn’t manage to land on a backronym I love (at least not yet). The contenders so far:
Naming is hard. I remain open to better suggestions. :D
Port is a side project. I don’t plan to invest serious time in it past the
point I consider it feature-complete, which won’t be far beyond what’s
already there. The deliberate goal is to keep it simple and focused, and its
feature set will stay close to inf-clojure and monroe. Port is not
competing with CIDER. If you want the full feature set (debugger,
inspector, test runner, profiler, structured stacktraces, refactor support),
CIDER + cider-nrepl is, and will remain, the way.
What Port gives you today is a small, dependable Clojure REPL that you can hook into Emacs without any external dependencies, just a stock Clojure JVM with a prepl listening on a port.
If you’re up for the long version, doc/design.md goes deep. Here’s the short version of what prepl gives you compared to nREPL:
:ret, :out, :err, :tap, plus an :exception
true flag on errors.That last point is the central design constraint. If you want to issue a
request and reliably read back its result without accidentally consuming
output from an unrelated background future or tap>, you need to layer
correlation on top of the protocol. Port does this with two tricks:
future/agent on the user thread
don’t bleed into the tool channel.port.tooling/-eval wrapper. Every subsequent helper
call goes through it, which captures *out* / *err* and returns a
tagged map containing the request id. The client matches the id against
a pending-callback registry.This is what nREPL provides via sessions and ops, just reinvented at the TCP layer. It’s a fair amount of work for something nREPL gives you for free, which only strengthens my view that nREPL is the better protocol for editor tooling. Still, it was an interesting and educational exercise.
One thing I’m fairly proud of: Port has no hard dependencies. You’ll want either
clojure-mode or clojure-ts-mode installed for the source-buffer side of
things, but Port itself only soft-depends on them via runtime fboundp
checks. Hook it onto whichever one(s) you actually use. I intend to keep it that
way. Dependency creep is a real problem in the Emacs (every?) ecosystem, and a small
package should stay small.
I tagged v0.1.0 yesterday. It’s small but already perfectly usable:
M-x port “jacks in” (bootstraps) (auto-detects deps.edn / project.clj /
bb.edn, starts a server and connects to it)M-. find-definition that follows into jar sourcesMELPA submission is queued up next. After that, expect Port to be in burst-driven maintenance mode like most of my smaller projects.
Feedback, ideas, and contributions are most welcome. The issue tracker is the right place.
Funny thing, I’d never actually written any code against prepl until I started this project. It was fun to spend some quality time with the “competition” of my beloved nREPL. Working with a different protocol always teaches you something about the one you’re used to, and I came away from this with a renewed appreciation for both: prepl is genuinely elegant for what it is, and nREPL is genuinely well-designed for what we use it for.
Big thanks to Clojurists Together and everyone else who supports my OSS Clojure work. You rock! Now if you’ll excuse me, I have new releases of CIDER, clj-refactor, and refactor-nrepl to get back to.
Keep hacking!
-1:-- Port: a minimalist prepl client for Emacs (Post Bozhidar Batsov)--L0--C0--2026-05-12T06:00:00.000Z
-1:-- [FR BARK] Add ability to set a summary (Post Org Mode requests)--L0--C0--2026-05-11T18:33:20.000Z
As celebrated as Emacs is for its programmability, I find the actual process of developing Emacs Lisp (Elisp) to be quite underwhelming. Developing in Elisp has meant learning its libraries and idioms, which is to be expected. What I really don’t care for though are the arcane keybindings associated with doing basic things like evaluating, navigating (Xref), and debugging (especially debugging). While I’ve already committed to muscle memory most of said keybindings, I’d argue that having a mouse-based “point and click” interface is beneficial for both novice and experienced Elisp developers alike, as it lets one focus on the code and not on recalling the right key incantation all the time.
The addition of context-menu-mode in Emacs 28 has provided the opportunity to build a mouse-based UI for Elisp development and I’m happy to announce the availability of one in the latest v1.3.0 update to Anju, now on MELPA.
To get an idea of what’s available in the v1.3.0 update, here’s a screenshot of the context menu when normally editing an Elisp file where the point is on the symbol foo.

If foo is instrumented for debugging and run, the context menu is adjusted to provide Edebug commands as shown below.

The context menu enhancements provided by Anju take full advantage of built-in functions that identify context at point. Is the point on a symbol? In a function? In an ERT test? On a lambda? The menu items added by Anju take these factors into account to provide a relevant menu offering.
Users can read more about Anju’s context menu enhancements for Elisp development at Emacs Lisp Context Menu (Anju User Guide).
Back in 2024, I did a deep dive into Edebug so as to give a presentation on it at the EmacsSF meetup. In doing so, I realized that all the core features for having an Elisp IDE were there, but no good UI to present it. I set upon prototyping one using Transient, with decidedly mixed results due to both Edebug and Transient fighting each other over window management.
A later Edebug UI prototype using the toolbar was attempted but it also had its issues, particularly with layout (or lack thereof) and toolbar-specific bugs in macOS. But a benefit of using the toolbar was that its UI interactions did not interfere with window management. The context menu also shares this benefit.
The context menu has markedly improved my developer experience with Elisp, as I find myself using it more than typing out keybindings. Even with keybindings, I’ll use the Casual Elisp Transient to accomplish most Elisp interactions that don’t require Edebug.
That said, I’m not here to eschew keybindings. I still use them, when convenient. But in many circumstances they are not. The context menu can provide an easier way to achieve the same thing. Isn’t that a good thing?
-1:-- Enhancing Elisp Development with Context Menus (Post Charles Choi)--L0--C0--2026-05-11T18:00:00.000Z
I’ve been using ICanHazShortcut for years. I originally started using it to have an easy way to switch to Emacs from anywhere in my system. Eventually, I added Safari and HomeKit to the list of apps I can invoke with a simple keypress but most of my ICanHazShortcut shortcuts are Emacs related. For example, I have F9 mapped to Emacs capture so that I can invoke any Org capture template from anywhere on my system. That’s really handy and I use it several times a day. I also have a shortcut to invoke Emacs Everywhere so that I can escape into the comfort of Emacs when entering data in some other app.
Today (Sunday, as I write this) I received a notification that a new version of ICanHazShortcut was available. It’s completely rewritten in Swift from Basic and has some new capabilities. You can read about them at the above link. For me, not much has changed. The new version continues doing what ICanHazShortcut has always done.
ICanHazShortcut is a minimal app that simply provides a shortcut for any command that you can specify in the terminal. There are plenty of more full featured key mappers available that may be better for more complicated situations but I find ICanHazShortcut perfect. It’s light weight and easy to configure. I almost never mess with ICanHazShortcut’s configuration. The last time I changed it—to add HomeKit, I think—was years ago. It truly is a set it and forget it app.
If you want a simple app for invoking Emacs—or anything else—in various ways, take a look at ICanHazShortcut; it’s worked very well for me.
-1:-- ICanHazShortcut 2.0 (Post Irreal)--L0--C0--2026-05-11T14:27:26.000Z
People are getting Emacs 31 ready for release. Looking forward to that! See emacs/etc/NEWS.31 for details.
Lots of posts for the Emacs Carnival theme of "May I recommend…", yay!
Links from reddit.com/r/emacs, r/orgmode, r/spacemacs, 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!
You can e-mail me at sacha@sachachua.com.
-1:-- 2026-05-11 Emacs news (Post Sacha Chua)--L0--C0--2026-05-11T13:00:59.000Z
Most Linux distributions ship generic binaries compiled to run safely on a vast array of older hardware configurations. While this ensures broad compatibility, it sacrifices the speed that comes from using the specific, modern instruction sets of your processor. Compiling Emacs directly from source allows instructing the compiler to generate machine code targeted at your CPU architecture, resulting in a faster and more efficient runtime environment.
Before we dive in, please consider sharing this article on your website/blog, Mastodon, Reddit, X, or your preferred social media platforms. Sharing it will help fellow Emacs users discover better ways to manage code folding.
Beyond raw hardware optimization, building from source enables dropping decades of legacy compatibility layers and embracing modern desktop technologies. For example, Wayland users can configure the build to bypass old X11 display protocols in favor of a Wayland environment, ensuring smoother rendering and better system integration.
Additionally, this article details how to optimize the internal native Lisp compiler, which transforms Lisp packages into machine code to ensure that every Emacs package in your configuration operates at its maximum potential speed.
Here is the step-by-step process for compiling a highly optimized Emacs binary and packages.
On Arch Linux, the cleanest and most native method to resolve build dependencies is to use the official Emacs PKGBUILD, which automatically read the official dependency list and install them:
mkdir -p ~/emacs-deps
cd ~/emacs-deps
wget https://gitlab.archlinux.org/archlinux/packaging/packages/emacs/-/raw/main/PKGBUILD
makepkg --syncdeps --nobuild
NOTE: Once makepkg finishes installing the dependencies, you can safely delete the ~/emacs-deps directory.
On Debian-based systems, the most efficient method to gather dependencies is to use the package manager to automatically fetch them based on the distribution’s source package. You must first ensure that source repositories are enabled:
/etc/apt/sources.list with root privileges in your text editor.deb-src (Read: “sources.list format” on Debian Wiki) and uncomment them by removing the # at the beginning of the line.sudo apt update
sudo apt build-dep emacs
If you are using a distribution not listed above, you will need to use your distribution’s specific package manager to install the required development libraries. Look for packages that include the library headers, typically suffixed with -dev or -devel.
Here is the master list of upstream library names required to compile this specific Wayland and Native-Comp optimized build:
Before building Emacs with native compilation support, we will optimize how Emacs transforms Lisp packages into machine code. This is managed via the native-comp-compiler-options and native-comp-driver-options variables. While the main Emacs build uses your global CFLAGS, this variable specifically instructs libgccjit on how to handle every .el file it encounters.
Add the following to your early-init.el file:
;; Display the architecture using:
;; gcc -march=native -Q --help=target | grep march
;;
;; The above command asks the compiler to resolve native for your current CPU
;; and display the resulting target. For example, if the output shows
;; -march=skylake, you know that skylake is the identifier you should pass to
;; -mtune and -march.
(defvar my-cpu-architecture "CHANGE_THIS_TO_YOUR_ARCHITECTURE")
;; `native-comp-compiler-options' specifies flags passed directly to the C
;; compiler (for example, GCC) when compiling the Lisp-to-C output
;; produced by the native compilation process. These flags affect code
;; generation, optimization, and debugging information.
(setq native-comp-compiler-options '("-O2"
"-g0"
"-fno-omit-frame-pointer"
"-fno-finite-math-only"))
;; `native-comp-driver-options' specifies additional flags passed to the native
;; compilation driver process, which may invoke the compiler and linker with
;; certain parameters.
(setq native-comp-driver-options `(,(format "-mtune=%s" my-cpu-architecture)
,(format "-march=%s" my-cpu-architecture)))
IMPORTANT: Change CHANGE_THIS_TO_YOUR_ARCHITECTURE to your specific architecture. Run the following command to display the CPU architecture:
gcc -march=native -Q --help=target | grep march
The above command asks the compiler to resolve native for your current CPU and display the resulting target. For example, if the output shows -march=skylake, then replace CHANGE_THIS_TO_YOUR_ARCHITECTURE with skylake.
NOTE: Avoid adding -mtune=native and/or -march=native to the native-comp-compiler-options and/or native-comp-driver-options variables. While these flags work in global CFLAGS, libgccjit, the library responsible for native compilation, often fails to resolve the native keyword correctly. This happens because the JIT interface does not always trigger the same host-probing logic as the standalone GCC driver.
The rationale behind the selection of these flags is as follows
-O2 is an intentional balance. While -O3 may provide small performance gains in some workloads, it can also increase binary size and occasionally reduce responsiveness. -Ofast is generally discouraged because it enables aggressive floating-point optimizations.-g0 disables the generation of debug symbols for .eln files, which reduces their size on disk and speeds up the compilation process itself.-fno-omit-frame-pointer The Emacs developers recommend using this flag to disable omit-frame-pointer. Although enabling omit-frame-pointer frees up a general-purpose CPU register, it does not yield significant performance gains on modern architectures and can lead to bugs that are difficult to debug. According to Eli Zaretskii, an Emacs developer: “See bug#76180. This is in the context of the igc branch, where omit-frame-pointer is particularly troublesome, though it also causes problems in other situations. For further details, see etc/DEBUG in the Emacs source tree.”-fno-finite-math-only flag prevents the compiler from assuming that floating-point operations never produce NaN or infinity values. This flag is mostly defensive because GCC does not enable -ffinite-math-only at -O2 by default, but it can help avoid unsafe assumptions if additional aggressive optimization flags are introduced later.After modifying the native-comp-compiler-options and native-comp-driver-options variables, you must force Emacs to rebuild your packages. Ensure Emacs is closed and delete all existing .eln binaries using the following command:
find ~/.emacs.d/ -name '*.eln' -delete
Because Emacs uses a deferred compilation engine (Native JIT compiler), you do not need to manually trigger a build script. Simply launch Emacs and begin your normal workflow. As Emacs loads your packages and detects the missing .eln files, it will spin up background threads to recompile them using your new optimization flags.
To build Emacs, you must first obtain the source code from the official mirror and switch to a stable release branch:
git clone --depth 1 https://github.com/emacs-mirror/emacs
cd emacs
git checkout "emacs-30.2"
NOTE: The official Savannah Git repository at https://git.savannah.gnu.org/git/emacs.git can occasionally be slow or unreliable, so this guide uses the official GitHub mirror instead.
We target a specific release tag like emacs-30.2 (If you desire to install another version, you can display tags using the git tag command) to ensure a stable foundation. Building from a tagged release, rather than the bleeding-edge development branch like the master branch, minimizes the risk of build failures or experimental regressions that could impact your daily productivity.
Once inside the repository, all subsequent configuration and compilation commands are executed from this directory.
Emacs uses the Autotools build system, which requires generating the final configuration script before it can be used:
./autogen.sh
This shell script reads the developer configuration files provided in the repository and generates the final ./configure script. It sets up the necessary infrastructure to inspect your specific environment, locate system libraries, and prepare the Makefile.
To enhance runtime performance, we must export specific variables that instruct the C compiler and linker to optimize the resulting binary for the host CPU:
export CFLAGS="-O2 -pipe -march=native -mtune=native -fno-omit-frame-pointer -flto=auto"
export LDFLAGS="-Wl,-O2 -Wl,--sort-common -Wl,--as-needed -Wl,-z,pack-relative-relocs -flto=auto"
The CFLAGS variable tells the compiler to apply safe, general-purpose optimizations (-O2), optimize instruction scheduling for the specific CPU compiling the code (-march=native and -mtune=native), store the metadata necessary for the linker to later perform cross-module optimization (-flto=auto), disable omit-frame-pointer (-fno-omit-frame-pointer), use memory pipes instead of temporary files to speed up the build (-pipe).
The LDFLAGS variable instructs the linker to apply additional optimization passes to the final executable (-Wl,-O2), group common symbols to reduce duplicate storage (-Wl,--sort-common), avoid linking unused shared libraries (-Wl,--as-needed), reduces binary size by performing a global analysis to inline functions and remove dead code across the entire program (-flto=auto), compress and pack relative relocations to reduce relocation overhead and binary size (-Wl,-z,pack-relative-relocs). Together, these flags help produce a smaller, more memory-efficient executable with improved startup and runtime performance.
We run the configure script to select exactly which features to include.
For X11 users:
./configure \
--with-x \
--with-x-toolkit=gtk3 \
--without-toolkit-scroll-bars \
--with-cairo \
--without-xft \
--with-harfbuzz \
--without-libotf \
--with-gnutls \
--without-xdbe \
--without-xim \
--without-gpm \
--disable-gc-mark-trace \
--enable-link-time-optimization \
--with-gsettings \
--with-modules \
--with-threads \
--with-libgmp \
--with-xml2 \
--with-tree-sitter \
--with-zlib \
--without-included-regex \
--with-native-compilation \
--with-file-notification=inotify \
--without-compress-install
For Wayland users:
./configure \
--without-x \
--with-pgtk \
--with-toolkit-scroll-bars \
--with-cairo \
--without-xft \
--with-harfbuzz \
--without-libotf \
--with-gnutls \
--without-xdbe \
--without-xim \
--without-gpm \
--disable-gc-mark-trace \
--enable-link-time-optimization \
--with-gsettings \
--with-modules \
--with-threads \
--with-libgmp \
--with-xml2 \
--with-tree-sitter \
--with-zlib \
--without-included-regex \
--with-native-compilation \
--with-file-notification=inotify \
--without-compress-install
The rationale behind the selection of these flags is as follows
--enable-link-time-optimization Instructs the build system to natively apply link-time optimization. This ensures the Emacs build scripts coordinate the optimization properly across all compiled object files to produce the fastest possible executable.--disable-gc-mark-trace: Disable the GC mark trace buffer for about 5% better garbage collection performance. It removes debugging code from the garbage collector marking phase. This provides a reduction in overhead during garbage collection cycles, leading to a more responsive experience during memory-intensive tasks.--with-native-compilation Enable native compilation. (I omitted the aot flag to instruct the build system to skip compiling the built-in Lisp files during the make step. Instead, Emacs defers this work until runtime, where it will use the optimizations in native-comp-compiler-options and native-comp-driver-options while compiling all .el files the first time Emacs is launched.)--with-cairo and --with-harfbuzz enable modern text rendering.--without-compress-install By default, Emacs compresses its installed Lisp files to save disk space. Using this flag keeps the files uncompressed. The benefit is faster load times when Emacs needs to read these files from disk, as it skips the decompression step entirely.--without-xft Disable xft because modern Emacs rendering no longer needs it. Modern GTK builds of Emacs use Cairo + HarfBuzz handle rendering.--without-included-regex Makes Emacs use the system libc regex implementation. On contemporary Linux systems using glibc, the system regex engine is usually better optimized and maintained than Emacs’s bundled GNU regex implementation.--with-libgmp Enables GMP, the GNU Multiple Precision Arithmetic Library, an optimized engine Emacs relies on to calculate arbitrary-precision integers (bignums) at bare-metal speeds. Modern Emacs workflows constantly process massive numbers in the background. If you disable this flag or fail to install the system library, Emacs is forced to fall back on mini-gmp, a generic, software-only C implementation designed strictly for portability rather than speed.--without-xim: Disable XIM, a legacy X Input Method protocol used primarily for typing complex languages (like Chinese, Japanese, or Korean) on old X11 systems. If you use GTK3/Wayland, modern input methods handle this instead. Disabling this is recommended for Wayland/PGTK users as it removes unnecessary X11-specific code.--with-file-notification=inotify Guarantees that the build will use the Linux kernel’s efficient event-watching API rather than falling back to slow, resource-heavy polling if the detection fails.--with-gsettings Enable communication with the GTK configuration storage system. This allows inheriting system-wide preferences for themes, fonts, antialiasing hints…--without-libotf: Disables the legacy OpenType Font library. This is recommended for modern builds that use HarfBuzz (--with-harfbuzz), as HarfBuzz handles text shaping more efficiently. Disabling this library reduces binary size without sacrificing font quality in modern desktop environments.--with-gnutls: Enables secure network communication. This is required for secure package installation from MELPA/ELPA and for browsing HTTPS websites via EWW.--without-xdbe: Disables the X11 Double Buffer Extension. This protocol is redundant for modern builds because both the PGTK (Wayland) and GTK3 (X11) layers handle window buffering internally. Disabling it simplifies the binary and ensures Emacs uses modern rendering paths.--without-gpm Disable General Purpose Mouse (GPM), a background service that provides mouse support for the Linux console (the text-only TTY you see before logging into a graphical desktop). Unless you plan to use Emacs in a bare-metal Linux console (outside of a terminal emulator like Alacritty, Foot, or GNOME Terminal), GPM is unnecessary. Modern terminal emulators use their own internal protocols for mouse interaction that do not rely on the GPM daemon.If your workflow is primarily text-based, you can significantly reduce the number of external libraries linked to your binary. However, each omission comes with a specific trade-off:
--without-sound Disables support for audio notifications. You will not hear the audible system bell or sound cues from productivity packages like Pomodoro timers or chat clients.--without-libsystemd Disables the ability for Emacs to communicate with systemd. You cannot use advanced systemd service features, such as Type=notify, which allows systemd to know exactly when the Emacs daemon is fully loaded and ready.--without-dbus: Disables D-Bus integration in Emacs. This produces a slightly leaner build, but removes integration with desktop services that rely on D-Bus. Depending on the desktop environment and enabled packages, this can affect desktop notifications, interaction with services such as GNOME Keyring, file manager integration, power and network state notifications, and various portal-based desktop features. It is generally safe on minimal Emacs GUI builds or terminal-only setups, but many modern Linux desktop environments expect D-Bus support.--without-gconf Disables support for GConf. This is a deprecated GNOME configuration system that was replaced by GSettings. Disabling it ensures your build is not carrying legacy, obsolete desktop integrations.--without-sqlite3 Disables the built-in SQLite engine. This breaks modern packages that rely on a local database for performance, such as org-roam or certain mail indexers.--without-m17n-flt Disables the m17n library for complex text layout. While fine for English-only workflows, this will cause rendering issues (incorrect character joining or positioning) for complex scripts like Indic or Thai.--without-selinux Disables Security-Enhanced Linux support. On systems where SELinux is active, Emacs will be unable to preserve or manage SELinux security contexts when creating or copying files, potentially leading to permission issues or security policy violations.--without-libsmack Disables Smack security support. Similar to SELinux, if your Linux distribution uses the Smack kernel security module, disabling this prevents Emacs from managing those specific security contexts on files.--disable-build-details: Omits build metadata, such as your machine’s hostname and the compilation timestamp, from the final executable. While this doesn’t provides performance or startup speed benefits, it ensures a “reproducible build” and prevents your personal system details from leaking if you share your compiled binary.--without-gif, --without-jpeg, --without-png, --without-rsvg, --without-tiff, --without-xpm, --without-webp Disabling these prevents Emacs from linking against heavy image processing libraries. Emacs will be unable to render these image formats natively. This breaks functionality for image-heavy modes, such as image-mode, viewing PDFs via pdf-tools, or displaying mathematical LaTeX previews.--without-imagemagick Prevent Emacs from using this large dependency for complex image transformations. You lose the ability to perform advanced image manipulation (like dynamic resizing or rotation of certain formats) within Emacs buffers.--without-lcms2 Remove the Little CMS color management layer. Images may appear with slightly incorrect colors on high-quality displays, as Emacs will ignore ICC color profiles embedded in files.--without-xinput2: Disables the modern X11 input extension. Warning: If you are building for X11, disabling this will break pixel-precision smooth scrolling for trackpads and mouse wheels, forcing Emacs to use choppy line-by-line scrolling. This flag does nothing for Wayland/PGTK builds and offers no performance benefits.--disable-acl: Disables support for Access Control Lists. Disabling this reduces the number of system calls Emacs performs during file operations. This is a good choice for single-user systems where standard Unix permissions are sufficient.--disable-xattr: Disables support for Extended File Attributes. Only keep this enabled if you rely on SELinux or filesystem-level file tagging.--without-kerberos --without-pop --without-kerberos5 --without-hesiod --without-mail-unlink: These flags disable support for ancient mail retrieval methods, directory services, and local mail spool manipulation. Because modern Emacs mail setups rely on external synchronization, disabling these ensures the build script does not waste time searching for legacy network libraries and keeps the binary entirely free of dead mail code.With the configuration complete, the next step is to compile the C source files and the core Emacs Lisp files:
make -j 48 -l "$(nproc --ignore=1)"
-j 48: This sets the maximum number of concurrent jobs to 48. Make will attempt to run up to 48 compilation commands in parallel. This is an upper bound; actual concurrency may be lower depending on dependencies and system load.-l $(nproc --ignore=1): This sets a load average limit. $(nproc --ignore=1) returns the number of available CPU cores minus 1. Example: on an 8-core system, this evaluates to 7. So effectively, -l 7 means: do not start new jobs if system load average is 7 or higher. Make uses system load average (typically 1-minute load average) as a throttling mechanism.On a low-load system, Make may run close to 48 jobs in parallel. Under high CPU pressure, Make will throttle and pause scheduling new jobs until load decreases.
(Related article: Similar to make -j command above for Emacs compilation, read “Enabling Emacs native compilation and dynamically adjusting the number of Elisp files compiled in parallel“)
The final step is to copy the compiled binary and its associated files to their proper locations on your file system.
sudo make install-strip
While the standard make install simply copies the compiled files, make install-strip performs an additional optimization. It strips debugging symbols from the final executable. Removing these symbols reduces reduces binary size on disk.
Building Emacs from source and bypassing generic Emacs distribution binaries strips away decades of legacy compatibility layers and align the Emacs’ execution directly with your specific hardware architecture.
Remember to trigger a fresh recompilation whenever you update core system toolchains, such as GCC or your graphical compositor, to maintain binary compatibility and performance integrity.
-1:-- A Technical Guide to Compiling Emacs for Performance on Linux and Unix systems (Post James Cherti)--L0--C0--2026-05-11T11:52:16.000Z
-1:-- [FR] ox-md: Export custom-id search strings (::#) as anchors (Post Org Mode requests)--L0--C0--2026-05-11T03:15:59.000Z
Marcin Borkowski (mbork) has an interesting post on the describe-personal-keybindings command. The idea is that the command lists the keybindings that you have set in your configuration. It’s convenient, mbork says, for checking that new Emacs releases haven’t stolen one of your bindings. It’s also interesting to see what bindings you’ve added and what, if anything, they’ve replaced.
But there’s a catch. In order for a personal keybinding to show up, it must have been set with the bind-key macro. That’s a problem for those of us who are long term users. Those who use use-package exclusively have no problem since the :bind command uses bind-key automatically but bindings set with, say, define-key will not appear in the describe-personal-keybindings output.
That’s inspired mbork to refactor his init.el to use use-pacjkage and for stand-alone bindings, the bind-key macro.
The minions are insisting that I mention what they consider the best part of mbork’s post. That, of course, concerned dark mode. Mbork begins his post by mentioning a Web app that provides a Web based cheat sheet of Emacs commands. Mbork says it’s a cool command but not for him because
if I were to create something like that, it would run in Emacs and not in the browser, it would definitely mention transpose-.* commands, and it would never be dark-mode-only;-).
The minions haven’t been causing much trouble lately so I thought it only fair to indulge their desire to get mbork’s dislike of dark mode on the record.
-1:-- Personal Keybindings (Post Irreal)--L0--C0--2026-05-10T14:52:57.000Z
I have used EWW in Emacs for some of my browsing for a while and it does the job very well unless browsing single page applications or other sites that do not send HTML unless you run JavaScript. Thank you Lars Magne Ingebrigtsen for making EWW! Hitting R filters out all the noise for a really pleasant reading experience. It is good to browse within Emacs with no context switching in a keyboard-driven way.
(Apropos they joys of context switching: When I am a bit tired, I use Emacs keybindings everywhere. Tap-to-click is naturally off on my laptops to prevent insanity. I am often able to "help" my students a lot within just a few seconds of random keybindings and clicking everywhere on their laptops. It is really good for students to learn patience and tolerance towards people unable to handle computers. They need that for their user support class and future work in the IT industry.)
When Joshua Blaise wrote about his eww setup and use, I read it with interest and stole most of his ideas for my own config. The important one for this little hack is that I set up URLs with endings like .mp3, .mp4, .m4v, .mkv etc to launch in mpv when browsing to them. This makes watching videos and listening to audio content easy with EWW. EWW is also good for browsing local files by hitting W with point on a file in dired.
In dired, I usually launch external programs for photo editing, media playback etc by pressing & with point on a file name. This brings up the completing-read interface in the minibuffer which asks me if I would like to use dired's guess as to which program to use (which I have set to guess xdg-open first) or something else. I press return and then mpv, gimp, darktable or whatever launches with the file.
I had an html file in my downloads folder which I launched with W to read in EWW. I then, by mistake, hit W when on a .mp3 file, and it launched in mpv. Since W launches the file in EWW and EWW was configured to open .mp3 files in mpv, it did that without asking me which program to use. It is faster to hit W than to hit & RET, or in worst case write a program name and RET. So now I launch media files with W in dired in stead of using &. It speeds things up a bit.
(While writing this, I also remembered that I have functions for playing enclosure links and links in elfeed through mpv that I might replace or improve by shuffling the links to EWW or einar-browse-url-mpv. I wrote my configuration for elfeed very early in my Emacs journey, without really understanding any of it, by copying snippets from the Emacs wiki, blogs and Reddit so it is high time to look at it again anyway. I can probably simplify it.)
Here are the relevant parts of my configuration for EWW to get this working:
(defun einar-browse-url-mpv (url &rest _args) "Opens URL in mpv." (start-process "mpv" nil "mpv" url)) (use-package eww :config (setopt browse-url-handlers '(("\\(youtube\\.com\\|youtu\\.be\\|vimeo\\.com\\|twitch\\.tv\\)" . einar-browse-url-mpv) ("\\.mp3$" . einar-browse-url-mpv) ("\\.mp4$" . einar-browse-url-mpv) ("\\.webp$" . einar-browse-url-mpv) ("\\.m4v$" . einar-browse-url-mpv) ("\\.mkv$" . einar-browse-url-mpv) ("\\.pdf$" . einar-browse-url-pdf) ("." . eww-browse-url))))
-1:-- Speed improvement hack for dired with EWW (Post Einar Mostad)--L0--C0--2026-05-10T14:47:00.000Z
Those of us who have been around long enough remember Sacha Chua’s Emacs Chat videos. The last one was a decade ago but now that Chua’s daughter is a bit older, she’s decided to resurrect them. The first new episode, Emacs Chat 21, is with Amin Bandali with whom she’s worked on EmacsConf for the last 7 years.
The format is always the same. Chua and her guest discuss the guest’s Emacs configuration and how they’ve solved various problems. There’s way too much material for a quick recapitulation—the video is an hour and 12 minutes long—but there’s a transcript at the link so you can go through it at your leisure if you find the video’s pace too rapid.
There were a couple of things that I found particularly interesting. The first is the upcoming user-lisp-directory. It allows you to specify a directory for your Lisp files and Emacs will automatically compile them and add them to the load-path for you. Bandali uses it as a replacement for the package system because he prefers to configure things manually.
The second interesting thing for me was his use of EXWM (Emacs X Window Manager), which goes a long way towards the dream of bringing everything into Emacs. I’ve long wanted to try it out but as its name suggests, it works with the X-Windows system only. The Irreal bunker has famously standardized on Macs so EXWM is unavailable to us. I’d still love to try it though.
There’s a lot of material in the chat so you’ll have to watch it—or at least skim the transcript—to get the whole picture. There are links to his configuration so you can steal anything that seems useful to you.
I’m really happy to see Chua resurrecting her Emacs Chats. I really enjoyed the previous ones and learned a lot from them and I’m sure that will be true of the new ones too.
-1:-- Emacs Chat 21 (Post Irreal)--L0--C0--2026-05-09T15:14:22.000Z
I've done a small update to
make-phony.el, my little
Emacs package that lets me be lazy when adding .PHONY to
mark a target as a phony
target
in a Makefile.
The only change is a tweak to the regular expression, to tighten up the check for a target that can be marked.
-1:-- make-phony.el v1.4.0 (Post Dave Pearson)--L0--C0--2026-05-09T07:36:11.000Z
-1:-- describe-personal-keybindings (Post Marcin Borkowski)--L0--C0--2026-05-09T03:53:14.000Z
As returning readers will know, I produce (or try to produce) regular builds of Emacs for Windows. When things work, these produce pre-compiled binaries as an installer and unpack-and-run zip files. You can find links to the latest set for each branch in the box at the top-left each page on the site.
Today's post is about one program out from the middle of the bucket-brigade of data I have created, generally in an effort to avoid unneeded queries of the upstream (Savannah or Savannah mirrors hosted) repositories.
-1:-- last-rev.pl (Post Corwin Brust)--L0--C0--2026-05-08T18:59:59.000Z
Carrying on with the theme of being lazy while editing
posts, I've released
blogmore.el v4.5.0. This version
adds blogmore-set-as-cover. With this, if you place point on a line that
is an image and run the command, it is set as the cover for the post.
Sure, it's not like it's hard to copy, move, insert a new line, type
cover: and then paste the text, but this is faster and more accurate.
And I'm lazy.
And I like hacking on Emacs Lisp that makes my workflow flow faster.
-1:-- blogmore.el v4.5.0 (Post Dave Pearson)--L0--C0--2026-05-08T18:27:54.000Z
The shell-pop Emacs package provides on-demand access to a terminal buffer via a single, configurable key binding. It allows toggling a terminal window without disrupting the workspace layout, making it a useful tool for quick command-line tasks.
NOTE: Kazuo Yagi, the shell-pop original author, appointed me as a co-maintainer of shell-pop Emacs package. I recently refactored shell-pop to improve robustness, fix bugs, and add support for additional terminals (vterm and eat). Stepping into the maintainer role gave me the opportunity to give the codebase a thorough refactoring.

Adding shell-pop to your workflow offers the following benefits:
shell-pop-full-span is set to set to t)To install shell-pop from MELPA:
(use-package shell-pop
;; :bind automatically sets up the keybinding AND tells Emacs to lazy-load the
;; package the moment the key is pressed.
:bind (("C-c t" . shell-pop))
:custom
;; The key sequence used to toggle the shell window.
(shell-pop-universal-key "C-c t")
;; Sets the screen position where the shell popup appears.
;; You can choose "bottom", "top", "right", "left", or "full".
(shell-pop-window-position "bottom")
;; If non-nil, the window stretches across the entire frame width.
(shell-pop-full-span nil)
;; The path to the shell executable used by the terminal emulator
;; (e.g., "/usr/bin/env bash").
(shell-pop-term-shell shell-file-name)
;; The height or width of the window as a percentage of the frame.
(shell-pop-window-size 30)
;; Setting this to non-nil sends commands to the shell. This is not always
;; desirable, as it can send commands to any prompt.
(shell-pop-autocd-to-working-dir nil))
Here are the exact configurations for the most popular Emacs shells. Simply copy and paste your preferred option into your init file:
(with-eval-after-load 'shell-pop
(setopt shell-pop-shell-type '("ansi-term" "*ansi-term*"
(lambda ()
(ansi-term shell-pop-term-shell)))))
(with-eval-after-load 'shell-pop
(setopt shell-pop-shell-type '("terminal" "*terminal*"
(lambda ()
(term shell-pop-term-shell)))))
Note: Requires the vterm package to be installed.
(with-eval-after-load 'shell-pop
(setopt shell-pop-shell-type '("vterm" "*vterm*"
(lambda ()
(when (fboundp 'vterm)
(let ((vterm-shell shell-pop-term-shell))
(vterm)))))))
Note: Requires the eat package to be installed.
(with-eval-after-load 'shell-pop
(setopt shell-pop-shell-type '("eat" "*eat*"
(lambda ()
(when (fboundp 'eat)
(eat shell-pop-term-shell))))))
If you are a long-time shell-pop user, here are the changes I recently made to the package. I encourage you to try the latest version and send Kazuo Yagi and me your feedback in the issue tracker:
Taking on a maintenance role for a tool I use daily has been an interesting experience. These recent updates aim to make shell-pop more reliable and modern. I encourage you to try the latest version and send us your feedback.
-1:-- Easily Toggle an Emacs Terminal with a Single Keystroke using shell-pop (Recently Refactored) (Post James Cherti)--L0--C0--2026-05-08T14:41:33.000Z
As I mentioned a few days ago, the Emacs 31 release process was on the verge of starting. Now Sean Whitton writes to tell us that the Emacs 31 branch has been created and that the feature freeze has begun.
This means that the Emacs 31 release cycle has begun and that’s what on the Emacs 31 branch is pretty much—modulo bug fixes and last minute emergency additions—what the final release will be like.
The release cycle—if you believe in history—is apt to be long but even though that can be frustrating it means that the final product is going to be rock solid.
Although I keep repeating it, I can’t say it enough: thanks to all the developers who selflessly donate their time and efforts to making and keeping Emacs one of the best—if not the best—editors available.
-1:-- The Emacs 31 Branch Has Been Created (Post Irreal)--L0--C0--2026-05-08T14:10:46.000Z
In the recent weeks I've been engaging Prot as an Emacs coach to help
with doing review passes over my upcoming ffs package as I work on
polishing and documenting it in preparation for offering it for
inclusion in GNU ELPA.
Yesterday we had our second session focused on ffs, which I recorded
and share publicly with everyone with Prot's permission, so that
others can also benefit from Prot's insights and experience as we
discuss various aspects of Emacs package development with the concrete
example of ffs.
Here is the video recording of our session:
You can view or download the full-resolution video from the Internet Archive.
I addressed most of Prot's feedback about ffs from our first
session, and I'll be working on the changes we discussed in this
session in the next days.
In the last third of the video we switched topics to discuss a few
Emacs-related tangents including adding a 'padding' effect for the
mode line and its constructs, and distilling and separating the
easily-reusable package-like parts of one's Emacs configuration from
the actual configuration of those parts (e.g. the distinction of
prot-lisp and prot-emacs-modules in Prot's Emacs configuration).
For mode line padding, here is the snippet I'm using with Prot's
doric-themes:
(doric-themes-with-colors
(custom-set-faces
`(mode-line
((t :box (:line-width 6 :color ,bg-shadow-intense))))
`(mode-line-inactive
((t :box (:line-width 6 :color ,bg-shadow-subtle))))
`(mode-line-highlight
((t :box (:color ,bg-shadow-intense))))))
Take care, and so long for now.
-1:-- FFS code review with Protesilaos (Post Amin Bandali)--L0--C0--2026-05-08T02:10:33.000Z
I met with Amin Bandali to talk about Emacs, specifically Amin’s
upcoming ffs package. Amin informed me about changes to ffs in
light of a discussion we had during a previous session.
Amin asked me to record the meeting and then publish it, which I happily agreed to. You can watch it on Amin’s website: https://kelar.org/~bandali/gnu/emacs/ffs-code-review-prot.html.
[ NOTE: I normally do not share anything about my meetings with people. Not who they are nor what we talk about. ]
Thanks to Amin for making this happen! I am looking forward to new developments.
By the way, I learnt about the function x-export-frames from a
mention in Amin’s ffs package, which led me to write
buffer-to-pdf: https://github.com/protesilaos/buffer-to-pdf.
-1:-- Emacs coaching with Amin Bandali (Post Protesilaos)--L0--C0--2026-05-08T00:00:00.000Z
: Transcript, yay!
I chatted with Shae Erisson about Emacs, keyboards, Org Mode, and life.
View it via the Internet Archive, watch/comment on YouTube, read the transcript online, download the video / MP3 / transcript, or e-mail me your thoughts!
Shae: This is an Ergodox Infinity, but there's a lot of other keyboard flavors like this. And one of the things that I particularly like about this... So around the same time I met Jeff Raskin, who wrote the Inhumane Interface. And so for this particular thing, this is like Control and Alt and Hyper and Super and Shift. And this means that under one thumb, I have a lot more modifier keys than you get off of a standard. And it also means... A lot of my problems started with Emacs pinky, the dreaded, the infamous... I think that one of my... I made a keyboard layout called "I am not koala." You may not know this, but koalas have two thumbs. They have one on each side. And that's cool, but I don't have two thumbs, and I realized that when I was trying to grab something, I didn't put my pinky on it. That would be silly, right? I want to put my thumb around it. And so I decided I would move all of my chording keys under my thumbs. And that's kind of how I...
Shae: Another thing I ended up switching to was I started using trackballs. Oh yeah, yeah. I tend to go completely overboard when trying out new things, so I bought 20 different models of trackballs and ended up settling on this one. The nice thing about this one is that this is how you scroll, and it has four buttons. Sacha: That is really cool. I like using ThinkPads, so I've been just living off the tiny little mouse in the middle of the keyboard. But back in the day, I also used a trackball. If I can get to the point where I want to take my hands off the keyboard again in order to do mouse things, that would probably be the direction I would go.
Shae: And so one of the things that my coworker wrote was this nifty thing called ShWiM. And it's basically "shell with me." And it's a wrapper around TTY share so that with one single command, you can share a terminal. And the way that we use this is... We both run Emacs as a server, and then we use emacsclient in the terminal to connect.
Shae: I don't know if you've ever done this, but I can have a terminal right next to this, and if I run emacsclient in a window, then I'm sharing the same thing. This is a graphical chat with Sacha, in the terminal or in the UI, and both of them are updated. Sacha: That's fantastic. I remember people were using tmate for something similar before where you could share that. But yeah, it's just making it seamless, making it frictionless. And on the other side, I have also just been using wormhole to send large files back and forth between Karthik and John Wiegley because we have this other Emacs chat thing where we're going to post it eventually, once I finish figuring out how to redact all the personal information and Org files. But yeah, it's great for being able to send things without having to worry about, oh, you know, what's my public IP? Can I tunnel all the different things to get past whatever firewalls there are? So if this also works for terminal things plus Emacs client, that sounds really, really exciting. Shae: We've tried some other experiments. One of the things we tried to do was, and the only downside is like, what if my terminal has a different size, then you have to kind of shrink and match. And so we tried to honestly directly bridge to Emacs clients. And because I don't know if you're aware that there's effectively a local socket for the Emacs client that you can have multiple things connect to. But it turns out there's some sort of like system so I couldn't like reach across the network and directly use my co-workers Emacs session and he couldn't use mine. Weird things happened when we tried to do this cross host. As far as I can tell the Emacs client only works in the same host. Sacha: That's interesting. Lately, I've also been experimenting with CRDT, which has that Emacs-less plant as well. So that's been nice. But yeah, of course, a lot of people will be kind of stuck with the first challenge of finding someone that they can pair in Emacs with. Shae: I understand. And I think I'm honestly very happy that my one single coworker at this job is also a big Emacs user. And so we exchanged cool ideas and worked on stuff. And I'm very happy about that. Sacha: Were they already an Emacs person before they joined? Or did you pick the coworker because they were an Emacs person? Shae: They picked me. They were pretty much the person who started this thing. And they picked me because they'd worked with me at the previous job. Although I did have an experience like that. I had this massive Emacs config file, like 20,000 lines, and half of it was comments because it had accrued over 20 years.
Shae: And I actually really do use the calendar all the time. This is like just switch to whatever it is. Of course, my email is here. You know what, let's see... So this... I don't know, have you seen this before? Have you seen this thing called STARTED in an Org mode file? Sacha: I use a STARTED state, yes. Shae: Well, I got it from you! So if I look at like, my Org Mode configuration, a lot of this STARTED stuff I have from you, I don't know when, but you were the person who introduced me to it. Sacha: It's the reminder that I did start working on this. I tend to get distracted by intermediate tasks, so it's nice to be able to say, try to finish these ones first before you move on to the next thing, maybe? Shae: I agree. I have the same thing, yeah. And I keep meaning, because this is... I know that you can put Org Mode configuration into the first TODO item. I would really like to move it into the elisp and I just haven't gotten around to it. And it's been 10 years. I mean, maybe I should just do it.
Shae: One of the things I did that I found fun... I really have written almost zero Elisp, but I did actually puzzle my way through this a year ago. Since so much of my life is in Org Mode, I learned how to make timers. This is very close to what you get directly out of how to do timers in Emacs. After some amount of time, I want my Org agenda to pop up because I want to say like, oh, what is the stuff I'm supposed to be doing? And what am I forgetting? What has been scheduled? And what is on my to-do list? And I also like to look at what is the stuff I've been working on lately? And I really like that a lot.
Shae: Another thing that I realized is that I had a blog post that was wildly popular. Where did I put it? And it was all about Emacs. I don't know if you saw the... Here we go. It was... Ah, here it is. So here it is in... This is very much an Emacs... Sacha: Oh, yeah, I remember that one. I put it in Emacs News. I thought it was great. Shae: All right, cool. Sacha: I would like the kiddo to sometimes be able to acknowledge this, but this is not happening. Still, yes. Shae: Right, right. Yeah, and so this was really fun because, like... I had a friend who was in development and there was like millions of dollars spent on how do you detect whether a programmer is in flow and it came down to if they're typing they're probably in flow so and that was it because they tried to look at EGs and doing all kinds of other stuff but it was like if they're typing don't interrupt them. And I don't know, because I do so much in Emacs, I'm not sure how accurate this was. But basically, that's where I learned to do timers the first time. Or maybe... I don't remember which one I did first. And the idea then was as soon as basically my average typing into Emacs has gone up a certain amount, then it will actually switch to busy. And it works just fine. It was a lot of fun to write. Sacha: So yeah, interesting use of getting the activity. I've seen other fun implementations of this. I think there's a c-c-c-combo package that makes some fun animation appear if you're typing really quickly. Shae: Oh, oh, yeah. I'm guessing because I think Atom, the Atom editor had that for a while. I guess that's where it came from. Sacha: So yeah, because you can instrument Emacs and play around with it, you can certainly do all sorts of things based on that information. Okay, so you've got it, you've got it set up so that when you come back to your computer, it'll show you the stuff that you've been working on. And when you're working on the things, you can tell it to tell the rest of the world not to bug you. Gotcha. Shae: That's right. [Sacha: What other fun stuff do you have in there?
Shae: And so, at the moment, it's summer... Where did my summer go? How can this be? There we go. How come I'm in spring? Wait, isn't spring over? Hasn't summer just started? You know what I was thinking would be fun would be take the time of day, and you know that the EF themes has spring, summer, autumn, and winter, and I'm not sure if there are dark versions of each of those, but I thought, like I know that Modus themes will do this like check for the local time of when it turns dark, and then it will go from the light theme to the dark theme as soon as the sun hits, and I was like, well, what if I do that for seasons, you know, wouldn't that be cool? Sacha: There's this subtle sense of change as you go through the year. But of course you also have this thing there where you just randomize it. Shae: Well, I like that. Sometimes it's like I'm just kind of like, ah, I'm bored. I'm just bored of what I'm looking at. And so I will just change my thing. And it's just time for something. I don't know. It seems to work. It's like it gives me a little brain break from what I was staring at. And I did not know I was going to reset the effects scale, but that's fine. Interesting. What else do I have in here?
Shae: I just started doing this thing with imenu. imenu integrates nicely with LSP. Sacha: That is a very pretty sidebar thing, and I need to learn how to do that. Shae: So because I have all these extra modifiers, my s-i is lsp-ui-imenu. And the reason that what I mostly use that for is when I have like a bunch of Rust code and I want to quickly jump through the structure of it. Basically that integrates with LSP, finds all the definitions, and I can quickly jump through it. I used to use lsp-treemacs for that, but lsp-treemacs puts things in its own order, not quite the same order I want, although treemacs is quite nice. I think that the thing to do is that you and I at some time maybe the next time if we do this again we should set up with a Shwim connection and you and I can both share our Emacs and then you can show me cool things that you do and I can show you cool things that I do and then we can start filing over some of the things. How about that? Sacha: That sounds fantastic. I know we'd wanted to experiment with pair programming a long time ago so that sounds like a seamless way to do it. And therefore I will go and figure out how to install shim and get it working. I will probably need your help to actually test it. I don't know, I think I can rustle up. Maybe it'll work off my phone. You haven't tried that. But lspui, okay, so I've just been using straight up imenu, like on Neanderthal, but lsp-ui has this fancy grouping of things and colors and stuff, so I definitely want to check that out. Shae: I'm a fan, yeah. I don't know. Do I have anything else exciting that goes with this in here?
Shae: I decided that it would be great fun to do my taxes. Sacha: You are showing me your taxes, do I need to like black out this whole thing? Shae: Well, this is actually just an example from the docs. So I could actually share my taxes on it because I mostly don't care. But I think in fact you can figure out exactly how much money I'm making by looking at the open whatever. So the thing about this is that I decided to file all of my tax forms directly into Org Mode spreadsheets and then do remote lookups. So basically each spreadsheet was one particular form. And then once I'd gotten to the bottom, like I need this result, like what's my estimated income? And then I would use the lookup, kind of this cross spreadsheet lookup. And that's how I did my taxes for last year. And then my de facto mother-in-law, she's an accountant, and she didn't exactly do this thing, but it was pretty close. She was like, you've got all your taxes in the spreadsheet. I was like, yeah. And then she looked at it and she was like, what is that? And I was like, anyway. So I got to kind of file everything back out into TurboTax, but that was a fun thing to build. Sacha: Yeah, I have something like that too. So for example, whenever I do my tax paperwork, I just have to have like, you know, the step by step checklist. Okay, this is where I need to go to get this number. This is where I can put it in. And then eventually it spits out a table that says, okay, put this in box 11, put this in box 13, so that I don't have to do the steps by hand. Because even before the, you know, for me, I use like simple stacks or whatever, it's web based. But before you get to the point where you can put the numbers in the form, you gotta go to this website, calculate this thing, and Org just makes all of that so much easier. Shae: I agree. Yeah. Sacha: And this remote lookup thing is something I'm always looking up because Org tables are so powerful, but also I need more examples in my life to remember how to use them. Shae: Well, I think it took me four hours the first time to get it all figured out. But I can send you an example without showing it here. I can send you an example because I figured out, I think I've hammered the remote lookup down very thoroughly. Sacha: And once you've got it right, you can just keep filling that in or copy and paste it. You have an example of the syntax and that's already all you need. Shae: Right. I did run across some limitations of the evaluation method of Org mode spreadsheets. But maybe I've been using them a little too hard, if that makes any sense. Sacha: Oh, what kind of limitation? Shae: Honestly, I think I finally found a way to say every single... Because it was... So really the way that spreadsheets work is they're much more like Dataflow. And that is just that you end up with, like, either you work from the endpoint, which is like much more Haskell style evaluation, which is where you're like, I need to start here. What depends on this? But in the case where you have a whole bunch of different Org Mode spreadsheets, I think I ended up with this little text style hack where I just ran it a bunch of times. So it's like evaluate, evaluate, evaluate. Because remote lookups I ran, you know, I don't remember. And I think I took notes, but I don't remember. That's one of the great things about Org Mode is that I swear it's my, like, half of my brain is in my Org Mode notes. And whenever I had, I'm like, oh, what was that thing? I'm like, well, fortunately, with my terrible short-term memory, I took copious notes because otherwise I would never be able to get back to it.
Sacha: So Org timer is a separate thing. It's useful for meetings and things like that. You would say, okay, your Org timer starts at the beginning of the meeting and then you can have a list and it automatically, like if you alt shift enter or something like that in the list, it'll automatically like insert the right timer, relative timer to it. There you go. So there's an org-timer-start. But the reason I didn't go that approach was because then you A. have to remember to actually start the timer and B. then you have to synchronize your time with video time. Which might not have started at the same time. So now I'm just like, okay, wall clock for everything. And then I can do the transformation with whatever I like. And since I'm editing my subtitles in Emacs, I can say, hey, this file started at this time, according to YouTube. And then just, you know, map all of the wall clocks to the appropriate subtitle times. Shae: Wow. That's really cool. Sacha: Anyway, so timers, relative, absolute, and using abbreviations is great. Which I think actually is a thing that I picked up from Karl. Karl Voit because he also likes to use... He has an abbreviation, not at the Emacs level, but he has an abbreviation on his system level, like with his window manager, so he can use this timestamp trick anywhere, including in Etherpad or wherever else where you want to insert the date and time. That's V-o-i-t, by the way. But yeah, so times are a great way to just leave yourself a pointer to that moment so you can go back to it later. Shae: Now I'm curious, how well does that integrate with this sort of thing? Because I really like looking back at my history agenda. Sacha: If you have it insert an inactive timestamp, I think it should still show up there. I think it will be a little like those. Shae: Yeah, it looks like the... Well, it looks like these two are showing up. Sacha: Yeah, yeah, yeah. Yeah, so that's a basic thing that I would have inserted by my either abbrev or... So it's not even dabbrev. It's just regular abbrev in Emacs. Shae: What's the difference? Sacha: dabbrev is like hippie... Okay, let me just double check here. I feel like dabbrev is sort of hippie expand-ish. It looks in your buffer or possibly other buffers. And I think hippie-expand and dabbrev, they kind of work together. It's an option to have them work together. Okay, so hippie-expand is... Oh, so I see. Hippie-expand is the more advanced version of dabbrev. dabbrev was Dynamic Expand, and Hippie Expand says, yes, that, but try a whole bunch of other things first. But my timestamp thing is actually just done by a regular abbrev, and I will find the thing in my config for "ot". Oh, yeah. I will put it in my chat. Shae: My spelling, most people say my emails are spelled really well, but it's only because I have ispell set up. Sacha: Yeah, ispell is great. I am learning French and therefore... Shae: Oh, c'est très bien. Je parle un peu de français aussi. Sacha: Oh, oui. I'm keeping a journal in French on my blog and I have the Tatoeba Project with all the example sentences and I have a consult interface to look up stuff in them so I can just borrow other people's words and try to make it sound more natural. Plus of course the usual searching for words in dictionaries and stuff. Anyway, in the chat, I put in my global abbrev table definition for insert format time string. In case you want to steal that, it's right there. Shae: I will definitely save that into my notes here.
Shae: Oh, I've got a cool thing that I'm doing for work. And that is that our readme file is not only a word file, but we also have the demonstration of our actual thing is done by using like dependent snippets. And so that means that like if you want that, perhaps this is something everyone already knows, I don't know, but we basically are using the results of earlier commands in later places. And the other nice thing about that is that then when we want to check, we have to effectively dock tests, right? When we want to check and see if our software works the way it does in the readme, we evaluate the final Org Mode snippet, which then calls it forward, calls it forward, and then if something goes up or not. Well, I guess I need to fix something. And so it was pretty exciting to put Org Mode niftyness into our, into my Word reading file, you know? Sacha: Nice, nice. And you did mention your other coworker is on board with the whole Emacs thing. So that's one of the things that people are often like, I want to use Org Mode and I want to use it for like the documentation or the testing or whatever, but they got to get everyone else on board with the thing. Otherwise it's Jupyter Notebooks or whatever else, right? Shae: Right. Okay, so I have a joke for you that I came up with a long time ago, and that is, do you know the only way, there's only one way that Sauron could have organized the invasion of Middle-earth, and do you know what he used? Sacha: What? Shae: Orc Mode. It's a terrible joke, isn't it? Sacha: That's okay. I'm sure someone in the comments will come up with an even worse pun. Shae: I'm excited! It's going to be great! Sacha: Never underestimate the punniness of the Emacs community. Shae: I completely agree. I don't know. Do I have anything else exciting in here?
Shae: I actually really like this one. I used to run all of my tests in compile. F12, I have F12 bound to compile. And one of the things I wanted was, I wanted something where it was, if the compile is successful, don't show me the results, because everything's good. And so since I'm doing stuff in Rust, when I run all the tests, it leaves the buffer up, and I need to get around to actually doing stuff like this for Rustic mode as well, where when the tests pass, just go away, because it's all good. And when the tests don't pass, show me where to... I need to look at the problem. And I got this from Enberg and Emacs, I don't know, 20 years ago. Maybe it was less than 20 years ago, but it probably wasn't. So yeah, there's so much good stuff. Yeah, there's just so much good stuff. And I also like to, oh, look, here we go. You can see that this is long gone, by the way. It's not there anymore. Sacha: I have a proper, you know, it's sachachua.com/dotemacs. A lot easier to remember. But yeah, and I think that's, yeah, yeah, I remember that now. defadvice is also obsolete. The new hotness is advice-add or something like that. Shae: Oh, really? I'm going to make another TODO item for there. Sacha: I was digging through my notes trying to find, do you share your config anywhere? Shae: No, but you know, at this point if I share it on YouTube, I might as well just throw it up somewhere. Why not? It's not very exciting. Like if you look at someone like Ross Baker who has magic, like wow, is there some magic coming in from Ross Baker? I'm so excited to see more stuff from him. There's just like, I guess I feel like compared to almost everybody else I know, I feel like a power user. Because I'm like, you know, I wish I could do this thing. A lot of times someone I know is like, well, I did that thing and here's a library. And I'm like, yeah, I'll have to do it. And I just, I guess I feel like I'm a power user. And on the good side, I guess I kind of, I really haven't written that much Elisp ever, like I was saying in the comments during your interview with Prot. And I kind of like to, it's just I guess it's never quite gotten to the top of my stack. And I did decide it was time for me to send money to Parade for at least for themes, if not for like, please teach me some Elisp so I can actually, because you know, it's not that Elisp is hard. It's more like, how do I kind of, what are the things I interact with? What are the words? What's the vocabulary of working with Emacs? I don't actually really know. As a user, sure, I can do cool stuff. I can do Lisp macros. I've done Scheme and Lisp some of the past, but not inside Emacs. Sacha: Alright, so let me clarify. After more than 20 years of using Emacs, did you say you feel like a power user or do not feel like a power user? Shae: I definitely feel like a power user, but I don't feel like someone who does much of anything with Elisp. I don't really feel like someone who has much of a clue in the internals. And that's not entirely true. I have some of the ideas. But for the most part, I haven't actually needed to know that much about the internals. And sure, I've dug into things like how do you efficiently work with large buffers in your ??, like the ropes data structure and stuff like that. That was more for fun. Although it is something that Emacs does and does extremely well. But I'd kind of like to... There's a lot of things I'd kind of like to change and I don't really have enough of the understanding of the kind of how I would write the Elisp to do it. Here's a good example. When I hit F3, it takes me to the one I'm currently clocked into. Unless I haven't clocked in to something since I started Emacs. And honestly, I would like to use something like org-ql, the Org query language, to go find if I've just started Emacs, and Org does not know about something, you know, I just want you to go search for it. I have so many cores and so much memory, just go find it. Sacha: That sounds like an excellent reason to go learn Emacs so that you can have it... If you're not currently clocked in, go find the most recent clocked in task and go there, or maybe present you with a list of things and then go from there. I would love to hear about your Emacs Lisp learning journey because that's one of the big things that moves people from, you know, power users, yes, but users, to using Emacs as a lightweight editor toolkit for something that's custom fit to exactly what their workflow is. And on that note, I'm going to try to wrap up gracefully before the kiddo, you know, just like drags me out here. Thank you so much for doing this. I look forward to more conversations. I'm going to post the transcript and other things like that pretty quickly, I think, because I have this nice workflow now that lets me take screenshots and everything, but there's so much here that I want to unpack. But I hear the kiddo, bye!#+begin_export 11ty
<a name="end-ec22-transcript"></a></details> #+end_exportbvt
Find more Emacs Chats or join the fun: https://sachachua.com/emacs-chat
You can e-mail me at sacha@sachachua.com.
-1:-- Emacs Chat 22: Shae Erisson (Post Sacha Chua)--L0--C0--2026-05-07T18:55:38.000Z
Figure 1: JPEG produced with DALL-E 4o
My dotfiles for my MacOS rice and Emacs configuration live in two public repositories. Both repos are shared as a reference; clone, fork, or just lift the bits that look useful to you!
This post is a thin entry point, and the READMEs in each repo carry the actual detail.
A single bootstrap.sh that takes a clean macOS install to a fully provisioned development machine in roughly thirty minutes. It installs Xcode CLI tools, Homebrew, and a long list of CLI utilities and language toolchains, then symlinks every config in files/ into the matching path under $HOME.
See repo for installation instructions.
What gets installed:
gh, k9s, bat, fzf, ripgrep, eza, jq, lazygit, AWS CLI v2, and more
The full package list lives in the repo's Brewfile. bootstrap.sh also clones .zetta.d to ~/.zetta.d as part of the Emacs setup; if you only want the shell side, comment out the emacs section.
My Emacs configuration, packaged as a small distribution. Around 320 packages wired up via a module DSL, with an Elpaca lockfile pinning every package to an exact commit, and byte- and native-compilation done up front so the first launch is clean.
The name is a cheeky play on how we name certain minimalist text editors after Metric Prefixes nano (10^-9) or pico (10^-12). This maximalist editor config is named after zetta (10^21).
See repo for installation instructions.
Notable parts:
zetta-modules! in ~/.zetta.elZetta also hosts several small packages I've written that live in their own public repos. See the README's "Bundled custom packages" section for the list. None of these are released or publicized yet, so bring a pinch of salt if you choose to try them.
-1:-- My Dotfiles: macOS Bootstrap and an Emacs Distribution (Post Charlie Holland)--L0--C0--2026-05-07T15:18:00.000Z
Jonathan Chu is a software engineer and Emacs enthusiast who’s been looking for a note taking app that he can actually use. He’s tried all the usual suspects but found them too opinionated for his liking. He wanted to work in Emacs and write his notes in Org mode but none of the existing packages were quite right. So he did what Emacs users always do when things don’t work exactly as they like: he wrote an Emacs package do things the way he wanted. The result was grove.
Chu says that Grove was informed by his experience with Obsidian. I’ve never used Obsidian so I can’t comment on that aspect but Chu says that Grove is Obsidian-like. The only external dependencies are ripgrep, Graphviz if you want the graph view, and Consult if you want the enhanced search capability. One of his goals was to have an easily installable and configurable package.
It looks like a pretty nice package if you’re looking for a note taking method with a bit of but not too much structure. I use Org mode for all my note taking across many dimensions and have never felt the need for a more organized approach. Sure, sometimes I think about using Denote or Org Roam but—for me—they never seemed worth the effort. Many others disagree, of course, but Emacs has a home for us all,
Take a look at his post or the Github repository for the details and a bit more on how things work.
-1:-- Grove (Post Irreal)--L0--C0--2026-05-07T14:58:24.000Z
I've released an update to
blogmore.el, my
Emacs package that helps me out when writing this blog. I've
added two commands to this version which help me be lazier than ever.
The first is blogmore-become-like. When run, this prompts for another post
and, once selected, it sets this post's category and tags to be the same
as the other one. I added this because I'm often writing an occasional
series of posts that are all about the same project, and so I always find
myself copying and pasting those frontmatter properties from another post.
The second command I've added is blogmore-toggle-image-centre. Built into
BlogMore is a little bit of styling that will
ensure an image is placed in the centre of the page, if the URL for the
image has #centre on the end. This means that, for most images I add, I
have to go and edit the URL to add that. Now I can just run a single command
when the cursor is on an image and it'll add (or remove, if it's already
there) that styling hint.
In both cases, I've added the commands to the transient menu too.
-1:-- blogmore.el v4.4.0 (Post Dave Pearson)--L0--C0--2026-05-07T08:05:10.000Z
capture icon
Product: Capture
Price: $7.99 · lifetime updates · up to 5 Macs · 7-day free trial
Capture is a product designed to capture something, and move on with your life. It is an universal product, you can be in any application, Safari, Chrome, BBEdit, Finder, anywhere. You can press the keyboard shortcut to invoke capture. Fill in what you want to capture. Hit return and go back to whatever you were doing.
The product is advertised as “Capture thoughts to Obsidian without leaving what you’re doing.” You don’t have to use Obsidian. I use Emacs and it works great for that too. You can use any text editor and it is as useful.
capture options
Capture gives you two options to capture your content.
capture where?
capture and folders
You can define the Obsidian vault that Capture deals with. In my case it is the folder which contain my org files. Within that folder is another folder called ‘capture’ where I put my captured files into.
capture context
Within these options you have various options. You can include context. You get to define the context.
capture tags
You can add tags to your captured content.
I am happy with Capture. It is a focused utility which does what it promises well.
⌘↵. On my machine ↵ saves the capture. There is no way to add a new line. This must be a bug.I used the program for fifteen minutes and bought it. It is the kind of utility which I am going to use multiple times a day.
Recommended most heartily.
macosxguru at the gmail thingie.
-1:-- Capture and Move On (Post Bicycle for Your Mind)--L0--C0--2026-05-07T07:00:00.000Z
twtxt was one of the strongest inspirations behind Org Social: a plain text file served over HTTP, with no active server, no database, no signup. I personally admire the work done by Buckket: the concept is so powerful that it has captured the hearts of many people over the years. Its author gave us an elegant solution for creating a personal microblog, an alternative to Twitter (now X).
That said, Org Social would not exist if it weren't for the limitations of twtxt or the natural evolution of social networks. Org Social keeps its spirit, learns from its mistakes and from the competition, reinforces other concepts (like federation) and adopts modern features (like visibility). It is not an improvement, it is a shift in approach.
That's why I'd like to go over the three most important aspects where Org Social improves on twtxt.
The most obvious one is the ability to have structured metadata thanks to Org Mode.
#+TITLE: Bob's journal
#+NICK: Bob
#+DESCRIPTION: I'm a software developer and I love open source.
#+AVATAR: https://my-awesome-website.com/avatar.jpg
#+LINK: https://my-awesome-website.com
#+FOLLOW: https://foo.org/social.org
#+FOLLOW: https://jane.com/social.org
* Posts
** 2024-12-12T12:00:00+0100
:PROPERTIES:
:LANG: en
:TAGS: emacs org-social
:CLIENT: org-social.el
:VISIBILITY: public
:MOOD: 😊
:END:
Hello Org Social!
This opens the door to giving context to each post, having native threads, tagging, organizing in groups, defining visibility, running polls...
| Feature | twtxt | Org Social |
|---|---|---|
| Format | plain text (Markdown optional) | Org Mode |
| Mentions | yes | yes |
| Profile metadata | minimal | rich |
| Tags | #hashtag inside the body |
:TAGS: as metadata |
| Native threads | no | REPLY_TO |
| Multiline | no | yes |
| Sub-headers | no | yes (#+) |
| Federated groups | no | yes (GROUP) |
| Languages | no | yes (LANGUAGE) |
| Polls | no | yes |
| Reactions / boosts | no | yes |
| Visibility | no | VISIBILITY (though not fully private) |
| Account migration | no | MIGRATION |
We don't just get richer post bodies: the possibilities for interaction between users grow without limit. The specification invites you to create, not to work around limitations.
Org Social follows these principles:
Without clear rules, the ecosystem fragments. There isn't a single line of the specification that isn't aligned with the points above.
A very important element in Org Social are the Relays, which let you organize threads, discover other users, receive notifications, run searches, get an RSS feed, etc. However, without them the network would still work: users could keep publishing, following others and interacting. Relays are not the core of the social network. Clients can rely on them, but should never depend on them. This isn't a quality exclusive to Org Social: twtxt is also aligned with this principle. The point lies elsewhere.
The goal of clients is to make reading and writing feeds (social.org) easier, not to be a requirement to participate. That said, they are very practical for building your timeline, since you need to read and sort the feeds of the users you follow. For that there are Desktop and Android versions thanks to Emacs, plus a native iOS version written in Swift.
The differentiating point is balancing different user profiles via the infrastructure. For example:
social.org on GitHub, GitLab, their own server, etc. They control and manage where it is hosted and how it connects.It embraces every kind of user, without sacrificing the essence of the social network. You don't need to be an expert to take part, but if you are one, you control every byte.
Org Social doesn't just improve on twtxt technically: it also evolves the concept of a social network on top of plain text. It takes a step forward by providing more infrastructure and incorporating modern features.
The future is not about going massive or competing with Mastodon, but about satisfying a very small niche of users.
Focus on the content or on engaging with others, Org Social will take care of the rest.
-1:-- twtxt vs Org Social: the evolution of an idea (Post Andros Fenollosa)--L0--C0--2026-05-06T13:21:31.000Z
Yesterday I joined Sacha Chua for a new episode of her Emacs Chat
podcast, where we talked about Emacs and life. I gave a quick tour
of my Emacs configuration, discussing at length my configurations for
EXWM (Emacs X Window Manager) among other topics like Emacs's facility
for visually indicating buffer boundaries in the fringe by setting
indicate-buffer-boundaries and my convenience configuration macros.
The above video is provided with closed captions and the below transcript courtesy of Sacha with minor fixes and formatting by me. I've included some of Sacha's screenshots from our chat, you can see the rest on the episode's page on Sacha's blog.
A few links from our chat:
ffs (Form Feed Slides) package for simple presentationsIt was a lot of fun - thanks again for having me, Sacha!
Take care, and so long for now.
For the full transcript please see: https://kelar.org/~bandali/gnu/emacs/emacs-chat-202605.html
-1:-- Emacs Chat with Sacha Chua (Post Amin Bandali)--L0--C0--2026-05-05T23:43:44.000Z
Figure 1: JPEG produced with DALL-E 3
This is the fifth post in my series on Emacs completion. The first, Incremental Completing Read (ICR), explains what modern completion actually is, and how Emacs exposes it as a programmable substrate rather than a closed UI. The second introduced the VOMPECCC stack of eight packages covering the six orthogonal concerns of a complete completion system. The third toured spot, a Spotify client built as a thin shim on top of those packages. And the fourth built a produce picker from scratch, demonstrating the specific features that each VOMPECCC package provides.
This post is the practical complement to all the other posts. Here, we showcase over a dozen workflows I use every day. Most are powered entirely by features that ship in the box with the VOMPECCC packages, and there are 'Bonuses' which demonstrate workflows enable by 3rd party packages that build on top of VOMPECCC. The prose is deliberately thin, and you will find most of the demonstration is in the video below.
As in the previous posts in this series, the upper-right of my Emacs (in the tab-bar) shows the keybindings and command names I am invoking, so you can map what you see onto your own configuration.
Two configuration choices show up repeatedly and are worth naming once upfront so the keystrokes are intelligible.
Async split character. My consult-async-split-style is comma, not the default #. In Consult commands like consult-ripgrep, everything before the first , is sent to the external tool as the search pattern, and everything after is filtered locally with my completion style.
Orderless dispatchers. My orderless-style-dispatchers bind affix characters to matching styles: @ for Marginalia-annotation matching, ~ for flex, ` for initialism, ! for negation. Each can be a prefix or suffix on a component. My orderless-component-separator is also ,, so a single comma serves double duty depending on context.
consult-ripgrep → input your search term → embark-export → wgrep-change-to-wgrep-mode → edit as you like → C-<return>
consult-ripgrep with , splitting external (ripgrep) from local (Orderless): for example, error,handler,~retry,!test.
consult-buffer with narrowing keys: b SPC for buffers, f SPC for recent files, m SPC for bookmarks, p SPC for project items.
consult-line within the current buffer; consult-line-multi across all buffers (or the project, with a prefix argument).
consult-imenu within the current buffer; consult-imenu-multi across every buffer of the same major mode.
consult-info for Info manuals (Emacs, Elisp, Org, plus every package that ships its own .info file); consult-man for system man pages.
M-x window @frame. The @ dispatcher routes a component through orderless-annotation to match against Marginalia's docstring text rather than the candidate name. This lets you query for commands by what they do rather than what they are called.
C-> (embark-act-all) runs a single Embark action on every candidate currently surviving in the prompt.
You can also embark-select to create a subset of displayed candidates and use embark-act-all to act on only those selected candidates.
embark-become switches the active command (e.g. find-file → switch-to-buffer) without losing the input I have already typed.
xref-find-references (M-?, with xref-show-xrefs-function set to consult-xref) → embark-export → wgrep-change-to-wgrep-mode → edit → C-<return> to write your changes. This is very similar to the ripgrep version above but driven by the language server, so foo the variable and foo the unrelated comment stay separate.
consult-recent-file → embark-export produces a Dired buffer, putting every Dired operation (mark, copy, rename, chmod, batch shell command) on the recent-files set.
In any Vertico session, C-' jumps to a labeled candidate (Avy-style); C-" does the same jump and hands the candidate to Embark.
s-V (vertico-repeat) reopens the last completion session with its prompt, input, and selected candidate intact.
consult-ls-git surfaces working-copy status, tracked files, and branches in a single multi-source prompt with narrowing keys. A nice on-the-fly alternative to the Magit status buffer.
consult-gh-search-repos streams GitHub repos as candidates; C-= previews the README; M-S (vertico-suspend) (or simply moving your cursor out of the minibuffer) detaches the minibuffer for free reading; s-V (vertico-repeat) (or simply moving your cursor back into the minibuffer) resumes; C-. exposes Embark actions (clone, browse, view issues, view PRs, view files, fork).
consult-gh-search-code against the contents of every public repository on GitHub. You get the same VOMPECCC features, but with the search space expanded to "all open source code in the world".
consult-omni-web fans one query out across Google, Brave, Wikipedia, StackOverflow, YouTube, and a gptel-backed LLM source simultaneously; s-j / s-k jumps between source groups; C-= previews; C-. surfaces Embark alternates (open in EWW, copy URL, etc.).
What makes this so cool is that none of these workflows required a single line of custom code. Each is built entirely out of the features that ship with one or more of the VOMPECCC packages. Pick the two or three that map onto frictions you already feel, and the rest will reveal themselves ad-hoc as you encounter new frictions.
Over a dozen high-impact Emacs workflows are demonstrated in this post: multi-file refactor, two-stage ripgrep, unified buffer switching, line search with preview, symbol navigation, docs search, M-x by docstring, batch action, mid-prompt pivot, symbol-aware refactor, recent files as Dired, and quick jump + act, session resume. Each of these workflows is composed entirely from features that ship in the box with the VOMPECCC packages.
-1:-- Emacs Completion Showcase with VOMPECCC (video) (Post Charlie Holland)--L0--C0--2026-05-05T18:15:00.000Z
I understand the gravitational pull of Emacs though for me it's been Vim/Neovim. I've spent entire year trying out tools like VSCode and Atom and sure they had some features that were neat, but they were never Neovim.
It's been at least 5 years since I tried another editor for coding though after realizing that I'd just go back to Neovim, which brings me to my Emacs adventures. I tried nvim-orgmode and it sort of worked but had issues that I was never able to work through. Then I went back to Todoist for a bit and missed orgmode, even if it was a hobbled form in Neovim.
This led me to Emacs and orgmode which I've been loving for about a year now. Still I keep wondering if I should move my coding workflow to Emacs and abandon Neovim?
There is a pull to just use one tool.
-1:-- The gravitational pull of familiar tools (Post Curtis McHale)--L0--C0--2026-05-05T16:26:00.000Z
This month's carnival topic is "may I recommend...". I'm too new to Emacs to recommend some fancy package or an interesting workflow so I'll reach back to my 20+ years doing software and finding tools.
May I recommend....keep it simple. Don't grab 50 new things from some video or blog post that some creator put up. People do that because it looks cool and then they over complicate their systems and abandon them. They layer complexity that looks cool over a system that already is working for them to solve problems they don't have with solutions often produced by people whose job is to get a new piece of content out that will go viral and pay their bills.
Many times it doesn't even seem like the creator uses the system at all, it just looked cool and had the proper keywords for what's popular right now.
I say, identify a problem you actually have. Spend some time researching options. Try out a few of them to see what works. Then stop messing around with your system and get work done.
-1:-- Emacs Carnival: May I recommend... (Post Curtis McHale)--L0--C0--2026-05-05T16:11:00.000Z
Protesilaos (Prot) has an excellent post on keyboard ergonomics for Emacs users. He considers various strategies for making Emacs commands easier to use and less likely to cause RSI damage. He considers everything from split keyboards to evil-mode.
He says he has both a split keyboard and a keyboard with a normal form factor. He says that the split keyboard is not a magic solution and that what works best for him is to configure “one shot modifiers” where the modifier is simply pressed—but not held down—before the key it modifies. So, to use his example, Ctrl+x is typed by tapping the Ctrl key and then the x key.
Along with that he suggests ordering the modifier keys in a way you find comfortable. The most important thing, he says, is to keep the Ctrl key close to the space bar so that you can use your thumb to press it. It’s also important to have the modifier keys located symmetrically so that, for example, you can use either hand for the Ctrl key.
As for the common advice to map Caps Lock to Ctrl, Prot says that’s okay but that it encourages the bad habit of always using your left pinky for Ctrl.
There’s a lot more information in Prot’s post—including how to configure one shot modifiers—so be sure to take a look at it.
I’ve been incredibly lucky. I use a standard keyboard, map Caps Lock to Ctrl and don’t have any symmetric modifier keys. Nonetheless, I haven’t suffered any RSI problems despite spending the majority of my day at the keyboard. But, as I say, I’m lucky. The smart thing to do is to read and head Prot’s advice.
-1:-- Emacs Keyboard Ergonomics (Post Irreal)--L0--C0--2026-05-05T16:05:03.000Z
I almost always reach for project-vc-dir when I want a VC status overview, and most of the time this is exactly what I want, the whole project laid out in one buffer, every modified, added and unregistered file in the repo sitting right there, ready to be diffed or committed. But every so often, particularly when I am deep inside a big repository and I only really care about a single subdirectory's worth of changes, that project-wide view is, frankly, a bit too much. Too many rows, too much scrolling, too much noise.
So, what am I actually after?, I want the same vc-dir buffer, but scoped to whatever directory I happen to be looking at, most commonly the directory I have open in dired. And it turns out this is almost trivially easy in vanilla Emacs.
The bit I had not initially appreciated is that vc-dir itself already accepts a directory argument, it is the interactive prompt that steers you towards the repo root, because it defaults to (vc-root-dir) rather than default-directory. If you call it non-interactively with a subdirectory instead, the Git backend quite happily scopes the status listing to files underneath that path, even though the overall VC root is still the same project root.
So the fix is a tiny wrapper that just hands vc-dir the current default-directory and skips the prompt entirely:
(defun my/vc-dir-here ()
"Run vc-dir on the current directory (dired's dir when called from dired)."
(interactive)
(vc-dir default-directory))
Then, because the main place I actually want this is from within dired, a keybinding that sits nicely alongside the standard C-x v family:
(with-eval-after-load 'dired
(define-key dired-mode-map (kbd "C-x v D") #'my/vc-dir-here))
The mnemonic, such as it is, is that C-x v d is the normal vc-dir binding with its usual prompt, and capital D is the "here, right now, this directory" variant. Lowercase for the prompted version, uppercase for the zoomed-in one, which also pairs up nicely in my head with project-vc-dir being the zoomed-out project-wide thing on C-x p v.
So the little two-tier workflow I have settled into is:
C-x p v – project-vc-dir, show me everything in the projectC-x v D from dired – my/vc-dir-here, show me just this subdirectory
And that is really the whole post, nothing clever, no new package, just a three-line wrapper and one keybinding, but it has genuinely taken a surprising amount of friction out of navigating VC state in large repos where I know perfectly well the only thing I have touched is under src/foo/, and I do not particularly want to be reminded of every other outstanding change elsewhere in the tree.
And yes, magit can do this with some narrowing, but actually, I like vc-mode!
-1:-- A Zoomed in vc dir for the Current Directory in dired (Post James Dyer)--L0--C0--2026-05-05T06:50:00.000Z
I've moved the repositories of the geiser packages I maintain to codeberg, so make sure you update your remotes if you access them directly through git. The URLs are already updated in the ELPAs, so nothing changed if you installed them via their packages.
Seventeen years and running. Happy hacking!
-1:-- geiser moved to codeberg (Post jao)--L0--C0--2026-05-04T19:09:00.000Z
I chatted with Amin Bandali about Emacs, configuration, EXWM, keybindings, audio, and life.
View it via the Internet Archive, watch/comment on YouTube, read the transcript online, download the transcript, or e-mail me your thoughts!
Links:
Amin: So that's a brief introduction, and then I have an early init section for doing the early init file. There's a couple of subheadings here. Actually, let me enlarge the font size a little bit to make it more legible. OK, great. I do a couple of things here like disabling package at startup because I don't use package as I mentioned. I manually install and update my packages as git submodules in my configurations repository.
Amin: I set load-prefer-newer to t to make sure that I never load any stale code. For example, I might edit some Emacs Lisp file by hand and forget to byte compile or native compile it. And this tells Emacs to basically just use the version of these three variants that's the most recent. Yeah. Nothing super fancy here.
Amin: I turn off a couple of things that I find a little bit distracting, like the menu bar or toolbar. Although I do say here that for people who are new to Emacs, they're actually super helpful. Sure, it's a little bit of visual clutter, but in the beginning, it's really, really helpful to help you orient yourself of what mode you're in, what tools do you have available in your disposal. And even someone who's been using Emacs for more than 10 years, I also use it sometimes when I'm like… just starting to use a new mode. So yeah, good stuff.
Sacha: Yeah, and then you've got a whole bunch of things where you set some variables to nil temporarily to make it faster, so that's in your startup in garbage collection. Amin: Exactly. Empirically, there is no hard and fast science behind this. I experimented over the years. I'm pretty sure I believe the default, for example, the garbage collection cons threshold is about eight megabytes. I tried increasing that a little bit to see how much If I increase it to what point will it make my startup faster? And I found this 30 megabytes or mibibytes to be kind of a sweet spot. So I bump that up. And then after Emacs has finished initializing, in the after-init-hook, I just restore the defaults.
Amin: And then, yeah, this is the bit with the user-lisp-directory that I was talking about. Awesome stuff. So you can basically designate a directory. For example, in my configuration, it's just a lisp directory. And then on startup, Emacs will go through and byte-compile, native-compile if necessary, and then add all of that stuff to the load-path automatically. So you get that. Yeah, and then this is the bit about site-lisp that I was talking about. So if you want to use user-lisp, but you're still using older Emacs versions that you maintain, you need to maintain backward compatibility in your config. This is how you do it, for example. So you just yeah, add it to load-path, require it and then call prepare-user-lisp. That's about it.
Amin: Yeah, and then I have the main init file. And there's not much in it. It's just the debug-on-error and debug-on-quit. So the debug-on-error thing, I set it to the value of init-file-debug. And if you look at that, the help for this variable, basically if you pass or launch Emacs with --debug-init, this variable will be true. So yeah. Sacha: I did not know that. Cool. Amin: Yeah, it's pretty helpful. I think, if I'm not mistaken, I took this from John Wiegley's dotemacs, but I can't remember for sure. It's been years. Yeah, it's pretty nice. And then here, I just set my name and email address. And very early I set a custom-file to keep all of that stuff separate from my .emacs. I don't want it mixing in.
Amin: And then pretty much the only other thing that's in my main init file is just to require and load these different modules or packages of my configuration. I have these as actual packages or as actual features. They provide themselves. And that's just something that I've found straightforward enough to do. I know, for example, Prot uses a dual approach. He has some of his configuration that's more readily usable, available as actual packages. And then the other ones, it's just Emacs Lisp code. It's not actual packages. But for me, I just keep it simple. Everything as packages and that's about that. Sacha: Fantastic. Let's dive into some of those configuration modules. Amin: Sure, let's see. Yeah, so this there's this like core thing which is kind of included gets included in all of my other files.
Amin: I wrote a bandali-configure macro shamelessly based on prot-emacs-configure which is what Prot uses and it basically is a way of kind of similar to use-package for like wrapping a bunch of relevant like Emacs Lisp code all together. It has the benefit, if you use it, if there is an error in that block or in the body basically, then it won't crash everything. That body will just get ignored and we display an error. And that's also the main reason that Prot uses it. The one thing that I added extra to mine, which I took with inspiration from Eshel Yaron's esy/init-step, is to wrap it up in basically time the execution of each of these blocks, which can be pretty helpful to help you see, okay, which part of my configuration is particularly slow. Usage examples. I just have it here. You can either basically pass it like a symbol like thing or you can also pass in a string as the first argument. And this is what will be displayed when you display a list of the evaluation times for all of these blocks in your configuration.
Amin: Yeah, and then I have a neat little function here like bandali-configure-report-times that will report these times, whether in the order that it's encountered them, or you can have it sort by fastest to slowest, slowest to fastest, blah blah blah. Sacha: You mentioned you're no longer using this. Is it because you wanted it to be easier to copy and paste your code? What got you to shift back to the regular vanilla type of configuration? Amin: Right, as neat as it is, I didn't find it super useful. For one thing, because I don't add or remove a ton of stuff to my Emacs configuration regularly, so if there is an error, it wouldn't cause an issue for the rest of my configuration. I didn't really find that very useful. And then my other potential concern is that the way I was structuring things, I would put all of the configuration, let's say for Gnus, in one of these blocks. But I wanted to be able to break that down into, for example, Org Mode sections more easily. So far, I just decided to not use it. I know I could technically break those down into smaller blocks, but I haven't done that yet. Sacha: Ihor says, this configure macro looks a lot like good old use-package, which you're not even using in the rest of your config. And I hear you about wanting to be able to split things into smaller blocks with more explanations in between them. So in my config, yeah, sure, I've got the use-package there to do the ensure and all that stuff. But I also have with-eval-after-load because I still want, you know, the links and the screenshots in between.
Amin: Then I just have another quick macro thingy here, bandali-define-keys, which wraps around Emacs's define-key. It affords me the convenience of defining multiple key bindings, and Prot's version of this (I think it's prot-emacs-keybind, or something like that) he imposes the limitation that the keys should be valid strings that can be passed to the kbd function, which is very fair and valid, but I wanted to not impose that, to keep the flexibility of using define-key directly. The consequences of that, as we can see, is we can pass in the old representation of key bindings, like the vector or whatever syntax, which Prot's doesn't support by choice, whereas mine does. Let's see. For example, let's look at the bandali-theme.el, which is all about… The appearance, I guess, of Emacs.
Amin: Yeah, so I just have a conditional block where, you know, if you're in a graphical environment, I'll just go ahead and load Prot's doric-themes, specifically doric-oak, which is what we're seeing right now. I'm using, it's very beautiful, it's very subtle, and it uses emphasis, bolding and stuff to draw your eye to something instead of using a million different colours, which I find pretty nice. Yeah, and then for example here I set up some fonts. I use this Sahel font for Persian and Arabic text. I set a colour emoji font here and this is like we get a kind of preview of what I do. It's like with-eval-after-load 'faces and then blah blah blah. Sacha: Ihor would like to point out that with-eval-after-load is also a macro that calls another macro. So I'm just going to mention it because it's there. These are your fonts. This is your theme. This is great because everyone always asks, what theme is this? What font is this? All right.
Sacha: I like your text scaling tweaks that you're just about to go into. You've changed the global mappings. Amin: Yeah, yeah, yeah. And I actually took this from Prot as well. And it makes a lot more sense. So by default, this, C-x C-+, -, blah, blah, blah, it only scales the text for the current buffer only. But in newer versions of Emacs, in Emacs 29, they also added commands to adjust this globally, including the mode line and all that stuff, which is usually what I want, for example, in this presentation or when I'm sharing my screen right now. It scales everything up globally. So yeah, I just swapped these to be the default, and then I add keybinds for the just local variants in case I need to use that. Yep.
Amin: Start the Emacs server if it's not running. And this is very useful, very helpful so that then you can call into an existing Emacs process with emacsclient and have it edit a file. I don't use it for anything fancy just yet. I believe Prot also mentioned in his video with you, Sacha, that he uses it for things like org-capture to spawn a new buffer in his existing Emacs session and things like that. You can do pretty cool things with it. But yeah, I just use it for being able to easily use my Emacs as EDITOR and VISUAL text editors. So yeah, this sets that up.
Amin: Adding a fundamental mode hook. Again, I took this from Prot. Sacha: I was surprised by that because I was like, oh, there isn't a fundamental-mode-hook? Okay, that makes sense now. Amin: Right, right. Yeah, there isn't a fundamental-mode-hook by design. But I still, in the past, have found that I wanted that. For example, for this display-fill-column-indicator, when I had it enabled everywhere, I was like, it would be nice if I could at least disable it for Fundamental mode. And at the time, I didn't have this. I added this just recently. So if I decide to go back to using something globally, but I don't want it in fundamental-mode, then I can disable it using this. Yeah, and then some standard stuff like I prefer spaces and a tab width of four characters.
Amin: Visually indicate buffer boundaries. This is a little bit hard to see right now, but here at the bottom left
Amin: you see a little down arrow
Amin: and then the little top arrow. And… Let's see if I can. Sacha: Oh!
Amin: And also here, for example, when it all fits in the view. Sacha: Huh, that is cool. I was looking at that. What does it do? And so that tells you, you can still scroll up or you can still scroll down, and you don't have to look at the scroll bar to see where you are. It just says there's more there. Amin: Yeah, exactly. Yeah. And it also helps distinguish when there's a newline character at the end of the file or not. So here in this buffer, there is.
Amin: But if I delete that, you see this indicator here changed shape. But if I go back and add the new line again. So yeah, that's also been very helpful for me because I added configuration files and some of these pieces of software are sensitive to having a new line at the end of the file. So yeah, it's very helpful and useful for that. Sacha: I would not have guessed that from the very short line in your config that turns that on. It's one line, (setq-default indicate-buffer-boundaries 'left), and yet it adds this nice little nuance to the way that fringe looks. Amin: Right. Yeah, absolutely. Perhaps I should expand more on it at some point later to explain these things. But yeah, just this one line. Sacha: May I recommend screenshots? Amin: Yes, you may, for sure. Yeah, I will definitely do that as well, because I'm also a bit of a visual person. I like seeing screenshots and videos, so yeah I'll take that to heart and do that for my own configuration as well. Sacha: When I post this, I'll probably… I figured out how to have the transcripts and then screenshots embedded into my transcript. I'll generate it automatically from the subtitle file. Our EmacsConf transcripts are going to get so fancy next year. But you can pull those screenshots and drop them into your config. It'll be great. Amin: Nice. Yeah, for sure. Sounds good.
Amin: And then here, I just enable some of these commands that are disabled by default. So yeah, it's useful, especially narrow-to-page, for example, or narrow-to-region. These are commands where Emacs disables them by default so that newcomers don't accidentally hit them and get very confused by what just happened. It doesn't disable them for good. It just basically prompts you for confirmation. Are you sure you want to run this command? I'm sure, at least about these commands. So I just enable them. And then something like, for example, overwrite-mode, which I never use and I don't want to accidentally enable. I just put it disabled so that if I do accidentally hit the keys, which might be, I don't know, something insert or whatever, then it will prompt me to make sure that I meant to do that. Sacha: That reminds me, I should probably turn that off for myself and then you get a whole new keyboard shortcut you can use too. Amin: Right, yeah. Let's see.
Amin: Yeah, I have just one line setting for package.el. In Emacs 31, we will be getting a package-review-policy which is very helpful. So if you do use package.el for installing packages from GNU ELPA, NonGNU ELPA, MELPA or whatever else, you can enable this, and then whenever you update your packages, you'll get a diff of what changed in this new revision of the package that you're downloading and you're about to enable. And you can presumably say yes or at least see what's going on, which I'd find helpful. Sacha: But you're not using packages, you mentioned, so you're just checking everything out and then you're just git pulling whenever you feel like it. Amin: Yeah, so right now I'm using git pulls and git submodules, very manual. I put this here because I think it's generally a very welcome change and awesome new feature that I want to spread the word about. So maybe someone who's looking at my config, they use package and that's perfectly fine. So this is just here to spread the word about it mainly, I guess. And if I start using package at some point myself in the future, then I will have this enabled. Let's see.
Amin: Very quickly, here I extend Info-directory-list. I like to, at least on some of my machines, use Emacs that I built from source directly in the source repository of Emacs. Just after doing make, I don't run make install, even though it's very easy to do that. You can install to a custom location by providing --prefix when you're ./configure-ing Emacs. Sometimes I just find it more convenient for me to not do that and just run make and then exit and reopen Emacs. And for that kind of a setup, I just extend the Info-directory-list to include the info subdirectory of the Emacs source repository so that the built-in Emacs info manuals will be available to me.
Amin: And then I use recentf for tracking recent revisited files. I bind it to C-c f r e for me to get a pop-up completion for visiting a recent file, it has completion. So if I hit TAB here, for example, we can see some of these files or directories that I visited recently. Sacha: I see. And then you're adding the directory to it. So what does that let you do? Because I'm assuming you're already in there in the directory. But how does that change your recentf? Amin: Right. So I need to think to remember this, but I think the point of this was that if I open a project in VC or in Dired, then I would like that directory to also get added to my recentf files list, because I think by default, recentf only includes files, not directories. Sacha: You're in it, you start up Magit or whatever, and then you move on to something else, but you want to be able to easily go back to it. Amin: Yeah, for example, I like to keep my recently visited directories in recentf as well. Because that's one of the main ways I jump between projects and stuff, even though there is literally a built-in Emacs project mode, which I still use. The only thing that I have here is… I don't want to add my home directory to the recently visited list, so the only thing that this function does is to skip that if I'm opening the home directory. That's about it.
Amin: And then here I configure mouse and scrolling behaviour. So I want Emacs to scroll very gently, one line at a time. I think the default is that when you reach the end of the page, it'll jump half a page down and then recenter. I don't remember default behaviour because I don't use it very much, but yeah, this basically makes it very predictable. For example, when I reach the edge of the page here and I press C-n, it'll only scroll one line at a time, instead of jumping and then doing something like this. Sacha: Oh yeah, mine does! Mine doesn't do that, so it does that jumping thing. I see what you mean here. Interesting. Amin: Yeah, so you can tweak that with scroll-conservatively and then scroll-preserve-screen-position, I believe.
Amin: Yeah, and then I use autorevert, which is pretty helpful. So this will have Emacs watch, for example, files that are open in your buffers. And if they change on disk, Emacs will automatically refresh the buffer so that you get the latest version. The cool thing is you can press undo in one of these files that's been autoreverted so that you get the revision that was there right before the change. So I've used that sometimes as well. Sacha: Yeah, and sometimes autofollow also is nice for log files and things like that. But yeah, autoreverting is great. Amin: Yeah, for sure.
Amin: repeat-mode is something that I've only recently started using, especially with my Emacs EXWM setup, using Emacs as my window manager. For example, if I hit C-x o, we see here in the echo area where it says repeat with o or capital O. So I can now only press o instead of saying C-x o, C-x o to do that multiple times. Keymaps that have support for this basically indicate that they want to be repeatable can declare that. And then once you invoke one of the keys in those keymaps, then you can repeat it with just that single character. And for example, for my setup, I have that with my EXWM workspace switching keys. So I can easily go to the next and previous workspaces, many of them at a time by just pressing p and n instead of doing the shortcut multiple times. Sacha: And actually, if you don't mind jumping ahead, the EXWM part of your config is fairly complex, and I think not a lot of people have a lot of experience seeing EXWM in action. And I don't know whether you're comfortable sharing you switching around to different workspaces, but if that is something that you can do, how are you doing all this awesomeness? I'm still too scared to use EXWM myself. Stability. But that's a me problem, not an EXWM problem.
Amin: Yeah, EXWM was pretty awesome. I used it back in 2018, '19 for a while, and then I kind of moved on to Sway and Wayland. But I don't know. It's something that I feel like once you try it, you want to keep going back to it. So recently, this past month or so, I decided to give it an earnest try and try to actually address any pain points that I've noticed. So it's much more usable for me now, and I'm sticking with it for now. I'm not a Wayland hater, but I'm just saying, at least for now, I'm using EXWM. And I'm happy to talk about it. Sacha: OK, what do you love about your setup for that one? Amin: EXWM? Sacha: Yeah, yeah. Like, you're doing a lot of rename buffers. Yeah, yeah, yeah. Amin: Right. Yeah, let me think. There's a couple of things. So, for the longest time, my Emacs EXWM configuration used super key as a prefix, which is the Windows [key] or the one with the logo, basically, to switch workspaces, launch applications and such. And at least the way that EXWM is right now, it doesn't… Like the way you have to add those global key bindings kind of slows down the EXWM startup. And I had many such key bindings.
Amin: So one thing that I did kind of recently is to define a prefix map here, like bandali-prefix-exwm-map. So I bind all of the keys and commands that I want here, and then this helps me really minimize what I'm telling EXWM, which is here. For example, this is how you set global keys with EXWM, and I just point it to my prefix map. C-c x and then any of those letters and functions that we saw. That's kind of annoying. I still use the super key here, but I have it s-x and s-,. On the left-hand side of my keyboard, x is right next to super, so I can hit it in one go with one motion almost as a single key with these two fingers. On the right side of my keyboard, I don't have a super key, but I have a control key that I remapped to super. On the right side, I do s-, with these two fingers. It's still very convenient for me to invoke those commands. And pairing this up with repeat-mode, as we can see just here, actually, then I can hit s-, and then p, n, or h, j, k, l many times to switch workspaces or shift focus to different windows and stuff without having to hit that kind of annoying s-x or s-, repeatedly. Yeah. Sacha: That sounds really cool. I should look into that. Sorry, quick aside.
Amin: Some of these things, like browsers, I still do them frequently enough, and I use different browser profiles. So I just define a new keymap so I can basically one-shot launch Chromium or Firefox in a specific browser [profile] or an incognito window and such. So yeah, I just do s-x b and then, for example, c to launch Chromium and all that stuff. So I found this pretty convenient.
Amin: Speaking of key bindings, before I get down this, let's see if I can find… C-c h. I think this is just before my EXWM setup. I'm pretty proud of this. I love this. It really goes to show how awesome Emacs is and extensible it is. Let's see. So as we know, these various help commands and describe commands are under C-h prefix. But some of them are not bound, for example, find-library or describe-face. Some of these I use pretty frequently. I was really having trouble coming up with descriptive-enough keybindings or short-enough keybindings for all of them. I put some of them here, for example, like C-c f l for find-library. But I can't do that for all of them. What I did was just do C-c h a or C-c h d. What this will do is basically, if I show that, It basically opens up M-x, fills in describe-, and then I can just type, for example, face, and that's it. So it basically opens up the minibuffer for me, pre-fills it with the string that I want, and I can type what is it that I'm looking for. And I found this to be better than trying to bind a million different keyboard things for describe this and that, apropos this and that, find this and that. So yeah and the way that we do that is to just use a minibuffer-with-setup-hook, and you just have a little lambda to insert the string that you give it, and then you invoke it. Sacha: Yeah, this is pretty cool. When I saw that in your config, I was like, I'm going to steal that. Pre-filling the minibuffer but still letting you do stuff with it, it's such a powerful thing, not just for completing the command itself, but even for when you're using the command, but you want to do something with the input before. You don't want to do it all the way, send it in and submit right away. You want to actually do something with it after you insert it. So great tip. Amin: Yeah. Thanks. Yeah, it's pretty useful. It's pretty nice. Yeah. And then back to the Emacs or EXWM stuff. So before I had, I used to yeah, sorry, go ahead. Sacha: Sorry. I forgot whether I was muted or unmuted. Amin: Okay, no worries.
Amin: For the longest time, I had 10 default EXWM workspaces on startup, and that can slow things down a little bit. So I found that okay, I don't really use all 10 workspaces always. So I set it to 5. So I get five workspaces initially. But I still bind keys here. Like if we go down. Let's see. Here. So here, I define those keys for all the way from, let's say, from 0 to 9 for all 10. And then if I try to switch to a workspace that doesn't exist, then EXWM will just go ahead and create it for me. Yeah, so I found that pretty cool. You can create workspaces on the fly. Yeah. Sacha: Yeah, and I saw that it moves your current window there, too. So that's just like, OK. Let's move it to workspace number two or whatever. Very cool. Amin: Yeah, yeah, yeah. I have keys or convenience keys for moving some window to some workspace. Yeah, it's nice. Let's see. Let's see. Yeah. So these are just made key bindings. I use hjkl here for switching windows.
Amin: I also have a ZSA Voyager split ergonomic keyboard. I can basically customize it infinitely. For example, I don't really have a super key on the first layer. What I have is a key that will do the s-x thingy, basically, my prefix. So that's the last missing piece is that if I'm at home and if I have this keyboard with me, then I just hit one key and then that's it. I'm in my prefix. But even if not, on the laptop, the s-x or the super comma are still easy enough for me to hit it with one hand. Sacha: Now I'm jealous and I definitely want to assign my prefixes to their own keys. Very tempting. I've started using the numpad because my laptop has one. I only use the numpad rarely, but we all need more keys. Amin: Yeah, ergonomic keyboards are pretty nice, especially these ones. For example, the ZSA ones where you can put QMK on it, the QMK firmware. You can define keys in a C file. I can actually show that. Let's see… QMK Firmware, Keyboards, ZSA, Voyager, Bandali, and then keymap.c. Sacha: Is this in your repository somewhere? Amin: Right. It's in a different repository, but it's still on https://git.kelar.org next to my configs repository. You can find this as well, but if I go smaller… Yeah, you can define keys here and have different layers, like the base layer. And then you can define a key to switch between different layers and put some of the keys there anyway. So yeah, it's a whole rabbit hole in and of itself. Prot also uses a split ergonomic keyboard. It really does help if you're typing for long periods of time. I actually had these for a while, and I wasn't using them too much, but I started slowly getting some pain in my wrists and here. So I was like, okay, I have the keyboard, might as well put it to good use, and I've started using it.
Sacha: Okay, so most of your keyboard shortcuts come off that kind of s-x or C-c something, and then you have a long prefix sequence, and you just remember everything or you use your… pre-fill some of it and then fill in the rest of the command. Amin: Pretty much all my window management related keys are on this s-x prefix that I'm showing here. And then I have a few other ones which I think I showed earlier. Is it this one? Anyway, I bind a few general keys outside of the s-x thing, like C-c e i. For example, I have C-c e e for eval-last-sexp. I do that a lot, so it's easy to hit that. Making frames or deleting frames. Sacha: I love how Emacs uptime is something you use frequently enough that you have a keyboard shortcut for it. Amin: Yeah, of course. I mean, I'm sometimes curious to see how long has my Emacs session been running. To continue with the EXWM stuff, let's see. This is just some keybindings I define here. It's all Emacs Lisp, right? It's amazing. You can mapc over whatever sequence and create keybindings like that. Only with Emacs we can do things like that. I just love it. Let's see.
Amin: I still keep these three other keys for raising and lowering the volume and toggling mute off of that prefix and just directly on my keyboard, hitting it directly in the exwm-input-global-keys because I do that very, very frequently. But I also have scripts that I can invoke. I should do keycast. So yeah, I can invoke the prefix with semicolon. I can set my volume here, adjust it here, type in what volume I want, or with the single quote, I can enter a value for the screen brightness. I like these things to be exact depending on the lighting in the room. I have preferred brightness values of 50 or 12 or 10 that I manually adjust. I guess it's a poor man's version of having something with a light sensor that can pick up and adjust automatically. I do it manually. Yeah. Sorry, you just muted yourself again. Sacha: You're just probably this close to writing the Emacs Lisp that takes your webcam image and then adjusts your light. But I think Prot was also saying he likes to do the lighting changes manually as well because warmer colors versus cooler colors and all of that stuff. Anyway, so you have all these buttons that EXWM listens to and it can launch various things for. That's a lot of things. Amin: Yeah, those are pretty cool.
Amin: EXWM has this lovely feature called input simulation keys where You can basically use it to bring Emacs key bindings to other applications like Firefox or whatever. And yeah, it's mind blowing when you try it for the first time. for example, I bind C-b to just hit the left arrow on the keyboard. And it does that. So I can define all of these commands that I'm using or used to using in Emacs. So I can get them in Firefox or other applications as well. Realistically, it's mostly Firefox. It's the only other program that I spend any reasonable amount of time outside of Emacs. Sacha: Let me point out this very important one that you have there. Under selection/cut/copy/paste, I see a C-w input simulation key. So this is for all the people who have accidentally closed their browser tab while trying to copy text. This is how you solve that problem. Use EXWM and use EXWM input simulation keys and you don't have to accidentally close your browser tabs again. @blaiseutube asks, hey, what about time since last save? Or do you have some kind of autosave magic? you know, in reference to the uptime thing, right? You have this thing that shows you… Amin: I don't think I have anything for autosave, but I have this habit of… I save everything pretty regularly. Yeah, so I've never really needed that feature, but I'm sure Emacs has something where you can, at the very least, just very dumb, simple implementation of has it been idle for one minute, then just do a save buffer. You can roll your own. But I don't have anything. Sacha: All right. I'm getting really tempted now to try out EXWM, even if it's just for those global keyboard remapping things.
Sacha: How is it for windows that you've got to have floating? I feel like it's very good at handling tiling things, but how is it for sometimes the apps kind of really want the floating window? Amin: Right, yeah, so you can toggle any window to be floating or not, and you can also - actually, we're just looking at it here. EXWM manage configurations, to match on the instance name or the class name of a window that you can get from xprop, to automatically make that tiling. For example, if I do my prefix and then capital T, it launches a floating terminal for me here. And if I go back to where I set it up, I just launch Xterm with the -name argument. This is where it can set the instance. And I just put any string you can want, like floating, for example. And then here in my configuration, I just check that if the instance name is floating, then I'll go ahead and float the window. Simple as that. Sacha: All right. This is starting to look exceedingly tempting. Lol, I save everything regularly, so he's one of those people who compulsively hit C-x C-s. Amin: Yeah, I do that a lot. I don't know. It's just me. But, yeah. Yeah. And then, I don't know. EXWM is awesome.
Amin: You can also put local simulation keys, application-specific simulation keys, depending on, the application, terminals, for example, or, Zathura. This is a PDF viewer. To have application-specific custom key bindings, how cool is that? For example, if I'm in Xterm or something like the Mate terminal, hitting C-c C-c twice basically, it'll just send the C-c key to the terminal. Because one thing with EXWM is that you can set it to capture a couple of Emacs prefixes, like C-x or C-c. So the application by default doesn't see it because Emacs captures it. But this is one of those mechanisms by which you can send a key through. Let's see.
Amin: So this thingy here, I enable EXWM and I add this rename hook and all it does is basically to add the window titles to the buffer that I can see on the mode line. But as long as it's within a certain reasonable length, like for example, I have 25 characters. If it's longer than that, it will just put dot dot dot (...). So yeah, that's all the purpose of that. Let's see, for example, if I launch Xterm, it appears there. The perfect example is actually here on the right-hand side. On the mode line, we see Firefox ESR Emacs Chat. It's a bit long, so it just puts the dot dot dot there. So that's all that does. Sacha: Yeah, now being able to use Emacs to manage the tiling of these things instead of my having to fiddle with alt-dragging things to snap nicely into buffers. Yes, very cool stuff. EXWM. Gotta try it. Amin: Yeah, for sure. Yeah, let's see.
Amin: Here I launch Dunst if the executable is installed for getting notifications in EXWM. I think there's at least one or two Emacs specific packages that implement a simple notification daemon or backend so that Emacs itself can handle that. But I found Dunst good enough for my use cases coming from i3, Sway, like tiling window manager background. I just reuse that. So yeah, I just start a process, keep a handle of it in this bandali--dunst-process variable here. And this thing I discovered recently, it's cool. using set-process-query-on-exit-flag, you can basically have Emacs not ask you if you want to exit Emacs if that process is still running. It'll just kill it without confirming with you. So just a little convenience. Sacha: That is also cool. Just a heads up, I have about 15 minutes before the kiddo runs out because she'll be done with school then. Even just the EXWM part and other things that you've shown us in the config have been super awesome. But are there other things in the next 15 minutes that you would love to show people so that they can see how it works in practice?
Amin: One thing I'll just mention, EXWM, one more thing, and then I'll go check. I think this is kind of recent: EXWM xsettings, and this allows you to dynamically at runtime change some of these things that you would normally set in an X resources file, like fonts. These kinds of settings were especially commonplace back when Wayland wasn't a thing or wasn't very popular. You would set some of these font settings there. With EXWM xsettings, you can do this dynamically, and what's awesome about that is it also lets you hook into, for example, if your screen configuration changes, if you plug in a monitor or unplug it, then you can run whatever xrandr command to set it up and also adjust those settings. The main thing I use it for is to change the DPI setting. The thing with X11 or Xorg is, unfortunately, there's no per-monitor DPI. There's one global DPI. But I found that on my high-DPI laptop screen, if I set the resolution to 1920x1080 instead of the full resolution, then the default DPI of 96 works just fine with my external monitor as well. All this little hook does, by calling into this function, is: if I'm plugging in my external monitor, lower the resolution and lower the DPI, and if I unplug it, go back to the high thing. I just love this. Sacha: That's great. We're definitely not going to demonstrate that because plugging in and unplugging monitors is not a good thing for screen sharing, but that sounds really cool. When things change, you can actually get your system to adapt to the changes for you. Amin: Yeah, it's lovely. Let's see. There's so much more to talk about.
Amin: I have written some things about the prompt for this meeting. Yeah, so I talked about that stuff briefly. Minibuffer setup. Things that I love about my setup is that it's kind of portable, simple. People can easily copy things from it if they want. It's kind of self-contained. And that was kind of a big thing a while back when I wanted to use my configurations on a couple of work machines. And these don't have direct outbound internet access. So I couldn't do things like installing packages with ELPA because that's done over HTTP. So yeah, I use submodules now. I recently began documenting my setup, very much inspired by Prot and Sacha and others.
Amin: This is my configurations repository. If you go here to treeview .emacs.d, this is the org file. I also export all of those individual components into this lisp subdirectory. All that stuff is here. The QMK thingy that was mentioned.
Amin: Oh, I wanted to mention FFS. Okay, I'll do that as well. Yeah, what's up with that? Sacha: I was trying to find information. It was like, there's no package. It's not what is this thing? Amin: It's FormFeed Slides and it's going to soon be a package. I was actually talking to Prot about it and I'm hoping to submit it for inclusion in GNU ELPA within, I don't know, the next couple of weeks. It's basically very similar to Prot's Logos package. Turns out we both had the same kind of idea at the exact same time in 2022, and we both used it for our LibrePlanet 2022 presentations. Of course, Prot being the diligent person that he is, he polished his work, documented it, put it on GNU ELPA. I still haven't gotten around to doing it yet, but better late than never. Yeah, let's see. I can maybe show a quick demonstration of that. So let's see. Let's see. Anyway, so if I go to my website sources and net-beyond-web. So I had the LibrePlanet talk a couple years ago. So what FFS is basically, it looks for a particular character in this case, or the default case, it's the page-delimiter, ^L, which you can insert by hitting C-q C-l. It basically then designates each of these areas as one slide. So, very, very simple slideshow that you don't even have to use Org or outline or any other major or minor mode. If I launch ffs, by default, it's in a mode where it binds a couple of convenience keys, like p and n, to go into the next and previous slide. You can hit e to edit a slide, similar to Org source, and then make your changes and all of that. And then you can start a presentation by hitting s.
Amin: It has hooks for, for example, bumping up the font size or whatever, hiding the mode line. I can toggle the mode line by hitting m here. Let's see. I can also toggle the cursor with c, to make the cursor visible or not. So, yeah. And then I'm just hitting p and n. Sacha: Very simple, very minimalist. You have a file, you've got page markers, and that's all you got. Amin: Yeah, pretty much. And then…
Amin: So you can designate a file as being the speaker notes where it has the same structure separators with ^L. But you can type your notes over here, whatever. And you can basically open these in two different windows or two different frames on separate displays. And then in whichever one of those you advance the slides, like p n n, it also does the other one. Sacha: That's brilliant. I was looking for a way to do that so I can pretend to know what I'm talking about when I have something on screen, but I can just read my notes or even just remember what points I wanted to make. So this is great. You have speaker notes. You've got the main screen. They can be in two different frames. You can have your frame that you're sharing and your frame that you're not sharing that has all of your cheat sheets. Excellent. And on that note, in about one minute, the kid is going to come running out and want to have snack and all that stuff. Thank you so much for walking through parts of your config. There is more. And so everyone who wants to find out more can go check out your setup. I have a great many things that I want to try out, starting from EXWM to little things like figuring out a boom mic setup because apparently your audio setup is making me very jealous. Yes, thank you for doing this. I'm going to post the transcript and the chapters. I have a chapter every minute. It's going to be a long time. But it was good. Lots of cool stuff. Thank you again. Amin: Sounds great. And yeah, you're very welcome. And thank you so much for having me as well, Sacha. I'm very delighted to be here, especially, I think, just by chance. I think I'm the first person who you're doing this with after the long hiatus. So that's an extra honor for me. But yeah, it's been fun. I could go on for hours. I'm sure we both could. This has been fun. Sacha: If we wanted to go on for hours, Prot has more flexible scheduling, so he can chat with people for two hours and stuff, and you already have conversations going on with him. But I unfortunately have a small mammal who's 10 years old and loves me very much, and likes to not let me concentrate for very long. But thank you everyone for joining. Thank you for the chat. And thank you also, stream, for all the interesting questions. I will send you all the information and update the post. And we'll see you all on Thursday. I've got another chat. All of a sudden, all these Emacs chats are going to happen. Thanks. Oh, and you said you're happy to be on the hook for doing another EmacsConf this year, right? Amin: Yes. You can hold me to that. There will be another EmacsConf this year and I will be active in it. Sacha: Alright then, I'm going to end that broadcast. Thanks everyone, bye! Amin: Thank you, bye bye!Find more Emacs Chats or join the fun: https://sachachua.com/emacs-chat
You can comment on Mastodon or e-mail me at sacha@sachachua.com.
-1:-- Emacs Chat 21: Amin Bandali (Post Sacha Chua)--L0--C0--2026-05-04T18:28:11.000Z
David Dimagid wrote this post for Emacs Carnival May 2026: "May I recommend…". Here it is!
Someone recently said on emacs-devel that they'd like to talk about recommending ELPA packages. Someone else said we should first ask what "recommending" actually means. RMS opened a thread asking that very question. It's still open, and you can follow it there (ELPA: to curate or not to curate).
I think we could apply Rich Hickey's technique here and start by looking up the definition of "recommend" in the dictionary. I invite everyone to do so with whatever dictionary you have at hand and to trust your definitions.
Now, we could evaluate ELPA packages for recommendation based on whether they complement or improve functionality already present in the core. For example, diff-hl by Dmitry Gutov. Its description says:
diff-hl-mode highlights uncommitted changes on the side of the window, allows you to jump between and revert them selectively. In buffers controlled by Git, you can stage and unstage the changes.
That last feature —staging partial hunks— is missing from VC, and diff-hl adds it seamlessly. We could say diff-hl complements the core.
Then there are major mode packages, like csv-mode, markdown-mode, cobol-mode, and so on. They add functionality that doesn't exist in the core. They have no direct equivalent. We could call them standalone packages.
Now consider another excellent package, like diff-hl, that depends only on the core: expreg, by Yuan Fu, the region expansion package. With a single key, it expands the region based on context. The core already offers this through sexp movement commands, but not with a single keybinding — you need several. Some will prefer the native core way; others will prefer the package. We could say expreg improves or, depending on how you look at it, duplicates the core's functionality.
So, in my opinion, package recommendations should be structured around their relationship with the Emacs core. I believe the best-regarded ELPA packages should be those that encourage users to use what the core already offers, first and foremost, and then try those packages because they extend a feature the core lacks or complement it. This would also help more people discover lesser-known core features, increase bug reports, and, over time, bring more contributors to Emacs. That way, the Emacs community could have a package repository it can trust for as long as Emacs exists. Perhaps the person who wrote Elfeed would have known about Newsticker and would have contributed to that package instead. Perhaps if we recommended what Emacs already offers, the Elisp we write would be Elisp of and for Emacs.
If you e-mail me your comments, I can forward them to David!
You can e-mail me at sacha@sachachua.com.
-1:-- From David Dimagid: What we talk about when we talk about recommending Emacs packages (Post Sacha Chua)--L0--C0--2026-05-04T17:06:00.000Z
It's May and I like puns, so I'm going to suggest "May I recommend…" as our Emacs Carnival theme this month, building on lively conversations about people's favourite packages on lobste.rs, Reddit, and Hacker News. Let's go beyond packages and talk workflows, tips, practices, perspectives… whatever you'd recommend!
It was pretty nice having a wiki page that people could edit without needing to wait for me, so if you write about this topic, feel free to and add your link. If you run into problems doing that, please e-mail me and I can add the link for you.
People have already started sharing their recommendations:
I'll also do a round-up post at the end of the month so that it shows up in people's RSS feeds.
Looking forward to seeing what y'all recommend!
You can e-mail me at sacha@sachachua.com.
-1:-- Emacs Carnival May 2026: "May I recommend..." (Post Sacha Chua)--L0--C0--2026-05-04T16:50:38.000Z
Thanks to everyone who shared their thoughts on the April 2026 Emacs Carnival theme of Newbies and Starter Kits. Check out that post to see all the entries people have shared so far. I enjoyed chatting with Prot about the topic, and he shared some defaults that even experienced users have been trying out. The carnival theme for May 2026 is "May I recommend…". Looking forward to reading your posts!
Links from reddit.com/r/emacs, r/orgmode, r/spacemacs, 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!
You can e-mail me at sacha@sachachua.com.
-1:-- 2026-05-04 Emacs news (Post Sacha Chua)--L0--C0--2026-05-04T13:08:22.000Z
Tools
Update: There are some legal issues associated with the Notepad++ product I talk about here. Trademark Violation: Fake Notepad++ for Mac | Notepad++. The original author says that the macOS version is an unauthorized clone. I am not going to cover this product. The macOS version has been renamed to Nextpad. Sounds shady as fuck.
That is all I have for today.
macosxguru at the gmail thingie.
Note: Thanks to Skylar Kang for the picture.
-1:-- Links of Note 2026-05-04 (Post Bicycle for Your Mind)--L0--C0--2026-05-04T07:00:00.000Z
Recently I realised that it'd be really nice if jumping to errors would store the previous location in the Evil jump list. These definitions do just that
(evil-define-motion mes/evil-goto-next-error (count)
:jump t
(unless (bound-and-true-p flymake-mode) (signal 'search-failed nil))
(flymake-goto-next-error count))
(evil-define-motion mes/evil-goto-prev-error (count)
:jump t
(unless (bound-and-true-p flymake-mode) (signal 'search-failed nil))
(flymake-goto-prev-error count))
and for now I've bound them to C-j and C-k (because that's what
evil-collection does)
(general-def flymake-mode-map
:states 'normal
"C-j" 'mes/evil-goto-next-error
"C-k" 'mes/evil-goto-prev-error)
This makes it easier to make a change, fix the errors caused by the change and then return to where I was.
-1:-- Jumping to errors in Evil (Post Magnus)--L0--C0--2026-05-04T06:16:00.000Z
Raw link: https://www.youtube.com/watch?v=UqfZZRl_eNw
On the 14th of May we will meet with Sacha and Philip to talk about
the upcoming Emacs 31 and other developments heading into Emacs 32.
Philip is a contributor to core Emacs and the main driver behind the
new newcomers-presets theme, among others. We will cover themes
related to the newcomer experience.
I am looking forward to it!
-1:-- Emacs live with Sacha Chua and Philip Kaludercic on 2026-05-14 17:30 Europe/Athens (Post Protesilaos)--L0--C0--2026-05-04T00:00:00.000Z
This is an excerpt from an exchange that I am reproducing with permission from my correspondent. I am not sharing their contact details.
As I understand, you’re using the regular keybindings in emacs. I’m trying to transition away from the vim way of editing text and was wondering if you’re using a more ergonomic approach for your text editing needs. I remember you were using some ergo split keyboards for that?
Indeed, I have a split mechanical keyboard (a gift from a person who identifies as “Andreas”). It is the Iris revision 8 by Keebio. I also have a regular full-sized keyboard (a gift from Arialdo Martini), which is the Keychron K5.
[ Keyboard-related articles of mine: https://protesilaos.com/keeb/. ]
The split keyboard is nice, though it is not a magical solution. Even
with a regular form factor keyboard, I can work with the standard
Emacs keys without any problem. What helps me the most is to configure
one-shot modifiers. This means that I can tap (press once, then
release) a modifier key, then tap a regular key to register it as a
modifier+key event. For example, C-x is this: tap Ctrl, then tap
x. Shift tapping is especially nice for prose, by the way, and
eases the pressure on the otherwise weak pinky. The time window for
registering a one-shot modifier is configurable.
The other useful tweak for a regular keyboard is to rearrange the layout of the modifiers. I prefer this order:
Super Alt Ctrl Space Ctrl Alt Super
[ If there is a Menu key, move it to the right corner and consider
assigning it to the Compose key if you are on Linux. ]
Now Ctrl is under the thumb, which is especially nice for Emacs.
Alt and Super can be swapped, if you use Super more heavily
(e.g. with a tiling window manager). But the important part is to keep
Ctrl close to the Space key.
Whatever you do though, remember to use both sets of modifiers. For
example, C-x involves the right hand for Ctrl and the left hand
for x. C-p needs the left hand for Ctrl and the right hand for
p. This way you distribute the burden so no one side is overworked
(and, of course, you take regular breaks from typing altogether).
Lots of Emacs users will rebind Caps Lock to Ctrl. While this is
fine in its own right, it tends to embed bad habits, such as with
using only the left hand to register the very common C-a, C-e,
C-d, C-f, C-s, C-r, C-w, C-g, C-z, C-x, C-c, C-v.
Exclusive left-handed use involves awkward twisting of the muscles
which will probably hurt you over time. Plus, the left pinky is forced
to press and hold a key while being stretched—looks bad. Again,
distribute the load.
The final part that makes everything easier is to configure a “layer”
key. When you press and hold this key, other keys register a different
input than normal. For example, Caps Lock can be the layer key,
which then makes h, j, k, l act as arrow keys. Same idea for
mapping Home, PgDn, PgUp, End someplace that makes sense (mine
are on y, u, i, o). I prefer to have Space as that layer
key: it only is a layer when I press and hold it, otherwise it
performs the ordinary function of the Space key.
It is okay to press and hold Space because you do it with your
relatively strong thumbs. Better have it this way than pressing and
holding with the pinkies.
All this can be achieved with software such as kanata. A custom
keyboard with QMK firmware can get the same configuration embedded
directly in the keyboard (so it works without any special program
running on the computer). Kanata will be the cheaper solution and is
probably better overall if you consider that it can apply to a
laptop’s keyboard.
A mistake in all this is to think that an expensive keyboard is inherently more ergonomic. If you keep curling, overextending, or anyhow stressing your muscles the injuries will occur regardless. A new keyboard can help if you use it as an opportunity to retrain your muscle memory.
Custom keyboards have potential advantages in terms of comfort because you can change the switches and keycaps that they use. For example, you can pick a lighter or heavier switch to match your typing technique. Then you can combine it with a shallower or steeper keycap profile to get the most out of that setup. There is no right or wrong here. It is a matter of optimising on top of the strong fundamentals that I outlined above.
As for evil-mode in Emacs, I think it is a good solution overall.
You do, however, need to install the evil-collection package and
probably also configure lots of other key bindings to get exactly what
you want. There are other packages that give you modal editing, though
I have only ever used evil-mode in earnest: it is fine.
That granted, I find that I do not like modal editing in general. It is especially inconvenient for me when I write at length (which I do a lot) because I tend to produce a wall of text in one go. Having a modal interface gives me no advantage in this common scenario. I also doubt it ever gave me the edge while programming. The bottleneck is how quickly and clearly I can think, not how fast I can edit lines of text (though, yes, Vim’s paradigm is powerful).
Consider then the overall comfort of your setup. Both in terms of the ergonomics of hardware but also how much effort it takes to maintain your Emacs configuration. The standard approach to key bindings gives you something that “just works” with practically every package you install. It may feel awkward in the beginning if you are coming from the Vim keys, but will be the most robust solution long-term from the perspective of maintainability.
-1:-- Re: Emacs and keyboard ergonomics (Post Protesilaos)--L0--C0--2026-05-04T00:00:00.000Z
I love teaching. I do not love grading, though. I’ve always thought it would be an ideal job if there were no requirement for grades, and if there were no grades, then there would be no need for exams. This, of course, isn’t true. In an ideal world, each student would be motivated to acquire knowledge, wisdom, and understanding, not a mere grade. Good students would still want some kind of assessment, so that they could know if they had reached their desired level of understanding. It seems that I can’t escape the necessity of testing.
I prefer to give essay exams in my upper-level courses, but the larger sizes of introductory courses make that impractical. Multiple-choice questions are easy to grade, but good ones are difficult to write. It would be nice to have a question bank from which I could easily choose questions to include on an exam, all stored in an easy-to-write format that could be used to produce both online and print versions of a test. This sounds like a perfect task for Emacs and Org mode.
Two years ago, I posted my method of writing quizzes in Org mode for import into Canvas, the LMS our university uses. I decided to use this format for multiple choice:
1. Multiple choice question (single correct answer)
a) Wrong
b) Wrong
c) Right*
d) Wrong
The multiple choice question bank will then consist of a collection of enumerated Org mode lists, something like this:
1. Why is global skepticism especially difficult to rationally respond to?
a) It requires accepting the existence of the external world before any argument can begin.
b) It is logically self-contradictory and therefore cannot be engaged directly.
c) There are no premises the skeptic would grant that could be used against the position.*
d) It collapses into local skepticism when pressed by careful argument.
2. What is Mackie's central claim in "Evil and Omnipotence"?
a) The existence of evil makes theism unlikely but not impossible
b) Religious beliefs about God and evil are positively irrational, not merely unsupported*
c) Omnipotence is logically incompatible with omniscience
d) The free will defense successfully resolves the logical problem of evil
3. Why is proving the nonexistence of the evil demon insufficient to establish knowledge of the external world?
a) The evil demon could simply be replaced by an equally deceptive force.
b) Disproving active deception still leaves open the possibilities of dreaming and naturally broken senses.*
c) The evil demon argument applies only to sensory knowledge, not to rational knowledge.
d) Proving a negative is logically impossible within Descartes' method of doubt.
I decided to have a frame split into two windows, the question bank in one and the scratch buffer in the other. I’d like to select questions from the bank and have them copied to the scratch buffer. Here’s the function that I wrote with the help of Claude:
(defun rlr/copy-mcq-to-scratch ()
"Copy the multiple choice question at point to the *scratch* buffer."
(interactive)
(save-excursion
(let* ((question-start
(progn
(end-of-line)
(if (re-search-backward "^[0-9]+\\." nil t)
(point)
(error "No question found at point"))))
(question-end
(progn
(goto-char question-start)
(forward-line 1)
(if (re-search-forward "^[0-9]+\\." nil t)
(match-beginning 0)
(point-max))))
(text (buffer-substring-no-properties question-start question-end)))
(with-current-buffer (get-buffer-create "*scratch*")
(goto-char (point-max))
(insert text)))))
If the point is anywhere in a question or one of its answer options, calling rlr/copy-mcq-to-scratch appends the question to the scratch buffer. I could use a keybinding for this, but I’m not sure I write exams often enough to waste a good keybinding. It’s easy enough to create a quick keyboard macro to select the first question and then press F4 for other questions.
If I want to create a Canvas Quiz, then it’s ready to be converted into a QTI file using the method I wrote about earlier. For print exams, I use the LaTeX examdesign class1, which requires this format for multiple choice:
\begin{question}
Multiple choice question
\choice {Wrong}
\choice {Wrong}
\choice[!] {Right}
\choice {Wrong}
\end{question}
To convert the questions, I select the entire scratch buffer and call this function. It formats the questions properly and inserts a blank line between each of them.
(defun rlr/org-mc-to-latex-questions (beg end)
"Convert org-mode multiple choice questions in region to LaTeX format. Questions are numbered lines followed by lettered choices (a-z). Correct answers are marked with * after the choice text."
(interactive "r")
(let* ((text (buffer-substring-no-properties beg end))
(lines (split-string text "\n"))
(result '())
(in-question nil))
(dolist (line lines)
(cond
;; Numbered question line: "2. Question text"
((string-match "^[[:space:]]*[0-9]+\\.[[:space:]]+\\(.+\\)$" line)
(when in-question
(push " \\end{question}" result)
(push "" result))
(push " \\begin{question}" result)
(push (format " %s" (match-string 1 line)) result)
(setq in-question t))
;; Choice line: " a) Choice text" or " a) Choice text*"
((string-match "^[[:space:]]*[a-z])[[:space:]]+\\(.+?\\)\\(*\\)?[[:space:]]*$" line)
(let* ((text (match-string 1 line))
(correct (match-string 2 line))
(tag (if correct "\\choice[!]" "\\choice")))
(push (format " %s {%s}" tag text) result)))))
(when in-question
(push " \\end{question}" result))
(let ((output (mapconcat #'identity (nreverse result) "\n")))
(goto-char beg)
(delete-region beg end)
(insert output))))
The next tasks are functions for easily removing and reordering questions. For that, I should probably wait until finals are over, though.
Now, unfortunately, it’s back to grading.
EDIT (May 4, 2026):
I must not be able to think when it’s later in the day. Reordering the questions is easy. Since they’re just Org lists, M-up and M-down moves an item and its child lists up and down. Deleting questions is not quite as easy, but it still wasn’t difficult:
(defun rlr/delete-mcq-at-point ()
"Delete the multiple choice question at point, including all its choices."
(interactive)
(save-excursion
(beginning-of-line)
;; If on a choice line, move up to the question line first
(unless (looking-at "[[:space:]]*[0-9]+\\.")
(re-search-backward "^[[:space:]]*[0-9]+\\." nil t))
(let ((start (line-beginning-position))
(end (progn
(forward-line 1)
(if (re-search-forward "^[[:space:]]*[0-9]+\\." nil t)
(match-beginning 0)
(point-max)))))
(kill-region start end)))
(org-list-repair))
I used kill-region to save the question to the kill ring, followed by org-list-repair to renumber the list. Killing instead of deleting is useful in cases where one might want to move the question farther than would be convenient with a simple reordering.
There are several LaTeX packages for producing exams. I’ve found that examdesign has the best combination of features for my needs. It can be used to easily print different versions of an exam to discourage cheating with an answer key for each version. It can handle five different types of questions, and has a block environment for questions that need to be placed in a group with instructions for the group. The questions in the block stay together even if the rest of the exam is randomly shuffled. If you need printed exams, I highly recommend it.
-1:-- Managing Multiple-Choice Questions With Org Mode (Post Randy Ridenour)--L0--C0--2026-05-03T19:31:00.000Z
Protesilaos (Prot) has a new, interesting package available: buffer-to-pdf. It does just what its name suggests. It takes the current Emacs buffer and exports it to PDF preserving things like theme, and font characteristics.
It’s easy to use. You simply call buffer-to-pdf and you get a PDF of your current buffer. You can specify the orientation—portrait, landscape, or current window—for the output but that’s the only choice you have to make.
The most complicated thing about the package is its pagination. If you have an Org file, each headline is a new page. The idea is to turn it the org file into a set of slides. Again, this all happens automatically.
For a simple text file, buffer-to-pdf paginates at screen borders. That seems like a natural thing to do and allows a certain amount of control over where the page breaks occur by adjusting the window size.
Finally, you can specify explicit page breaks by inserting a form feed (^L). Prot’s video doesn’t make clear how the form feeds interact with the window boundary heuristic but, as Prot says, the best way of thinking about buffer-to-pdf is as a screen capture that produces a PDF. It’s a perfect way to share an Emacs buffer with someone else.
If you’re interested in this package, take a look at Prot’s video at the above link. You can check out the package’s Git repository here.
-1:-- Prot’s New Org-to-buffer Package (Post Irreal)--L0--C0--2026-05-03T14:42:33.000Z
I’ve been looking for (or rather, chasing!) the right note-taking workflow in Emacs for over a decade now. Back in 2013, I wrote about setting up Deft mode with Org-Mode and it was my attempt at bringing that Notational Velocity-style simplicity into Emacs, and I used it for a long time. I genuinely liked Deft, but it’s no longer actively maintained, and the same goes for Zetteldeft which was built on top of it as an alternative successor. Since then, I’ve tried the other major players – org-roam, Denote, and a handful of others. They’re all extremely impressive and comprehensive packages that do more than I could ever ask for, but none of them ever quite stuck for me. I’d set one up and more or less force myself to use it for a few weeks, and then quietly drift back to a loose pile of org files in a directory. And on my darker days, Apple Notes.
The problem was never these packages – it was more me and my typical, simple workflow that I’ve grown so used to over the years. Learning a new tool carried implicit friction points that compounded over time. Org-roam is powerful, but it is opinionated about note creation - every note needs a unique org-id property and lots of frontmatter that I often had to lookup from previous notes to even remember what to include. The whole system, when used correctly, is backed by a SQLite database via emacsql that indexes your nodes and links. That’s a lot of overhead in my candid opinion. If the database gets out of sync or emacsql has compilation issues, you’re debugging infrastructure instead of taking notes. This was another pain point of mine since I often work on multiple machines (work, personal).
On the other hand, simple tooling like ripgrep is plenty fast for searching files, and removing the database removes an entire category of things that can break – especially for newer users who are already navigating the Emacs and org-mode learning curve. Denote is a great package that uses a lot of good, well-thought-out ideas and tooling, but I found it had a higher barrier to entry and is a bit opinionated in favor of note-taking workflows that I just never adopted or used over the years. This isn’t meant to be a knock on org-roam or Denote - it’s all my preference – but I wanted something that fit how I actually work without getting in my way - and something that I knew I would use long term. The note-taking workflow I wanted is something that felt closer to just opening a folder of org files, but with the modern conveniences that tools like Obsidian offers.
So I wrote grove.el.
Grove is an Obsidian-like note-taking mode for Emacs. One keybinding opens a full workspace with a file tree sidebar and your org notes. No external Emacs dependencies, no databases – just org files, a directory, and ripgrep.
The feature set covers the things I actually want and use daily:
[[note title]] syntax, click to follow, creates the note if it doesn’t exist#hashtag and org :tag: syntaxThe honest answer is that I wanted a note-taking system that I’d actually use. Every previous attempt had some piece that didn’t fit my workflow, and over time that friction compounded until I stopped using it entirely.
What I kept coming back to was how simple tools like Obsidian feels. Yes, I know - it’s basically org-mode but with a pretty GUI! But you open a vault, you see your files, you write notes with wikilinks, and the tool stays out of your way. The graph view is a nice addition - nothing new, but something that I knew I wanted to try and recreate in a less complex fashion. The sidebar is useful visually - often times it is very beneficial to focus on a single, solo buffer, but when it comes to note taking, visually seeing the other notes can add extra context without overloading you - enabling you to add categorization and linking with minimal overhead. My intention was to create something that doesn’t prescribe a methodology - you can do Zettelkasten, GTD, or just free-form notes, and Grove doesn’t care. I wanted that same feeling and purpose that I get when I’m in Emacs, where I already spend a good portion of my day.
Grove is intentionally less opinionated than many of the existing note-taking packages in the Emacs ecosystem. There’s no enforced file naming scheme, no required metadata format, no database to maintain. Your notes are org files in a directory. If you stop using Grove tomorrow, your notes are still just org files. I think that matters most in the end - when you stop using a tool, the underlying bits don’t change, including yourself.
At the same time, I wanted it to be batteries included. One of the barriers I’ve seen with Emacs note-taking setups is that getting everything working – the sidebar (especially this!), the linking, the search, the capture workflow - it all requires stitching together multiple packages and a fair amount of configuration. Grove bundles all of that into a single package with sensible defaults. The goal is that a new user can install it, point it at a directory, and have a complete note-taking workspace immediately. Whether you’re new to Emacs or have been using it for many, many years, the setup cost is minimal and investment low.
Grove requires Emacs 29.1+ and ripgrep. Graphviz is optional for the graph view, and Consult is optional for enhanced search.
Grove is currently in review for MELPA. Once it is approved and merged, you’ll be able to install it with:
M-x package-install RET grove RET
Or with use-package:
(use-package grove
:ensure t
:custom
(grove-directory "~/notes"))
In the meantime, you can install it manually by cloning the repo:
git clone https://github.com/jonathanchu/grove.git
(use-package grove
:load-path "path/to/grove"
:custom
(grove-directory "~/notes"))
The entry point is C-c v v to open the Grove workspace, or M-x grove-open. From there, the full keybinding set lives under the C-c v prefix:
grove
├── C-c v v Open workspace
├── C-c v q Close workspace
├── C-c v c Quick capture
├── C-c v f Find note
├── C-c v s Search notes
├── C-c v d Daily note (today)
├── C-c v y Daily note (yesterday)
├── C-c v t Daily note (tomorrow)
├── C-c v b Show backlinks
├── C-c v # Search by tag
├── C-c v i Inbox review
├── C-c v l Insert wikilink
└── C-c v g Graph view
The file tree sidebar tracks your current file, and you can expand/collapse directories with TAB. Quick capture (C-c v c) opens a buffer where you type your note - the first line becomes the filename and it’s saved directly to your inbox for later triage.
I have a few things I’d like to explore next – note templates, tag autocomplete, and some refinements to the graph view to make it interactive. These are definitely nice-to-haves, but I would only want more time to think about some of these more thoughtfully as complexity increases with features like interactive graph views. But the core is solid and I’ve been using it daily as my primary note-taking system, which has been the real test.
If you’ve been looking for a note-taking setup in Emacs that doesn’t require much configuration or revamping your notes workflows, give Grove a try! Feedback and contributions are always welcome.
-1:-- Introducing grove.el (Post Jonathan Chu)--L0--C0--2026-05-03T04:00:00.000Z
Philip Kaludercic wanted to continue the conversation from YE24: Sacha and Prot Talk Emacs - Newbies/Starter Kits. He's spent a lot of time thinking about this as one of the main contributors to newcomers-presets, so there'll probably be much to cover!
(America/Toronto -0400) = Thu May 14 1030H EDT / 0930H CDT / 0830H MDT / 0730H PDT / 1430H UTC / 1630H CEST / 1730H EEST / 2000H IST / 2230H +08 / 2330H JST
We'll probably talk about:
Related links:
You can e-mail me at sacha@sachachua.com.
-1:-- May 14: Sacha, Prot, and Philip Kaludercic Talk Emacs: Newcomer Experience (Post Sacha Chua)--L0--C0--2026-05-02T17:21:07.000Z
Sean Whitton writes to say that the Emacs development team is planning to start the Emac 31 release process next week. That means that they will cut the Emacs 31 branch and start the process of testing and refining it in preparation for the final Emacs 31 release.
I really like how the development time is handling releases lately. They plan on a major release about once a year and in between time issue updates to fix bugs or problems in the latest major release.
If you follow the Emacs Devel mailing list, you’d think that the developers’ full time job is Emacs and that they have no family. It’s incredible how much unpaid time these people devote to Emacs
for the benefit of us all. As I always say, if you find yourself in a bar with any of them, the drinks are on you. These guys really are heroes.
-1:-- The Start Of The Emacs 31 Release Process (Post Irreal)--L0--C0--2026-05-02T14:53:37.000Z
Jan G sent me a two-part comment.
I was under the impression that when using elpaca you needed to disable use-package, and that when using elpaca-use-package, you were redefining the macro. I’m not 100% sure about this, but the documentation has an example of use-package and how it actually expands to an elpaca command.
I wouldn't know. All I can say is that it would be nice if package managers that
hook into, or completely redefines use-package, would document if they deviate
from the behaviour of "vanilla use-package" in some way.
Given that, use-package’s documentation is always going to be a little off, since elpaca is doing everything async. The only way I’ve found to reliably manage some dependencies is to use the elpaca-after-init hook, so they don’t even try to run until elpaca is finished loading everything.
I'd say it sometimes seems like the documentation for use-package is a little
off for use-package itself 🙂
The README for Elpaca says that
Add configuration which relies on after-init-hook, emacs-startup-hook, etc to elpaca-after-init-hook so it runs after Elpaca has activated all queued packages.
but that seems like a very big hammer and as I understand it I'd have to move
the whole :init block for python-mode into the hook in that case. Playing
around with the various blocks for use-package isn't too time consuming and I
think it's a good first thing to try.
-1:-- Follow-up on switching to eglot (Post Magnus)--L0--C0--2026-05-02T11:20:00.000Z
I should have dealt with comments I got to my posts on how I deal with secrets in my work notes, here, and here. Better late than never though, I hope.
The first one is a link to post titled How I use :dbconnection in org files. It
describes a nice way of setting sql-connection-alist based on the contents of
a file, in his case ~/.pgppass.
The other starts with a function for searching ~/.authinfo.gpg for entries of
the form
machine <host>/<dbname> login <username> password <password> port <port>
and then setting sql-password-search-wallet-function and sql-password-wallet
to tell sql-mode to use it
(defun my/sql-auth-source-search-wallet (wallet product user server database port)
"Read auth source WALLET to locate the USER secret.
Sets `auth-sources' to WALLET and uses `auth-source-search' to locate the entry.
The DATABASE and SERVER are concatenated with a slash between them as the
host key."
(when-let (results (auth-source-search :host (concat server "/" database)
:user user
:port (number-to-string port)))
(when (and (= (length results) 1)
(plist-member (car results) :secret))
(plist-get (car results) :secret))))
(setq sql-password-search-wallet-function #'my/sql-auth-source-search-wallet)
(setq sql-password-wallet "~/.authinfo.gpg")
The value for sql-connection-alist is then as normal
(setq sql-connection-alist
'((some-dbname (sql-product 'oracle)
(sql-port 1521)
(sql-server ...)
...))
and the blocks in orgmode looks like this
SRC sql-mode :product oracle :dbconnection i3v1e-ro :results raw
SELECT to_char(sysdate, 'YYYY-MM-DD HH24:ii:ss') AS today,
to_char(sysdate + 1, 'YYYY-MM-DD HH24:ii:ss') AS tomorrow
FROM dual;
SRC
Both of these feel closer to the intent of sql-mode in a way. I'll have to try
using sql-connection-alist at some point.
-1:-- Secrets when connecting to DBs (Post Magnus)--L0--C0--2026-05-02T10:41:00.000Z
Raw link: https://www.youtube.com/watch?v=JG4R-d0N-is
In this short video I demonstrate my new package for Emacs. It is called buffer-to-pdf. The idea is to save your current buffer to a PDF, while preserving how it looks. This means that your font size, theme, and other visual effects are preserved and written to the PDF. buffer-to-pdf is not meant to be a replacement for elaborate export methods: consider it a quick yet effective way to get a “screen capture” of your Emacs that you can then share as a document. I believe this will be especially useful for academics or people who need to distribute presentation notes on a regular basis. The package is available here: https://github.com/protesilaos/buffer-to-pdf.
-1:-- Emacs: save any buffer as PDF (my new buffer-to-pdf package) (Post Protesilaos)--L0--C0--2026-05-02T00:00:00.000Z
Here are a couple of quickies. Neither one requires much exposition on my part but they are both interesting. In the first, Prot shares what he considers decent default settings for Emacs. Naturally, I don’t agree with all of them but they’re an excellent start for your init.el. For example, I’d be more likely to prefer Melpa over Gnu Elpa, and I prefer Swiper to Consult but that may be simply because I’m used to Swiper and it works well for me.
Most of the rest of his choices I agree with or at least am agnostic about. That’s the thing about Emacs, you get to choose what works best for you.
The second quickie is a post from Charles Choi that discusses bulk search and replace commands in Emacs. Choi begins with reviewing regular expression syntax. That’s important because some Emacs command use the builtin regexp syntax and others call various versions of grep, which, of course, have their own regexp syntax.
As usual with Choi’s posts there’s a lot there and it requires careful reading but it’s worthwhile. As Choi says, the Emacs bulk search and replace commands make possible workflows that would be harrowing in other editors but they’re also difficult to discover. His post is intended to remedy that.
-1:-- A Couple Of Emacs Quickies (Post Irreal)--L0--C0--2026-05-01T14:48:49.000Z
I previously wrote about useful Emacs commands for reading. This allowed me to use j and k to scroll the window up and down instead of going forward or backward a line.
I am now using meow for my modal editing needs and have been really happy with it. Meow allows for custom states to be defined, but I have been using a different method recently that takes advantage of the built-in normal and motion states.
Meow has a very clever design choice in that when a key is pressed it can translate it to the default emacs binding and call it via a macro. Below is an example of the function meow-next, which I have bound to j. It essentially just executes the key-binding that is stored as the value of meow--kbd-forward-line which happens to be C-n.
(defun meow-next (arg)
"Move to the next line.
Will cancel all other selection, except char selection.
Use with universal argument to move to the last line of buffer.
Use with numeric argument to move multiple lines at once."
(interactive "P")
(unless (equal (meow--selection-type) '(expand . char))
(meow--cancel-selection))
(cond
((meow--with-universal-argument-p arg)
(goto-char (point-max)))
(t
(setq this-command #'next-line)
(meow--execute-kbd-macro meow--kbd-forward-line))))
(defvar meow--kbd-forward-line "C-n"
"KBD macro for command `forward-line'.")
Because meow’s keyboard macro commands are all stored as variables, it is easy for us to overwrite them locally. In the following example I will show how I made a minor mode that lets me have a more enjoyable reading experience.
Firstly, we need to bind the new functions to some obscure key combination. I chose to add these to the global keymap in this case as I want them available across a variety of major-modes.
Then I wrote functions to toggle between the original values of the meow–kbd variables and their overrides.
Finally, I defined a minor mode that can be added to a major-mode’s hook.
(keymap-global-set "M-s-j" 'scroll-up-line)
(keymap-global-set "M-s-k" 'scroll-down-line)
(defvar meow-reading-originals
'((meow--kbd-backward-line . "C-p")
(meow--kbd-forward-line . "C-n")))
(defvar meow-reading-overwrites
'((meow--kbd-backward-line . "M-s-k")
(meow--kbd-forward-line . "M-s-j")))
(defun meow-reading-restore-directions ()
"Restore Meow's direction variables locally."
(dolist (binding meow-reading-originals)
(set (make-local-variable (car binding)) (cdr binding))))
(defun meow-reading-overwrite-directions ()
"Overwrite Meow's direction variables locally."
(dolist (binding meow-reading-overwrites)
(set (make-local-variable (car binding)) (cdr binding))))
(define-minor-mode meow-reading-mode
"Adjust some bindings to make `meow-normal-mode' a better experience for reading modes."
:lighter " reading"
(if meow-reading-mode
(progn
(meow-reading-overwrite-directions)
(setq-local meow-cursor-type-motion nil)
(meow--update-cursor-motion))
(progn (meow-reading-restore-directions)
(kill-local-variable meow-cursor-type-motion)
(meow--update-cursor-motion))))
Here is an example of how you can have the minor mode be loaded for all buffers of a given major mode.
(use-package elfeed
:hook
(elfeed-show-mode . meow-reading-mode))
The reason that I prefer this to making a whole new “reading-state” is that this is still using meow’s default motion-state. I get to take advantage of all of the default key-bindings. One of the reasons that I moved from evil to meow was that I was getting tired of having to bind so many functions myself. With this method, I can essentially say “I want this mode to behave the same as all of the others, just with one or two changes”.
I am also working on a minor mode for lisp modes that takes advantage of smartparens to hopefully create a lispy like environment, but that is still a work in progress.
-1:-- Overriding keybindings with Meow (Post Jiewawa)--L0--C0--2026-05-01T00:00:00.000Z
-1:-- Emacs Carnival: History and Thoughts on Starter Kits (Post Eric MacAdie)--L0--C0--2026-04-30T17:54:45.000Z
After reading the sad news that Chris Wellons is abandoning Emacs and the Emacs packages he developed one of my first concerns was for Elfeed. It’s the RSS reader that I depend on everyday for my research and news curation. Wellons will be missed for many reasons but his stewardship of Elfeed is the most important one to me.
I’m all but certain that Wellons will find good hands in which to entrust the future of Elfeed but as I learned in the Boy Scouts, it pays to be prepared. Serendipitously, I stumbled upon this post from Dave’s Blog that mentions he moved from Elfeed to Gnus. The post is about a solution he found for following links referred to in the RSS summary but I was more interested in his use of Gnus in place of Elfeed for RSS.
I’ve considered, off and on, moving to Gnus but I’m really happy with mu4e for email and elfeed for RSS and Network News is, sadly, no longer important so moving to Gnus didn’t make much sense to me. Now, unfortunately, I may have to think about it. Gnus is a powerful complicated program and it seems a shame to use it just for RSS but if worse comes to worst it’s nice to have a mature and reliable fallback available.
As I said, I’m pretty sure Elfeed won’t have any problems finding a new maintainer who will sustain its high quality but it’s nice to know that if I need it, there’s a viable, Emacs-based solution available.
-1:-- RSS With Gnus (Post Irreal)--L0--C0--2026-04-30T17:07:01.000Z
I have been doing a lot of fiddling with images lately, mostly through dired and image-dired, and one little thing has been bugging me for a while. When I open an image in Emacs, image-mode happily shows me the picture, but it never tells me the one bit of information I actually want to know, how big is the thing?, width, height, file size, that sort of thing. You can of course bounce out to a shell and run identify or file, but that feels silly when Emacs already has the image loaded.
So I thought, right, this should be a five minute job, just slap something into the header-line on image-mode-hook and be done with it. And it more or less was, although there was a small wrinkle along the way that is worth mentioning, because it caught me out.
Here is what ended up in my init.el:
;;
;; -> image-mode-dimensions
;;
(defun my/image-mode-show-dimensions ()
"Display the open image's pixel dimensions and file size in the header line."
(when (and (derived-mode-p 'image-mode)
buffer-file-name
(file-exists-p buffer-file-name))
(condition-case err
(let* ((image (or (image-get-display-property)
(create-image buffer-file-name)))
(size (image-size image t))
(width (car size))
(height (cdr size))
(bytes (file-attribute-size
(file-attributes buffer-file-name))))
(setq header-line-format
(format " %d x %d px %s"
width height
(file-size-human-readable bytes))))
(error
(setq header-line-format
(format " image dimensions unavailable: %S" err))))))
(add-hook 'image-mode-hook #'my/image-mode-show-dimensions)
(add-hook 'image-mode-new-window-functions
(lambda (&rest _) (my/image-mode-show-dimensions)))
A few notes on what is going on here. The or around image-get-display-property and create-image means we use the displayed image spec when it is there (cheaper, no extra file read), and fall back to building one from the file path when it is not. image-size with a non-nil second argument returns dimensions in actual pixels rather than canvas units, which is what I want. file-size-human-readable gives me a nice 2.4M rather than 2516582, because nobody reads bytes directly.
The condition-case is there because images can occasionally throw, especially when something has gone wrong with imagemagick or an unsupported format sneaks in, and I would rather see a polite header-line message than have the hook explode and pollute *Messages* every time I open a picture.
The second hook, image-mode-new-window-functions, is the one that handles the case where you flip between image and text view of the same buffer with C-c C-c, since the image gets re-displayed and the header-line needs to refresh too.
So now when I pop open an image, I get a nice little header-line that reads something like:
1920 x 1080 px 2.4M
A small thing, but the kind of small thing that makes Emacs feel like it fits a bit more snugly around how I actually work.
-1:-- A Tiny Header line Tweak: Image Dimensions in image mode (Post James Dyer)--L0--C0--2026-04-30T10:00:00.000Z
Emacs offers a dizzying number of commands to perform bulk operations on multiple files or buffers. These commands are quite capable and can make trivial the execution of workflows that would be heroic in other editors. Unfortunately these commands are also difficult to discover as a number of them are not featured in easily accessible menus.
This post calls attention to bulk commands related to search and replace in Emacs and how their discoverability can be improved using the Casual and Anju UI packages.
Before moving forward, let’s talk about how Emacs handles regular expression syntax in search and/or replace commands. Whenever using an Emacs command involving a regular expression (regexp), you will need to understand what kind of regexp syntax is expected. There are largely two to know:
Commands using grep-style regexps do so because they invoke the local install of the grep utility. The grep regex syntax is implementation dependent. If you use GNU grep, you can read its syntax here, which share some character classes with Emacs.
The Casual RE-Builder package is a great way to work with Emacs regexps as it provides a command to escape the regexp properly for interactive input. re-builder alone only provides a regexp that can be used in Elisp code.
The table below shows the different search and/or replace workflows and their associated commands.
| Workflows | Command | Regexp Type | Notes |
|---|---|---|---|
| Search regexp in files in directory | rgrep | grep | AKA “Find in Files.” Results can be edited using writeable grep (wgrep). |
| Search regexp in files in project | project-find-regexp | grep | |
| Search regexp in files in directory and present in Dired | find-grep-dired | grep | |
| Search regexp in tagged files | tags-search | Emacs | |
| Search file names matching shell pattern in directory and present in Dired | find-name-dired | shell | |
| Search file names matching regexp in directory and present in Dired | find-lisp-find-dired | Emacs | Implementation uses Emacs regexp type. |
| Search file names matching regexp in current directory and present in Dired | casual-dired-find-dired-regexp | Emacs | Wrapper around find-lisp-find-dired using current directory. Available via Casual. |
| Query replace regexp in project files | project-query-replace-regexp | Emacs | |
| Incremental search marked files with plain text | dired-do-isearch | For use in Dired. | |
| Incremental search marked files with regexp | dired-do-isearch-regexp | Emacs | For use in Dired. |
| Query replace regexp in marked files | dired-do-query-replace-regexp | Emacs | For use in Dired. |
| Search regexp in marked files | dired-do-find-regexp | grep | For use in Dired. |
| Search regexp in marked files and display first match | dired-do-search | Emacs | For use in Dired. |
| Replace regexp in marked files | dired-do-find-regexp-and-replace | grep | For use in Dired. |
| Replace regexp in marked files using diff interface. | dired-do-replace-regexp-as-diff | Emacs | For use in Dired. |
| Incremental search marked buffers with plain text | ibuffer-do-isearch | For use in IBuffer. | |
| Incremental search marked buffers with plain text with regexp | ibuffer-do-isearch-regexp | Emacs | For use in IBuffer. |
| View lines which match regexp in marked buffers | ibuffer-do-occur | Emacs | For use in IBuffer. |
| Query replace plain text in marked buffers | ibuffer-do-query-replace | For use in IBuffer. | |
| Query replace regexp in marked buffers | ibuffer-do-query-replace-regexp | Emacs | For use in IBuffer. |
| Run git grep, searching for regexp in directory. | vc-git-grep | grep | |
| Replace all references to identifier. | xref-find-references-and-replace | ||
| Interactively replace identifier in current xref buffer. | xref-query-replace-in-results | ||
| Rename symbol at point for project. | eglot-rename | Requires Eglot support. | |
| Replace regexp in files using diff interface. | multi-file-replace-regexp-as-diff | Emacs | |
| Start multi-buffer incremental search on a list of files. | multi-isearch-files | ||
| Start multi-buffer incremental regexp search on a list of files. | multi-isearch-files-regexp | Emacs | |
| Start multi-buffer incremental search on a list of buffers. | multi-isearch-buffers | ||
| Start multi-buffer incremental regexp search on a list of buffers. | multi-isearch-buffers-regexp | Emacs | |
| Show all lines in buffers containing a match for regexp. | multi-occur | Emacs | |
| Show all lines containing a match for regexp in buffers that match bufregexp. | multi-occur-in-matching-buffers | Emacs |
Choice of command depends on the quantity and specificity of files or buffers to work on. Both Dired and IBuffer marking allow for specific selection of files or buffers respectively.
Many of the commands in the table above are discoverable via menu using the Casual and Anju packages. Hierarchical menu categorization aids in the discovery and recognition of these commands, making them more usable.
| Command | UI | Notes |
|---|---|---|
| rgrep | (C-o) casual-editkit-main-tmenu › (/) Search/Replace › (g) Find in Files… | Available via Casual EditKit. |
| rgrep | (Menu-bar) Edit › Search › Search in Files… | Available via Anju. |
| project-find-regexp | (Menu-bar) Edit › Search › Search in Project Files… | |
| tags-search | (Menu-bar) Edit › Search › Search Tagged Files… | |
| project-query-replace-regexp | (Menu-bar) Edit › Replace › Replace in Project Files… | |
| find-name-dired | (C-o) casual-editkit-main-tmenu › (/) Search/Replace › (d) Files… | Available via Casual EditKit. |
| find-grep-dired | (C-o) casual-editkit-main-tmenu › (/) Search/Replace › (G) Files containing text… | Available via Casual EditKit. |
| casual-dired-find-dired-regexp | (C-o) casual-dired-tmenu › (f) Filter by name… | Available via Casual Dired. |
| dired-do-isearch | (C-o) casual-dired-tmenu › (/) Search/Replace › (C-s) I-search… | Available via Casual Dired. |
| dired-do-isearch-regexp | (C-o) casual-dired-tmenu › (/) Search/Replace › (M-s) I-search regexp… | Available via Casual Dired. |
| dired-do-query-replace-regexp | (C-o) casual-dired-tmenu › (/) Search/Replace › (r) Query regexp and replace… | Available via Casual Dired. |
| dired-do-find-regexp | (C-o) casual-dired-tmenu › (/) Search/Replace › (g) Find regex… | Available via Casual Dired. |
| dired-do-search | (C-o) casual-dired-tmenu › (/) Search/Replace › (s) Search first regexp match… | Available via Casual Dired. |
| dired-do-find-regexp-and-replace | (C-o) casual-dired-tmenu › (/) Search/Replace › (G) Find regex and replace… | Available via Casual Dired. |
| ibuffer-do-isearch | (C-o) casual-ibuffer-tmenu › (C-s) I-Search… | Available via Casual IBuffer. |
| ibuffer-do-isearch-regexp | (C-o) casual-ibuffer-tmenu › (C-M-s) I-Search Regexp… | Available via Casual IBuffer. |
| ibuffer-do-occur | (C-o) casual-ibuffer-tmenu › (O) Occur… | Available via Casual IBuffer. |
| ibuffer-do-query-replace | (C-o) casual-ibuffer-tmenu › (M-r) Query Replace… | Available via Casual IBuffer. |
| ibuffer-do-query-replace-regexp | (C-o) casual-ibuffer-tmenu › (C-M-r) Query Replace Regexp… | Available via Casual IBuffer. |
| vc-git-grep | (Menu-bar) Tools › Version Control > Git grep… |
The replace commands can do catastrophic damage if not used with caution. Treat them like power tools.
Some guidance before using replace commands:
Have a backup plan in case you need to recover anything.
Use re-builder to help figure out the right regexp.
Know the scope of what you want to change (directory, files, buffers).
Some commands will only modify the buffer of an affected file. Check if modified buffers are saved. You can use IBuffer to identify and save such buffers. It is left as an exercise to the reader to determine which commands exhibit this behavior.
The inventory of commands above are from what I know of Emacs, which is guaranteed to not be comprehensive. If there are others missing from this list, please let me know at kickingvegas@gmail.com.
While many of these commands have been in Emacs for years (decades even), they were not usable to me until I built a UI for them. I think motivated readers using Casual and Anju for bulk search and/or replace tasks will find a similar sentiment.
Amended 2026-04-30: Added vc-git-grep, eglot-rename, xref-find-references-and-replace, and xref-query-replace-in-results. Thanks to Henry Leach and Gene Pasquet for their input!
Amended 2026-05-04: Added dired-do-replace-regexp-as-diff, multi-file-replace-regexp-as-diff, multi-isearch-files, multi-isearch-files-regexp, multi-isearch-buffers, multi-isearch-buffers-regexp, multi-occur, multi-occur-in-matching-buffers. Learned about the diff commands from Christian Tietze's post Preview Mass Text Replacements with Emacs 30.1 replace-regexp-as-diff.
-1:-- Bulk Search & Replace Commands for Files and Buffers in Emacs (Post Charles Choi)--L0--C0--2026-04-30T05:15:00.000Z
These are the basic settings for Emacs that I shared with Sacha Chua during our livestreamed meeting on 2026-04-30: https://www.youtube.com/watch?v=z7pcLdwuyxE.
UPDATE 2026-05-01 08:24 +0300: Added a missing :config to the
bookmark block.
UPDATE 2026-05-02 22:33 +0300: Replaced duplicate variable-pitch
with the intended fixed-pitch.
;;; Sensible defaults that are not too intrusive and focus on common use-cases. By Protesilaos on 2026-04-30.
;; These are not all of my favourite options. I am not even including
;; any of my packages. They are just some basics that I consider
;; useful, given what I have learnt from my exchange with other people
;; of all skill levels.
;; Persist all customisations in a separate file called "custom.el".
;; It is in the same directory as the "init.el".
;;
;; Without the `custom-file', Emacs writes directly to the "init.el",
;; which can be confusing.
(setq custom-file (locate-user-emacs-file "custom.el"))
(load custom-file :no-error-if-file-is-missing)
(use-package package
:ensure nil
:config
;; I am not using `add-to-list' here because the default "gnu" is
;; confusing to people, given that "elpa" is the better known name
;; for it.
(setq package-archives
'(("gnu-elpa" . "https://elpa.gnu.org/packages/")
("nongnu" . "https://elpa.nongnu.org/nongnu/")
("melpa" . "https://melpa.org/packages/")))
;; Prefer GNU ELPA but accept the reality of MELPA's utility to the
;; wider community.
(setq package-archive-priorities
'(("gnu-elpa" . 3)
("nongnu" . 2)
("melpa" . 1))))
;;;; General options
(use-package emacs
:ensure nil
:demand t
:init
(defun prot/keyboard-quit-dwim ()
"Do-What-I-Mean behaviour for a general `keyboard-quit'.
The generic `keyboard-quit' does not do the expected thing when
the minibuffer is open. Whereas we want it to close the
minibuffer, even without explicitly focusing it.
The DWIM behaviour of this command is as follows:
- When the region is active, disable it.
- When a minibuffer is open, but not focused, close the minibuffer.
- When the Completions buffer is selected, close it.
- In every other case use the regular `keyboard-quit'."
(interactive)
(cond
((region-active-p)
(keyboard-quit))
((derived-mode-p 'completion-list-mode)
(delete-completion-window))
((> (minibuffer-depth) 0)
(abort-recursive-edit))
(t
(keyboard-quit))))
:bind
("C-g" . prot/keyboard-quit-dwim)
:config
;; Set your favourite font family and height here. The :height is
;; 10x the point size you most commonly find on other applications.
(set-face-attribute 'default nil :family "Aporetic Sans Mono" :height 160)
;; Set your favourite font for elements that are designed to always
;; be monospaced. The height SHOULD BE a floating point, which is
;; interpreted as relative to the `default'.
(set-face-attribute 'fixed-pitch nil :family "Aporetic Serif Mono" :height 1.0)
;; Same as above for proportionately spaced elements. Make any
;; buffer proportionately spaced by enabling the `variable-pitch-mode'.
;;
;; [ NOTE: If you use the Modus themes or derivatives, set
;; `modus-themes-mixed-fonts', load the theme for the option to
;; take effect, and then enable `variable-pitch-mode':
;; spacing-sensitive elements like Org tables and code blocks will
;; remain monospaced. ]
(set-face-attribute 'variable-pitch nil :family "Aporetic Sans" :height 1.0)
;; I have never seen a user say "no" to loading a theme they have
;; downloaded. Technically, any Elisp file can run arbitrary code,
;; so this is not doing much on the security front.
(setq custom-safe-themes t)
(setq use-short-answers t)
(setq read-answer-short t)
(setq help-window-select t) ; also check `display-buffer-alist' below
(setq help-window-keep-selected t) ; Emacs 29
(setq find-library-include-other-files nil) ; Emacs 29
(setq window-combination-resize t)
(setq save-interprogram-paste-before-kill t)
;; Do not jump to the current line in `*occur*' buffers. The reason
;; is that you are already on that line: you want to do `occur' to
;; get more than that (and, presumably, to do something with the
;; results such as to edit them with `occur-edit-mode').
(setq list-matching-lines-jump-to-current-line nil)
(setq completion-category-defaults nil))
;;;; Save minibuffer histories
(use-package savehist
:ensure nil
:config
(savehist-mode 1))
;;;; Delete the selected text when inserting new text
(use-package delsel
:ensure nil
:config
(delete-selection-mode 1))
;;;; Bookmarks
(use-package bookmark
:ensure nil
:config
;; Emacs 29 displays a bookmark icon on the fringe. Many people
;; have asked me what that thing is. I also think it is confusing.
(setq bookmark-fringe-mark nil)
;; Write changes to the bookmark file as soon as 1 modification is
;; made (addition or deletion). Otherwise Emacs will only save the
;; bookmarks when it closes, which may never happen properly
;; (e.g. power failure).
(setq bookmark-save-flag 1))
;;;; Dired
(use-package dired
:ensure nil
:config
;; Most people I have talked to prefer a single Dired buffer.
;; Personally I like the many Dired buffers, but I understand why
;; this feels overwhelming.
(setq dired-kill-when-opening-new-dired-buffer t)
(setq dired-auto-revert-buffer #'dired-directory-changed-p) ; also see `dired-do-revert-buffer'
(setq dired-clean-up-buffers-too t)
(setq dired-clean-confirm-killing-deleted-buffers t)
(setq dired-recursive-copies 'always)
(setq dired-recursive-deletes 'always)
(setq delete-by-moving-to-trash t)
(setq dired-create-destination-dirs 'ask)
(setq dired-create-destination-dirs-on-trailing-dirsep t) ; Emacs 29
(setq wdired-create-parent-directories t))
;;;; Isearch
(use-package isearch
:ensure nil
:config
;; ;; Enable those to make "package install" match those words with
;; ;; anything in between. I think this is the single best tweak I
;; ;; ever made.
;;
;; (setq search-whitespace-regexp ".*?")
;; (setq isearch-lax-whitespace t)
;; (setq isearch-regexp-lax-whitespace nil)
(setq isearch-lazy-count t)
(setq lazy-count-prefix-format "(%s/%s) ")
(setq lazy-count-suffix-format nil))
;;;; Diff
(use-package diff
:ensure
:config
;; You cannot expect the syntax highlighting of themes to look
;; equally readabable against what typically are red and green
;; backgrounds. This should be opt-in by default, not opt-out.
(setq diff-font-lock-syntax nil))
;;;; Ediff
(use-package ediff
:ensure nil
:config
;; Ediff is virtually unusable without those. Especially on tiling
;; window managers. But even on a regular desktop environment it is
;; confusing and cumbersome to have the control panel in another
;; frame.
(setq ediff-split-window-function 'split-window-horizontally)
(setq ediff-window-setup-function 'ediff-setup-windows-plain))
;;;; SHR
(use-package shr
:ensure nil
:config
;; t is bad for accessibility and generally awkward for HTML email
;; (especially with dark themes).
(setq shr-use-colors nil)
;; This option should not exist, given `variable-pitch-mode'.
;; Furthermore, its default value runs counter to almost everything
;; else in Emacs which just uses the `default' face.
(setq shr-use-fonts nil))
;;;; Control the display of common ancillary windows
;; Always focus common ancillary windows. Place them in a window
;; already occupied by their respective major mode or below the
;; current window.
(add-to-list 'display-buffer-alist
'((or . ((derived-mode . occur-mode)
(derived-mode . grep-mode)
(derived-mode . Buffer-menu-mode)
(derived-mode . log-view-mode)
(derived-mode . help-mode)))
(display-buffer-reuse-mode-window display-buffer-below-selected)
(body-function . select-window)))
(add-to-list 'display-buffer-alist
'("\\`\\*\\(Org \\(Select\\|Note\\)\\|Agenda Commands\\)\\*\\'" ; the `org-capture' key selection, `org-add-log-note', and agenda dispatcher
(display-buffer-in-side-window)
(dedicated . t)
(side . bottom)
(slot . 0)
(window-parameters . ((mode-line-format . none)))))
(add-to-list 'display-buffer-alist
'((derived-mode . calendar-mode)
(display-buffer-reuse-mode-window display-buffer-below-selected)
(mode . (calendar-mode bookmark-edit-annotation-mode ert-results-mode))
(inhibit-switch-frame . t)
(dedicated . t)
(window-height . fit-window-to-buffer)))
(add-to-list 'display-buffer-alist
'((derived-mode . reb-mode) ; M-x re-builder
(display-buffer-reuse-mode-window display-buffer-below-selected)
(inhibit-switch-frame . t)
(window-height . 4) ; note this is literal lines, not relative
(dedicated . t)
(preserve-size . (t . t))))
;;;; ESSENTIAL packages to install
(use-package vertico
:ensure t
:config
(vertico-mode 1))
(use-package marginalia
:ensure t
:config
(marginalia-mode 1))
;;;; VERY USEFUL but not essential packages
(use-package orderless
:ensure t
:config
(setq completion-styles '(orderless basic)))
(use-package consult
:ensure t
;; All commands have their utility, but those are commonly needed.
:commands (consult-buffer consult-line consult-outline consult-find consult-grep))
(use-package embark
:ensure t
:bind
;; Embark is helpful in every context, though there are other ways
;; to do what it does. Where it stands out is in its ability to
;; deal with all the minibuffer results. The equivalent of those
;; two commands should be a core Emacs functionality.
( :map minibuffer-local-map
("C-c C-c" . embark-collect)
("C-c C-e" . embark-export))
:config
;; Needed for correct exporting while using Embark with Consult commands.
(use-package embark-consult
:ensure t
:after consult))
;; Useful when combined with `delete-by-moving-to-trash'.
(use-package trashed
:ensure t)
-1:-- Emacs: decent defaults I shared with Sacha Chua (Post Protesilaos)--L0--C0--2026-04-30T00:00:00.000Z
I’ve been reading RSS and Atom feeds in Gnus for a few weeks, having moved over from elfeed. IIRC in elfeed it was pretty easy to visit the URL that an entry summarized. I’ve been searching for a while to do the same in Gnus, without much luck.
But today I finally hit C-h b while in the Gnus summary buffer, and
finally noticed w bound to
gnus-summary-browse-url. Aha! This function will “Scan
the current article body for links, and offer to browse them.” For
many articles, this will get me the one and only link, to the
article. For some of the articles, this finds several URLs, so I just
have to try to pick the right one. For that, I note
If only one link is found, browse that directly, otherwise use completion to select a link. The first link marked in the article text with ‘gnus-collect-urls-primary-text’ is the default.
And what is gnus-collect-urls-primary-text? It’s “The
button text for the default link in ‘gnus-summary-browse-url’” and its
value is “Link”. Exactly what I’m usually seeking!
This is an example of Emacs being self-documenting.
-1:-- Browsing URLs from Gnus Summary buffer (Post Dave's blog)--L0--C0--2026-04-29T00:00:00.000Z
For a while now, the python shell in Python mode in Emacs has not worked properly on my work laptop. I get some strange glyphs in the top of the python shell buffer when opening it from a file with C-c C-p and when I tried importing a file with C-c C-c, I would get an error saying stringp was nil and every character in what I tried to import was written first once, then together with the next, then the next three and so on. It looked somewhat psychedelic and was more or less unusable.
I also had trouble evaluating python code blocks in org mode which has been annoying when presenting with inter-present-mode for my students or exporting from org files I used for presentations to PDF or docx to upload to our school's learning platform (it's learning). In org, I would get the same error saying stringp was nil when evaluating code blocks that I would get when trying to import files to the REPL in python mode.
I first thought the problem was related to my einar-python-virtualenv function which locally changes the python-shell-interpreter for a file if it is in a project with a virtual environment since I made that quite recently, but the strange thing was that it worked perfectly on GNU Guix on my main machine at home. I then thought maybe it was a Windows 11 problem since I only experienced it at work, so I tried on a Raspberry Pi 4 at work with the latest Raspberry Pi OS and I had the same problem.
I then tried launching Emacs with -q to see if the problem was related to my config or not. When I then launched the python shell from a file with C-c C-p, the REPL itself worked slightly better, but I still got some strange glyphs at the top. I then spent some time trying to figure out where in my config the problem appeared and removed first the einar-python-virtualenv and then my configuration for python-mode, but the problem persisted. I also looked into whether some setting for comint-mode might cause the problem.
After spending one and a half hour trying to troubleshoot this on Monday, I today realised I updated Python to 3.14 on my work Windows 11 laptop a while ago. I checked the python version on the Raspberry Pi and it was 3.13. I checked packages.guix.gnu.org and Guix uses version 3.11. I thought maybe something changed in one of the newer versions. I had a look at news for version 3.14 and did not find anything promising. I then checked out what was new in 3.13 and one of the first things was a new and improved python shell.
Luckily, you can get the old shell that python mode in Emacs works with by setting the environment variable PYTHON_BASIC_REPL to something. When I added this function call to my Emacs config for python mode, the python REPL works in python mode again and it is possible to evaluate org code blocks and export files that will evaluate them on export again:
(setenv "PYTHON_BASIC_REPL" "1")
I write this so others experiencing the same problem can find a solution. In the long term, python-mode, python-ts-mode and org mode needs to work with the new and improved python shell since the old shell will probably be removed at some point in the future, but for now, just setting the environment variable is enough to get both the REPL and org code blocks working again.
-1:-- Fix Emacs python-mode REPL and org code block with python evaluation problems (Post Einar Mostad)--L0--C0--2026-04-28T18:55: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!