Irreal: Query: Emacs on the M1

It’s time for me to upgrade my MacBook Pro. I don’t usually upgrade this soon but my current laptop has the horrible butterfly keyboard and there are flickering problems both with Emacs and other apps.

The new hotness, of course, are the M1-based MacBooks, which run faster and cooler than the Intel versions. My one hard requirement is that it run Emacs; it’s a deal breaker if Emacs doesn’t run without (M1-based) problems. This site indicates that Emacs does run on the M1 but the MacBook Pro is a significant investment that would be effectively useless to me if there are problems running Emacs.

So I’m asking the knowledgeable Irreal cohort for advice.

  1. Are any of you running Emacs on the M1?
  2. If so, are you running in native mode or emulation?
  3. Are there any performance or other problems?
  4. What version of Emacs are you using?

If you have any wisdom on Emacs and the M1, please leave a comment. I’d be very grateful.

-1:-- Query: Emacs on the M1 (Post jcs)--L0--C0--March 08, 2021 08:03 PM

Sacha Chua: 2021-03-08 Emacs news

Links from, r/orgmode, r/spacemacs, r/planetemacs, Hacker News,, YouTube, the Emacs NEWS file and emacs-devel.

-1:-- 2021-03-08 Emacs news (Post Sacha Chua)--L0--C0--March 08, 2021 03:44 PM

Manuel Uberti: Quick starting is a bendy road

After more than a year with straight as my package manager, recently I have decided to sit down and look closely at how I handle my Emacs packages.

For all the interesting design choices and splendid documentation straight offers, I have never used neither its version freezing capabilities nor the chances to edit the source code of a package to try possible fixes before sending patches upstream. Two reasons, mainly:

  • I update my packages on a daily basis, accepting the risk of breakages in order to signal them to the maintainers and offer some help;
  • when I want to send a patch, I have the source code of the package I am working on outside of my Emacs configuration to avoid leaving something messy around.

These are not issues with straight, of course. It all depends on what one needs from their package manager.

One of the major benefits that straight brought to my setup is a boost in startup speed. However, why don’t give package-quickstart a try? Setting package-quickstart to t instructs package.el to pre-compute an autoload file so that the activation of packages can be done much faster, resulting in a faster startup1. And indeed it does, resulting in more or less the same 0.4 seconds that I was getting with straight.

One thing to be aware of is that, as the documention of package-quickstart suggests, “the use of ‘package-quickstart-refresh’ every time the activation need to be changed, such as when ‘package-load-list’ is modified” is required. Hence, I added an :after-while advice to package-menu-execute (bound to x in Package Menu) to make sure package-quickstart-refresh is run after every upgrade.

Again, mine is not an argument against straight. It’s still a great package manager and a fantastic alternative to the built-in package.el. However, these days my Emacs interactions do not need the fine-grained control straight provides.


  1. See the relevant commit

-1:-- Quick starting is a bendy road (Post)--L0--C0--March 08, 2021 12:00 AM

Cyberthal: Textmind case study | fixing a technical problem that has exploding dependencies | '3dashboard heading stack

My '3dashboard "Emacs hacking" task heading just exploded into a seven-link executive dependency chain.

I wanted to test my fix for a treefactor-up bug. But Chemacs launched my Emacs dev instance in Terminal instead of GUI. I investigated and found I also need to upgrade to Chemacs 2. Leery of doing so on my production user account, I decided to update my long-outdated fallback user account. This spawned a whole new chain of troubleshooting steps, including a mysterious magit bug. Currently I'm adding the fallback account's SSH key to my private server, so that I can update my Bash aliases, so that I can check whether the magit error occurs on vanilla Spacemacs.

Whenever a new dependency arises, I simply append it to the subheading list. Meanwhile captures the actual sequence of thought and action.

This smooth calm resolution of complex "exploding" technical problems used to cause me great frustration. Now it's simply automatic. I couldn't even remember what I was originally trying to do until I decided to amuse myself by writing this retrospective. '3dashboard lets me focus entirely on the current subtask, vastly reducing the difficulty of the problem.

Here's the '3dashboard heading. It doesn't include many completed steps, which I delete from '3dashboard unless they provide useful context:

 **** Emacs hacking

 ***** add imac@fallback ssh key to

 ***** VC chemacs dotfile

load it onto imac@fallback

 ***** troubleshoot imac@fallback spacemacs

run vanilla spacemacs via chemacs and test whether magit still broken

 ***** upgrade to chemacs 2

try upgrading on imac@Textmind fallback

 ***** troubleshoot chemacs non-GUI launch
 ***** fix treefactor-up elisp COUNT arg bug

 ****** test it

start my dev Emacs instance.

 ***** [[id:6587FC1B-B3CE-4F51-9A59-C61F3750EA17][fix treefactor bug outside spacemacs, with test suite]]

[contents truncated]

The last heading was originally the parent. I kept appending dependencies atop it. When that got messy, I subordinated them all under a new "Emacs hacking" heading.

This method works because I'm not concerned about representing every nuance in '3dashboard. Asides, digressions, doubts and details are captured in the ramblog. I trust the ramblog processing loop will handle them appropriately, leaving me free to pursue maximum yield from my current ramble.

-1:-- Textmind case study | fixing a technical problem that has exploding dependencies | '3dashboard heading stack (Post Cyberthal)--L0--C0--March 07, 2021 06:51 AM

Christian Tietze: Change Case of Word at Point in Emacs, But for Real This Time

At the moment, I’m proof-reading and editing the book manuscript of my pal Sascha for the new edition of the Zettelkasten Method book. As with most things text these days, I’m doing that with Emacs.

Something that continually drives me bonkers is how Emacs handles upcasing, downcasing, and capitalization of words by default. The functions that are called for the default key bindings are upcase-word, downcase-word, and capitalize-word. These sounds super useful to fix typos. The default behavior is odd, though: They only change the case of the whole word when you select the word first. Otherwise they change the case of the remainder of the word beginning at the character at the insertion point. The docstrings say as much: “Capitalize from point to the end of word, moving over.” Why?

Anything before the insertion point is ignored; and when capitalizing, only 1 character is actually changed.

So the functions are aware of my intention to change the word. Why don’t they start at its beginning?

I can understand the underlying functions involved here that act on the region aka selection of the user. They usually expect 2 parameters, the start and end of the region where the effect should be applied. That’s super useful to compose effects with other functions because of its general nature.

The “convenient” behavior of the key-bound functions to change the case for the remainder of the word puzzles me, though. Is it because you can pass numerical parameters to it to continue from point onward N words forward or backward? I dont’ know. Even then, why not start at the beginning while we’re at it? I would understand not acting on words at all without a selection, and just changing the case of character at the insertion point’s location then. But this?!

Xah Lee, who seemingly has done every conceivable thing you can do to Emacs in the past 20 years, implemented his own ‘toggle letter case’ function that does what maybe not every Emacs Lisp programmer, but any writer would expect: to act on the whole word.

He opted to figure out word boundaries via the [:alpha:] regular expression. That’s maybe not always enough, but it’s good enough for typing text. And, unless “thing at point”, it is consistent. Every mode can redefine what a “word” means in its context. (Which is useful on its own, but not helping to keep downcasing predictable.)

I changed Xah’s code a bit, because I don’t want to cycle through cases interactively. I’d rather hit M-u for ALL CAPS upcasing once.

Imagine a helper function ct/word-boundary-at-point-or-region that returns 2 character locations: the start and end of either the current region (i.e. selection in emacs) or the word below the insertion point.

The return value could be (100 110) for a 10 character word that starts at offset 100. The position of the insertion point notably doesn’t matter.

You can upcase a word like this, using car to get the first element of the returned list value, and cadr (aka (car (cdr x)))) to get the last element.1

Here’s a function that would utilize this to fetch both points and then capitalize the region:

(defun ct/capitalize-word-at-point ()
  (let* (($bounds (ct/word-boundary-at-point-or-region))
         ($p1 (car $bounds))
         ($p2 (cadr $bounds)))
    (upcase-initials-region $p1 $p2)))

I’d have to copy and paste that for all three case-changing functions I need. I’d rather extract the common theme here and change the approach to an adapter of sorts, if you pardon the OOP terminology when using Lisp.

The actual implementation of ct/word-boundary-at-point-or-region thus is implemented in a way to figure out the start and end points of a word, return these, but then also forward these to a callback, if that is provided.

Here’s the implementation, mostly copies from Xah’s excellent code:

(defun ct/word-boundary-at-point-or-region (&optional callback)
  "Return the boundary (beginning and end) of the word at point, or region, if any.
  Forwards the points to CALLBACK as (CALLBACK p1 p2), if present.

  (let ((deactivate-mark nil)
        $p1 $p2)
    (if (use-region-p)
        (setq $p1 (region-beginning)
              $p2 (region-end))
        (skip-chars-backward "[:alpha:]")
        (setq $p1 (point))
        (skip-chars-forward "[:alpha:]")
        (setq $p2 (point))))
    (when callback
      (funcall callback $p1 $p2))
    (list $p1 $p2)))

Let me walk you through the parts here in case Lisp is odd for you to read:

  • When a region is active, use the region beginning and end points for $p1 and $p2.
  • When no region is active, move the insertion point to the beginning of the word, save that as $p1, skip to the end of the word, save that offset as $p2. (And restore the original position thanks to the save-excursion decorator.)
  • If a callback function is given, pass the two points.
  • Always return a tuple of points via (list $p1 $p2).

Now I can get the tuple of points if I need, or I can tell the function to call another function and forward these points.

The implementation thus shrinks down to one-liners:

(defun ct/capitalize-word-at-point ()
  (ct/word-boundary-at-point-or-region #'upcase-initials-region))
(defun ct/downcase-word-at-point ()
  (ct/word-boundary-at-point-or-region #'downcase-region))
(defun ct/upcase-word-at-point ()
  (ct/word-boundary-at-point-or-region #'upcase-region))

;; Set global shortcuts
(global-set-key (kbd "M-c") #'ct/capitalize-word-at-point)
(global-set-key (kbd "M-u") #'ct/upcase-word-at-point)
(global-set-key (kbd "M-d") #'ct/downcase-word-at-point)

I prefer these one-liners over repeatedly unpacking 2 points frm a tuple that was returned.

The actual capitalization should maybe be implemented a bit different, though: upcase-initials-region only changes the case of the initials and leaves the remainder untouched, unlike capitalize-word which lowercases the rest. "fizzBUZZ" thus becomes "FizzBUZZ". My expectation is for the whole word to change, not just the initial characters, so I prefer to downcase the whole word first and then capitalize the initials for my current task:

(defun ct/capitalize-region (p1 p2)
  (downcase-region p1 p2)
  (upcase-initials-region p1 p2))
(defun ct/capitalize-word-at-point ()
  (ct/word-boundary-at-point-or-region #'ct/capitalize-region))

I have to say I really like function composition.

By the way, I also evaluated to train myself to expand the selection to the current word first and then call the built-in case changing functions. There’s tools for that. But that sucks, and the default behavior of the built-in functions still is odd.

  1. If you’re new to Lisp, using only cdr is like a dropFirst call on an array, still returning a list, but with 1 element in this case. car then fetches this element. And cadr is a shorthand for this common combination to fetch the butt of a list, so to speak. 

Receive Christian’s new posts via email

-1:-- Change Case of Word at Point in Emacs, But for Real This Time (Post)--L0--C0--March 06, 2021 08:07 AM

Hristos N. Triantafillou: My Custom Emacs Setup

It seems to be widely accepted that creating a powerful, useful Emacs setup "by hand" is just too much trouble, and you should choose a "distro" like Doom Emacs. But is it really all so bad? If you go the route of "hand-made", will you suffer through endless nights of fixing your setup? The answer is: probably not, but read on for more details!
-1:-- My Custom Emacs Setup (Post)--L0--C0--March 06, 2021 12:00 AM

Andrea: Dignity, or why people are not goods

Art and dignity to find ourselves
-1:-- Dignity, or why people are not goods (Post)--L0--C0--March 06, 2021 12:00 AM

Irreal: Red Meat Friday: Offend a Programmer

How to offend a programmer with a survey:

You gotta admit: It is offensive. The proper survey would have been

  • Emacs
  • Vim
  • VSCode, Atom, Sublime, or other bling-centric editor
  • Eclipse, IntelliJ, or other pushbutton app generator
  • Nano, Notepad, or other toy editor
-1:-- Red Meat Friday: Offend a Programmer (Post jcs)--L0--C0--March 05, 2021 06:20 PM

Andrea: Emacs as your code-compass: what files do I need to change next?

-1:-- Emacs as your code-compass: what files do I need to change next? (Post)--L0--C0--March 05, 2021 12:00 AM

Protesilaos Stavrou: Modus themes 1.2.0 for GNU Emacs

Just published version 1.2.0 of the Modus themes. The detailed release notes are reproduced below. For any questions pertaining to this publication feel welcome to contact me.

My immediate task now is to prepare patches for upstream Emacs so that the modus-operandi-theme and modus-vivendi-theme can be updated from version 0.13.0 to the current one.

Modus themes version 1.2.0

By Protesilaos Stavrou <> on 2021-03-04

This entry records the changes introduced to the project since the
publication of version 1.1.0 (2021-01-24).  There have been close to 100
commits in the meantime.

Every colour-related modification documented herein conforms with the
overarching accessibility objective of the themes for a minimum contrast
ratio of 7:1 between background and foreground values in their given
combination (the WCAG AAA standard).

As the official manual is referenced several times throughout this log,
make sure to store its URL: <>.  Or
read it from Emacs' Info reader by evaluating this form:

    (info "(modus-themes) Top")

If you are coming from older versions, please consult the change log
entry for version 1.0.0 with regard to the breaking changes that were

Prior notice: Upgrading the themes in Emacs28 and GNU ELPA

Emacs28, the current development target, now includes a 'require-theme'
function.  It is a prerequisite to upgrading the Modus themes to their
current version.  Prior to the definition of that function, the themes
could not transition from their 0.13.0 version to >=1.0.0.  Special
thanks to Basil L. Contovounesios for making it happen, as well Mauro
Aranda and Eli Zaretskii for their feedback and support.

Expect the Modus themes in upstream Emacs to be updated shortly after
the publication of this document.

GNU ELPA currently ships version 0.12.0 of the two standalone packages
'modus-operandi-theme' and 'modus-vivendi-theme'.  This will change in
the immediate future, as a new 'modus-themes' package will succeed them.
That new package will be built directly from emacs.git, as it must now
become a ':core' entity instead of being listed as an ':external' one.

Again, expect a patch to be applied to elpa.git shortly after this
document goes live.

Customisation options

[ All variables and their values are documented in the themes' manual.
  The default value is always nil. ]

+ The new boolean 'modus-themes-subtle-line-numbers' variable will make
  the effect of 'display-line-numbers-mode' more subtle when set to a
  non-nil value.  It removes the underlying background of the unfocused
  lines while toning down their foreground.

+ The 'modus-themes-diffs' variable now accepts a 'deuteranopia' value.
  This optimises for red-green colour deficiency in all modes that show
  diffs (diff-mode, ediff, Magit...).  In practice, all instances of
  green are replaced with appropriate blue hues.  For more on the
  matter, read the report which also includes pictures:

+ The 'modus-themes-syntax' variable now reads 'faint-yellow-comments'
  as a valid value.  This has the same scope as the existing 'faint'
  value with the added effect of assigning a yellow tint to comments: it
  tones down the saturation of colours that apply to code syntax
  (standard font-lock faces and others inheriting from them).

+ The 'modus-themes-links' variable is expanded to accept the new value
  of 'neutral-underline-only': it removes the foreground from the link
  and draws a neutral gray underline below it.

Refinements to existing packages or face groups

+ Refashioned all faces that pertain to emails, including Gnus, Mu4e,
  Notmuch, and the standard 'message.el' library.  This concerns the
  colours that apply to the message header keys and their values, as
  well as quote levels.

  - Introduced more contrasting hues for headings and made more
    considerate use of bold typography.  The new colour combinations are
    better suited for the task of delivering a sense of structure;
    structure that is at once effective and subtle.

  - Applied less intense colours throughout all quotation levels.

  - Revised the sequencing of hues in quotation levels to allow distinct
    levels to stand out more without relying on excessive saturation.

  - Aligned the styling of Notmuch header dates with their counterparts
    in other similar contexts, in pursuit of theme-wide consistency.

+ Rewrote the faces of EBDB to achieve a better sense of structure.

+ Refined the colour combinations of change-log and log-view buffers to
  make it easier to discern distinct elements.

+ Tweaked the colours of certain Elfeed constructs to improve the
  overall presentation of its search buffers.

+ Changed the colour combinations of 'M-x re-builder' to amplify the
  distinction between the matching regexp groups while still reducing
  their overall intensity.

+ Reconfigured the 'diff-changed' face to always extend its background
  to the edge of the window.  Such "changed" lines are visible in
  'diff-mode' buffers when the command 'diff-unified->context' is

+ Tweaked the colour combinations of ancillary faces in diff buffers
  when the variable 'modus-themes-diffs' is set to the value 'fg-only'.
  In particular:

  - Removed the subtle background from the diff hunk headings and changed
    their colour to ensure good visibility---guarantees a sense of

  - Made the context lines inherit the default foreground colour (pure
    black/white), so that it contrasts better with red, green, and
    yellow text.

  - Applied an accented foreground to the diff header.  This is to
    ensure that it is not mistaken for a diff hunk's context.

  All these guarantee that the foreground-only highlights in line-wise
  differences draw more attention to themselves.

+ Aligned all the standard hi-* faces with their default aesthetics.
  Those are used by commands such as 'highlight-symbol-at-point'.
  Thanks to Philip K. for the valuable feedback in issue 157:

+ Removed obsolete Consult faces and added new ones, so as to remain in
  sync with the latest developments in that project.  Thanks to Daniel
  Mendler (Consult's maintainer) for reporting the inconsistency in
  issue 155: <>.

  - 'consult-preview-line' now retains fontification on the current
    line, instead of applying its own foreground.

  - 'consult-narrow-indicator' is refashioned to be colour-coded in a
    consistent way with 'consult-async-split', as both denote the
    delineation of a given scope.

  - 'consult-imenu-prefix' contrasts better with text on its current
    line, while it adapts to possible customisations performed on the
    Consult front.

+ Expanded the coverage of 'marginalia' faces to two include
  'marginalia-char' and 'marginalia-type'.  This is done in the interest
  of internal consistency between the elements of this set, as their
  defaults were also accessible (they inherit from standard faces that
  we already support).

+ Opted to render the Notmuch logo in a neutral gray backdrop.  This was
  deemed necessary as the logo is an immutable image file that consists
  of black and white strokes.  Black and white are the main background
  values of 'modus-vivendi' and 'modus-operandi' respectively, which
  could lead to confusion.  The neutral gray ensures that the logo is
  visible at all times.  Thanks to Utkarsh Singh for the feedback in
  issue 122: <>.

+ Refined the dedicated colour values used for diff hunk headings, as
  seen in diff-mode buffers or Magit.  The new colours yield text that
  is easier to read by slightly toning down the combined intensity of

+ Removed the subtle background of 'diff-header' and 'diff-file-header'.
  The header's foreground and textual representation suffice to render
  it distinct in its context.

+ Tweaked 'org-agenda-structure' and 'org-scheduled' to enhance the
  usability of Org Agenda buffers.

  - Made 'org-agenda-structure' use the largest possible height that we
    expose to users: 'modus-themes-scale-5'.

  - Re-calibrated the hueness of 'org-scheduled' and amplified its
    saturation, in order to better convey the meaning of a scheduled

  Thanks to Morgan Smith for the valuable feedback in issue 153:

+ Tweaked the faces of the 'bongo' package to enhance the
  distinctiveness of the constructs they style.

+ Adjusted the overall aesthetic of calendar faces in the interest of
  theme-wide consistency.

+ Aligned the visual metaphors of 'org-code' with those of 'org-macro'
  and 'org-verbatim', by ensuring that a subtle background is present
  behind the affected text, while the foreground conforms with the norms
  of the 'modus-themes-no-mixed-fonts' customisation option.

+ Made quoted text in Info buffers look the same as 'org-verbatim' and
  Markdown's inline code.

+ Instructed the faces of 'info-colors' to inherit from appropriate
  font-lock faces.  This guarantees that everything works as intended
  with the various values of 'modus-themes-syntax'.

+ Refined the language tag of Markdown fenced blocks so that it does
  attract unwarranted attention while delivering on its intended

+ Rendered explicit the slant of ace-window hints, guaranteeing that it
  does not inherit from the underlying text.  Thanks to Nicolas De
  Jaeghere for the patch:
  [ Some more changes have been discussed, but those require tweaks to
    the upstream package. ]

+ Ensured that the 'org-tree-slide-header-overlay-face' never draws an
  overline when the variable 'modus-themes-headings' includes a relevant
  setting for heading level 1.  Such as with the following example (all
  customisation options are documented in the themes' manual):

    (setq modus-themes-headings
          '((1 . section)

+ Extended support for the new 'tab-line-tab-inactive-alternate' face as
  that occurs in Emacs28 (current development target).  It comes into
  effect when the variable 'tab-line-tab-face-functions' includes a
  value of 'tab-line-tab-face-inactive-alternating'.

Newly supported packages

+ bbdb :: Thanks to Nicolas De Jaeghere in issue 128:

+ mmm-mode :: Thanks to Davor Rotim for the feedback in issue 161:

+ quick-peek :: Thanks to Burgess Chang for the feedback in issue 151:

+ selectrum-prescient :: This new package was brought to my attention by
  Manuel Uberti.  The intent is to phase out the faces in Selectrum,
  namely 'selectrum-primary-highlight', 'selectrum-secondary-highlight',
  though those will still be supported by the Modus themes for the
  foreseeable future.

+ shortdoc

+ spray

+ terraform-mode :: Thanks to Kevin Fleming for the feedback in issue
  159: <>.

+ vc-dir (Emacs28)

Theme-related contributions to the wider community

+ Contributed the faces for 'vc-dir' in Emacs28 and applied them to all
  VC backends: <> and

+ Contributed a new face and some related tweaks to Emacs'
  'shortdoc.el': <>.

+ Added faces to the 'tab-bar-echo-area.el' package:

+ Reported issue that led to the review of the header face in
  'org-tree-slide': <>.

+ Helped refine the faces of the 'rlist.el' package:

Documentation updates

+ Wrote about the indirect support for the 'goggles' package.  I had
  helped write its faces, as was documented in the changelog for version
  1.1.0 of the themes.  Thanks to Manuel Uberti for bringing this to my
  attention in issue 158:

+ Explained that any changes to 'custom-theme-load-path' and/or
  'custom-theme-directory' should be performed before the themes are
  loaded.  Thanks to Adrian Manea for the feedback in issue 156:

+ Included the symbol 'bg-only' in the 'modus-themes-diffs' section of
  the manual.  Thanks to user "iSeeU" for reporting the omission:

+ Expanded the manual's entry on the semantics of the optional heading
  scale used by the themes (the variables 'modus-themes-scale-[1-5]').
  The values 1-4 apply to regular headings, with 4 being the largest on
  the scale.  While 'modus-themes-scale-5' is reserved for special
  headers, such as Org '#+title:' or the Org Agenda's structure.  Recall
  that those variables only come into effect if the boolean variable
  'modus-themes-scale-headings' is set to a non-nil value (it is nil by

+ Made several changes to the '' file in an effort to
  improve the accuracy of the generated Texinfo markup.  Thanks to Glenn
  Morris and Richard Stallman for their valuable feedback in

+ Recorded a note in the manual on the intended colouration of
  backgrounds applied by 'mmm-mode'.  It explains what the constraints
  are from an accessibility standpoint and how users can configure
  things locally for more colourful, yet inaccessible, backgrounds.
  Thanks to Davor Rotim for the valuable feedback in issue 161:

+ Refined the manual's note on prism.el, simplifying the code samples
  and clarifying the commentary.

+ Wrote indices for concepts, variables, functions, which are rendered
  in the Info manual.

+ Elaborated on the possibility---and relative merits---of implementing
  a theme-agnostic hook for advanced face configurations, as opposed to
  relying on 'modus-themes-after-load-theme-hook'.  Thanks to Daniel
  Mendler for the valuable feedback in issue 131:


+ Rewrote the documentation string of the 'deftheme' declaration of
  'modus-operandi' and 'modus-vivendi'.

+ Provided links to the Info nodes that discuss each of the 'defcustom'

+ Wrote doc strings for every custom face that the themes define.
-1:-- Modus themes 1.2.0 for GNU Emacs (Post)--L0--C0--March 04, 2021 12:00 AM

Protesilaos Stavrou: Use ‘M-x query-replace-regexp’ to downcase matches

Earlier today I wanted to convert a bunch of Org meta data keywords to lower case notation, with the help of isearch-forward-regexp and query-replace-regexp. This included everything from special comments, like #+TITLE: to property drawers in the form of :PROPERTIES:. There were 340 such cases in my file and I was reluctant to do so manually. Thankfully, Emacs makes such a task fairly simple once you get past the essentials, because it lets you evaluate arbitrary Elisp forms for the replacement text. This includes the possibility of running some function on a matched regexp group. In this case that function was (downcase OBJECT).

First I needed a regular expression that would capture all targets. isearch-forward-regexp and its query-replace-regexp counterpart expect a single backslash for the escape character, so I ended up with this pattern:

^\(#\|:\)[^ ].*?:

If I were to test this in the buffer, I could use M-x re-builder, which however requires double backslashes (same for when you write Elisp code):

^\\(#\\|:\\)[^ ].*?:
  • Once I was sure of the regular expression I had to use, I went to the top of the buffer and invoked isearch-forward-regexp (bound to C-M-s by default).

  • Entered the pattern ^\(#\|:\)[^ ].*?:, got live feedback of the matching items, and switched to query-replace with C-% (isearch-query-replace). When the Isearch is regexp-aware so is the corresponding query-replace.

  • For the replacement text I instructed the command to evaluate the downcase function. This is done by escaping the comma operator (,) and then supplying the function with a regexp group. Because I wished to match everything, the group should be \0. Which means that the replacement should be expressed thus: \,(downcase \0).

Try this with any string in a buffer, say, Hello:

  • M-x query-replace-regexp
  • Hello
  • \,(upcase \0)

Confirm the operation and you should get HELLO. This works with multiple groups and can read a series of Elisp forms. An example with Hello world:

  • M-x query-replace-regexp
  • \(Hello\) \(world\)
  • \,(downcase \1) \,(capitalize \2)

Which should give you hello World.

The elegant minimalism of the query-replace interface grants you the power to either replace each match one at a time or hit the exclamation mark (!) to answer “yes to all”. This is what I did to downcase all 340 matches. Voila! All of my Org file’s meta data were converted to lower case in one go.

Finally, I discovered query-replace-regexp-eval which saves you from adding the escaped comma operator for the replacement’s Elisp form. However its doc string reads thus:

Interactive use of this function is deprecated in favor of the
‘\,’ feature of ‘query-replace-regexp’.  For non-interactive use, a loop
using ‘search-forward-regexp’ and ‘replace-match’ is preferred.
-1:-- Use ‘M-x query-replace-regexp’ to downcase matches (Post)--L0--C0--March 03, 2021 12:00 AM

Irreal: How to Implement a Zettelkasten Link Type in Org

Christian Tietze is an author at the site and, of course, keeps his notes in a Zettelkasten. He has his own app, The Archive, for that but he’s also an Emacs user. He uses a timestamp as a key to his Zettelkasten notes and can access them from his browser with a URL of the form:


Being an Emacs user, Tietze wanted to be able to link to his notes through Org mode. To do that, he implemented a special Org-mode link type: zettel. Thus he can use links like



[[zettel:TIMESTAMP][Descriptive text]]

and clicking on one of them opens the relevant note in his browser.

It turns out to be pretty easy to set this up. Take a look at Tietze’s post for the details. Of course, his is a pretty specialized use case but the same simple procedure can be used to set up your own special links. The post is short and informative so it’s worth taking a look at it even if you don’t need a special link type right now.

-1:-- How to Implement a Zettelkasten Link Type in Org (Post jcs)--L0--C0--March 02, 2021 09:02 PM

Chen Bin (redguardtoo): Use Magit to commit efficiently and correctly

I prefer using git cli because it's more light weight.

Here is my bash alias of git commit,

alias gc="git commit -m"

The problem of my "cli-only" workflow is it can't detect my mistakes automatically.

I often forget to add new code file into git. So my final commit might miss files.

Magit UI solution

One solution is to use Magit to commit inside Emacs. After commit, I could double check the files inside the hooks provided by Magit.

My set up in Emacs,

(defun my-lines-from-command-output (command)
  "Return lines of COMMAND output."
  (let* ((output (string-trim (shell-command-to-string command)))
         (cands (nonempty-lines output)))
    (delq nil (delete-dups cands))))

(defun my-hint-untracked-files ()
  "If untracked files and commited files share same extension, warn users."
  (let* ((exts (mapcar 'file-name-extension (my-lines-from-command-output "git diff-tree --no-commit-id --name-only -r HEAD")))
         (untracked-files (my-lines-from-command-output "git --no-pager ls-files --others --exclude-standard"))
         (lookup-ext (make-hash-table :test #'equal))
    ;; file extensions of files in HEAD commit
    (dolist (ext exts)
      (puthash ext t lookup-ext))
    ;; If untracked file has same file extension as committed files
    ;; maybe they should be staged too?
    (dolist (file untracked-files)
      (when (gethash (file-name-extension file) lookup-ext)
        (push (file-name-nondirectory file) rlt)))
    (when rlt
      (message "Stage files? %s" (mapconcat 'identity rlt " ")))))

(with-eval-after-load 'magit
  (defun my-git-check-status ()
    "Check git repo status."
    ;; use timer here to wait magit cool down
    (run-with-idle-timer 1 nil #'my-hint-untracked-files))
  (add-hook 'magit-post-commit-hook #'my-git-check-status)
  (add-hook 'git-commit-post-finish-hook #'my-git-check-status))

Screenshot of step 1 in Emacs, magit-commit-step1.png

Screenshot of step 2 (final step) in Emacs (I was reminded of untracked files "bye.js" and "tree.js" at the bottom of UI), magit-commit-step2.png

BTW, my actual code in my .emacs.d is a bit different.

CLI solution but still using Magit

Another solution is still doing the git thing in shell but use the Magit plus Emacs "-batch" option.

Here is my bash setup,

function gc {
    # check my emacs.d exist
    if [ -f "$HOME/.emacs.d/" ] && [ "$PWD" != "$HOME/.emacs.d" ]; then
        # magit hook does not work
        emacs -batch -Q -l "$HOME/.emacs.d/init.el" --eval "(magit-commit-create '(\"-m\" \"$@\"))" --eval "(my-hint-untracked-files)"
        git commit -m "$@"

Screenshot in shell, magit-commit-in-shell.png

-1:-- Use Magit to commit efficiently and correctly (Post Chen Bin)--L0--C0--March 02, 2021 01:06 PM

Sacha Chua: 2021-03-01 Emacs news

Links from, r/orgmode, r/spacemacs, r/planetemacs, Hacker News,, YouTube, the Emacs NEWS file and emacs-devel.

-1:-- 2021-03-01 Emacs news (Post Sacha Chua)--L0--C0--March 01, 2021 02:24 PM

Andrea: Preview post: set your editing goals

-1:-- Preview post: set your editing goals (Post)--L0--C0--March 01, 2021 12:00 AM

Irreal: Emacs Writer

As most of you know, I’m very interested in the ways that non-technical people use Emacs and ways of making Emacs more accessible to such people. Ashton Wiersdorf is a technical user married to a non-technical writer looking for a better way to wrangle text. Being an Emacs user, Wiersdorf naturally thought of Emacs but worried that it was too intimidating for non-technical users so he built emacs-writer, simple configuration purpose-built for writers.

Wiersdorf makes a point of saying that this is still a work in progress and that you shouldn’t inflict it on a loved one unless you’re willing to provide technical support. Still, it seems like a nice project that can be easily adapted for individual needs.

I think this is a great project as long as its intended users understand that it’s a “starter kit.” I use Emacs for writing all the time and a lot of the features I use everyday are add-ons that users add as they become more experienced. If you plan on using emacs-writer forever, you’re missing the real power that Emacs has to offer. On the other hand, it makes a great configuration to start with and there’s not reason you can’t add to it as you become more experienced with Emacs.

In any event, it’s worth following this project if you have someone who could benefit from a real text editor. As Wiersdorf says at the top of the README,

“Writing should be all about the words. But word processors like Microsoft Word, Google Docs, or Apple’s Pages force you to think about formatting as you compose.”

-1:-- Emacs Writer (Post jcs)--L0--C0--February 28, 2021 10:40 PM

Amin Bandali: How I do my Computing

inspired by the computing page of rms


My librebooted ThinkPad X200 computer is the machine I use the most and where I do most of my computing. I also have the privilege of having access to a fleet of servers through our school's Computer Science Club that I use for some more computationally intensive tasks every now and again, and also for hosting this very website.

GNU/Linux distributions

I have used a wide variety of GNU/Linux distros over the years; but as of late, I find myself using Trisquel, Guix System, and Debian (with no contrib or non-free) almost exclusively. For the kernel, I mostly use GNU Linux-libre. Guix System comes with GNU Linux-libre out of the box, and on Debian-based distros I tend to install it from jxself's APT repository.

Actual computing

I spend most of my time in GNU Emacs.

TODO: elaborate

Maintaining this site

I took a great amount of inspiration from Phil Hagelberg's setup. The pages of this site are written in plain HTML using GNU Emacs, with GNU M4 acting as a full-featured template engine. A GNUmakefile provides convenient make rules to build and publish the site. The bibliography of my publications is generated from bandali.bib using bibtex2html, and further processed and put together using GNU sed and another GNUmakefile. The git repository containing all the sources used to build this site is available here.

-1:-- How I do my Computing (Post bandali)--L0--C0--February 28, 2021 12:00 PM

Marcin Borkowski: Visible bell in Emacs

Emacs has this habit of beeping when something goes wrong (or when the user presses C-g). Frankly, this is quite useful, since it is an instant feedback, but there are times when I don’t want that behavior.
-1:-- Visible bell in Emacs (Post)--L0--C0--February 27, 2021 09:44 AM

Tory Anderson: Best features for text-editing in emacs

There has been recent discussion about emacs for text editing and it got me thinking; I use emacs for a lot of non-code text editing and here are some features I use all the time that lead me to consider emacs good at text-editing. I’ll separate them into built-in and external library categories. What would you add to this list for things that help with raw text-editing (not IDE-like programming features)?
-1:-- Best features for text-editing in emacs (Post)--L0--C0--February 27, 2021 12:00 AM

jao: simplicity pays off

i've been using Bastian Bechtold's org-static-blog for this blog for more than a year now. Back in the day, i mentioned how well it integrated with my emacs workflow and how its simplicity was a big asset1.

During this year, i've contributed several little features to the package, and it's always been an easy and natural process. The last instance has been prompted by Sacha Chua asking me whether an emacs-specifc RSS feed was available, in order to add this blog to Planet Emacslife.

Turns out it wasn't available: org-static-blog did know how to use tags, but didn't generate per-tag RSS feeds. Until yesterday. It was a question of half an hour and a little PR to add that functionality. If you check the changeset, you'll see that most of its 62 additions and 24 deletions are just a bit of refactoring that make adding the feature almost trivial.

It was just another example of something i experience almost everyday in this Emacs life, namely, how easy and direct it is to mold the computer environment to fulfil new requirements, sometimes in idiosyncratic ways no external package is going to implement for you, and some other times (as in this case) in ways you can share with the community. The result is an environment almost exquisitely adapted to your needs, and it think that it is precisely this rooting in direct, day-to-day user needs that, at the same time, makes individual hacks so rich and useful to everyone else. That, and the fact that adapting an external package to your liking is so often just a couple lines of elisp away.

I hope i did it right, and you all Emacslife followers can see me waving hello, and this big thank you, Sacha! :)



Inevitably, i've been tweaking my configuration since then: you can see it, as a literate org file, in my emacs configuration repo here.

-1:-- simplicity pays off (Post)--L0--C0--February 26, 2021 02:29 AM

Protesilaos Stavrou: The Modus themes now cover deuteranopia in diffs

I just extended the modus-themes-diffs customisation option with the ability to read a deuteranopia value.

Deuteranopia describes insensitivity to the green channel of light. This includes the possibility of not distinguishing between red and green; the two colours that are typically codified in diff buffers as denoting “removed” and “added” states respectively.

Evaluating (setq modus-themes-diffs 'deuteranopia) and then re-loading the theme of choice will replace all instances of green in diff buffers with variants of blue. This affects the standard diff-mode, Ediff, Smerge, Magit, Vdiff, and any other library that inherits from those.

Below are illustrations of the phenomenon while using Magit diffs as an example with word-wise differences enabled (“refined” diffs). We try to simulate how deuteranopia is experienced. Those with it see red and green as variants of brown/yellow and interpret shades of magenta without its red channel’s intensity (magenta consists primarily of red and blue, so it looks closer to a desaturated blue).

Red VS Green (default)

Modus Operandi default

Modus Operandi default simulated

Modus Vivendi default

Modus Vivendi default simulated

Red VS Blue (‘deuteranopia’ option)

Modus Operandi deuteranopia

Modus Operandi deuteranopia simulated

Modus Vivendi deuteranopia

Modus Vivendi deuteranopia simulated

Accessibility broadly understood

While the Modus themes are not designed with the express goal of optimising for deuteranopia across all of Emacs’ interfaces, we can always make steps towards improving that experience. The fact that we already conform with the highest standard for colour contrast (WCAG AAA) puts us in a good position to expand our commitment to accessibility so that it accounts for variations in colour perception.

Designing for such cases is no mean feat. I had to take screenshots of all relevant configurations, display them in the GNU Image Manipulation Program, and set a filter that simulates deuteranopia vision: from GNU IMP’s “View” menu, search for “Display Filters” and then apply “Color Deficient Vision”. That had to be done tens of times during the testing process.

What inspired me to add support for (setq modus-themes-diffs 'deuteranopia) is the blog post of Sam Kleinman (aka “tycho garen”) on Editor Themes (2021-02-24), which echoes the relevant wishlist item on my project’s issue tracker (issue 118) where I got feedback from Hörmetjan Yiltiz.

Apart from its immediate utility, consider this new feature a statement of intent: I want to make the themes as accessible as possible and am willing to act on user feedback to that end.

If you believe something does not work properly while using either modus-operandi or modus-vivendi, please do not hesitate to bring the issue to my attention. Colour is a complex phenomenon: even when we formally conform with the lofty target of a minimum 7:1 contrast in relative luminance, we may still encounter cases where things do not “feel right”. We can always fix those outright or, where necessary, benefit from the power of Elisp to provide the relevant customisation options.

-1:-- The Modus themes now cover deuteranopia in diffs (Post)--L0--C0--February 25, 2021 12:00 AM

Irreal: Customizing the Agenda

If you’re an Org-mode user you’ve probably seen some of the custom Agenda displays that enterprising users have created. They can be useful for those who like to organize their activities and use the Agenda as a portal into that organization. Daniel Gopar gives us a pointer to how it’s done:

The link in the tweet takes you to the section of the Emacs manual that describes the default sorting of Agenda items. If you want to build a richer, customized display, you should check the section of the Org manual on Custom Agenda Views or you could take a look at Alphapapa’s org-super-agenda package.

-1:-- Customizing the Agenda (Post jcs)--L0--C0--February 24, 2021 06:49 PM

tycho garen: Editor Themes

It's not real secret that I'm red-green colorblind. It's not really a major life obstacle: I've got a wardrobe of clothes in colors that I can easily tell apart, I have developed a number of heuristics for guessing colors that are right enough, and mostly it just creates funny stories where I get a confused look if I try to describe something that might be purple, or have to convince a coworker into reading a graph for me.

One challenge historically, however, has been various kinds of text editing color themes: so often they end up having some kind of low contrast situation that's hard to read, or two different aspects of code that should be highlighted differently but aren't. I've tried lots of themes out, and I would always end up just going back and using default emacs themes, which might not have been great, but I always found it useable.

Until Protesilaos Stavrou's Modus Themes, that is.

These are super compelling and I never really knew how good an editor could look until I started using it. Like is this what it's really like for the rest of you all the time? Things are clear: I never get confused between type names and function names any more. There are rarely situations where I feel like the highlighting color and text color are the same, which used to happen all the time.

The real win, I think, is that Modus' makes dark themes accessible to me, in a way that they never were before. For the most part "dark themes" which have been so popular recently, are just impossible to see clearly (for me), I also find that it's less taxing to spend time in front of screens when darker backgrounds, so being able to spend most of my time doing work in an environment that's easy to read. I tend to keep to light backgrounds when using a laptop and dark backgrounds otherwise.

The second piece is that, I think I've caved in and decided to increase the size of the font, by default in my text editor, at least when I'm using my desktop/external monitor. I think my vision is as good as it's been, though I should probably get that checked out post-pandemic. I think there's a balance between "small fonts let you see more of the file you're working on," and "larger fonts let you focus on the area that you're editing." When I'm writing English, the focus is great, and when writing software I tend to want more context. There's a balance also in wanting to keep an entire line length viable at once, and an ideal words-per-line limit for text that's useful for making things easier to read. So there's some tuning there, depending on what your workload looks like.

I guess if there is any lesson in this it's that: Comfort matters, and you shouldn't push yourself into uncomfortable display situations if you can.

-1:-- Editor Themes (Post)--L0--C0--February 24, 2021 12:00 AM

Sacha Chua: 2021-02-22 Emacs news

Links from, r/orgmode, r/spacemacs, r/planetemacs, Hacker News,, YouTube, the Emacs NEWS file and emacs-devel.

-1:-- 2021-02-22 Emacs news (Post Sacha Chua)--L0--C0--February 23, 2021 04:47 AM

Protesilaos Stavrou: Introducing the Modus themes exporter (Emacs library)

I just published the initial version of the modus-themes-exporter.el as part of my dotfiles’ Emacs setup.

The library consists of a set of functions that help produce a port of the active Modus theme (modus-operandi or modus-vivendi) for a variety of external applications. Currently covered entries are XTerm, URxvt (rxvt-unicode), Xfce terminal (xfce4-terminal), and Vim (gui and term, as well as NeoVim).

The exporting is performed by the modus-themes-exporter-export command. Its doc string reads thus:

Export current Modus theme using TEMPLATE.

When called interactively, TEMPLATE is chosen from a list of candidates
using completion.  Else it must be a string that corresponds to the car
of a cons cell in `modus-themes-exporter-templates-alist'.

The output is stored in the kill ring.

When called from Lisp with optional FILE as a path to a regular file,
write there directly.  When called interactively with the universal
prefix argument (\\[universal-argument]), prompt for FILE instead:
supplying a non-existent path will create that file outright.  Once the
output has been written to the file, prompt to visit it.

With optional NO-VISIT, either as a non-nil symbol in Lisp or a
double prefix argument interactively, do not prompt to visit the

Here is a side-by-side presentation of Emacs (left) and Xfce’s terminal with Vim running inside of it (right). Click to enlarge.

Modus themes exporter light

Modus themes exporter dark

What is this all about?

Before we start… No, I do not intend to switch back to Vim: I plan to remain a full time Emacs user for years to come.

The modus-themes-exporter.el allows me to satisfy the demand for porting my Modus themes to other applications. I have done so several times in private, where I would supply an Xresources file or whatnot to the person emailing me. I have also offered my consent to those who asked whether they could create ports for VSCode—none of those endeavours has yielded any results as far as I know.

Demand for ports has also been expressed publicly on the issue tracker of the Modus themes’ repo (issue 116) as well as my dotfiles (issue 31). Furthermore, Simon Pugnet wrote the modus-exporter a while ago which, however, is targeted at older versions of the themes prior to their major refactoring in version 1.0.0.

I must stress that insofar as external text editors are concerned the output of this library does not constitute a fully fledged theme. Creating an original piece, especially one with the technical requirements for uncompromising legibility that the Modus themes stand for, requires a lot of work and painstaking attention to detail (I have been doing so for ~1.5 years now, ever since day one of switching to Emacs). No automated process invented thus far can replace the context-specific aesthetic judgement of the designer. Still, a templating system can help approximate what has already been achieved, while acknowledging the constraints imposed by the incompatibilities between the various applications and Emacs (e.g. how they highlight code, as illustrated in the screenshots above).

With those granted, the ports cover a subset of the palette used in each of the Modus themes which means, ipso facto, that they make compromises in the interest of maintainability. Similarly, there is no plan whatsoever to replicate the customisation options that the real themes for Emacs have, as well as implement anew their advanced, “do-it-yourself” features (consult the Modus themes’ manual, which, by the way, is pushing towards 20k words).

Experimental release

Please bear in mind that there is still a lot of work to be done before this library reaches a certain standard of quality:

  1. Refine the templating system.
  2. Test automated processes for outputting ports in bulk.
  3. Improve Vim’s colour mapping so that it mimics that of Emacs, to the extent possible.
  4. Write ports for the GTK Source view widget (Gedit, GNOME Builder, etc.).
  5. Expand support for more terminal emulators, such as Kitty, Alacritty.
  6. Convert colours from hexadecimal RGB notation to decimal, so that we can cover KDE’s Konsole and, potentially, Kate, Kwrite, etc.

Patches and user feedback are most welcome!

-1:-- Introducing the Modus themes exporter (Emacs library) (Post)--L0--C0--February 22, 2021 12:00 AM

Tim Heaney: Murderbot is my new favorite thing!

I just finished Network Effect by Martha Wells. This is the first full-length novel featuring Murderbot. What a joy! I only just discovered Murderbot late last year, but the first four novellas came out a few years ago. I can't believe no one has mentioned them to me before— they seem like exactly the sort of thing I would love— but I just happened to see them mentioned on twitter.
-1:-- Murderbot is my new favorite thing! (Post)--L0--C0--February 22, 2021 12:00 AM

emacsair: Transient 0.3 released

I am excited to announce the release of Transient version 0.3, consisting of 87 commits since the last release a year ago.
-1:-- Transient 0.3 released (Post)--L0--C0--February 21, 2021 10:59 PM

Raimon Grau: 2 emacs lisp curiosities

So some guy wrote a story about emacs being used in some air traffic control system, because elisp. :) And another user (unrelated) showed off this amazing cl-loop in emacs. 

 2 elispy things that got me smiling this weekend :)

-1:-- 2 emacs lisp curiosities (Post Raimon Grau ( 21, 2021 08:35 PM

Irreal: Configuring Mbsync to Work with Gmail

I long ago gave up using Gmail due to privacy concerns. Still, lots of folks—and companies—still use it because, among other things, it does have the advantage of portability that doesn’t depend on your current ISP or your OS. Gmail is easy to use as long as you use their Web UI.

If you’re an Emacs user who’d like to deal with email from within Emacs, however, things are bit more difficult. The hard part is retrieving mail from Gmail’s IMAP server. You’d think you could just use your usual credentials but that doesn’t work.

Jakub Kadlčík has a post that explains how to configure mbsync to deal with Gmail. The difficulties mostly involve generating and using a special password. I’d like to beat up on Google for making things so difficult but they’re simply trying to make the process a bit more secure and, truth by told, setting things up for Apple Mail is similar.

I’ve never configured mbsync for Gmail but I did for Apple Mail and found it difficult because I couldn’t find any write-ups on how to do it. As with Gmail, the difficulty is not the mbsync configuration file, it’s generating the special app password you use. It’s the same with Gmail: the tricky part is knowing that you need an app password and finding out how to get one. That’s where Kadlčík’s post comes in handy. If you’d like to retrieve Gmail with mbsync—or, really, any of the IMAP downloaders—take a look at his post.

-1:-- Configuring Mbsync to Work with Gmail (Post jcs)--L0--C0--February 21, 2021 07:24 PM

Alvaro Ramirez: Frictionless org habits on iOS

21 February 2021 Frictionless org habits on iOS


I've been wanting org to keep track of my daily habits for a little while. The catalist: reading James Clear's wonderful Atomic Habits (along with plenty of lock-down inspiration).

As much as I live in Emacs and org mode, it just wasn't practical enough to rely on my laptop for tracking habits. I wanted less friction, so I've been experimenting with building a toy app for my needs. Naturally, org support was a strict requirement, so I could always poke at it from my beloved editor.

I've been using the app every day with success. The habits seem to be sticking, but equally important, it's been really fun to join the fabulous world of Emacs/Org with iOS/SwiftUI.

This is all very experimental 1 and as mentioned on reddit (follow-up here) and twitter, the app isn't available on the App Store. I may consider publishing if there's enough interest, but in the mean time, you can reach out and install via TestFlight.

Send me an email address to flathabits*at* for a TestFlight invite.



The app's been fairly stable, but who knows… please backup your org file before feeding it to the lion.

-1:-- Frictionless org habits on iOS (Post)--L0--C0--February 21, 2021 06:08 PM

Irreal: Managing Window Placement

One of the tropes of Emacs use is the idea that there’s always something new to learn about the editor. I know that to be true but today it was brought home to me by a new video from Protesilaos Stavrou. The video is nominally about managing window placement but part of that is the notion of “side window.”

I had never heard of them before or even the concept that they implement. It’s no wonder. While I was preparing to write this I looked them up in the documentation but couldn’t find anything at all about them in the Emacs manual. I had to consult the Elisp manual to find any information about them.

The problem that Stavrou is seeking to solve is the inconsistent placement of the windows that pop up for things like HELP. Sometimes a new window is created; other times an existing window is reused. If you’re like me, you probably suspected that the behavior is configurable but haven’t seen or used the mechanism to do it. Window placement configuration is fairly fine-grained so you can pretty much have it anyway you like.

Unless you’re very particular about window placement or want to implement something like emacs-dir-treeview, you probably won’t need to deal with side windows or the other functionality that Stavrou discusses but his video does show how the configuration is possible if you need it. The video is just short of 19 minutes long so plan accordingly.

-1:-- Managing Window Placement (Post jcs)--L0--C0--February 20, 2021 09:56 PM

Marcin Borkowski: Using keyboard macros to emulate query replace

A few days ago, however, I needed to do something I consider really blogworthy, even though the tip I’m going to share today is (surprise, surprise!) very Emacs-centric. I was editing a paper which used italics (with the \emph LaTeX macro) really a lot (more than 100 times). Very many (but not all) of its occurrences were to be changed to quotes, so that e.g. \emph{petrichor} should be changed to ,,petrichor’’ etc.
-1:-- Using keyboard macros to emulate query replace (Post)--L0--C0--February 20, 2021 09:00 AM

Andrea: Emacs as your code-compass: what is this text about -- without me reading it?

-1:-- Emacs as your code-compass: what is this text about -- without me reading it? (Post)--L0--C0--February 20, 2021 12:00 AM

Christian Tietze: Emacs Org-Mode: Automatic Item TODO/DOING/DONE State Transitions for Checkbox Changes

In Emacs org-mode, you start with two states for your outline headings by default to manage tasks: TODO and DONE.

I recently introduced a new state in between: DOING. That helped me come back to stuff I had to let lie for a while.

In code, that means at least:

(setq org-todo-keywords
      (quote ((sequence "TODO(t)" "DOING(g)" "|" "DONE(d)"))))

I actually have multiple sequences, but these don’t matter for this demonstrations.

Thanks to StackExchange, I had automatic parent-child-updates and “statistics cookie” actions for a while.

Video Demo

Check out a video demo of the TODO/DOING/DONE state transitions [on YouTube.](]

Cookies in Org-Mode

The “cookies” part is a summary of sub-items: of N TODO/DONE items, how many are done? That’s displayed on the parent with a cookie

It works both for checkbox list items and for nested outlines. To illustrate this, let me quote another, very short StackExchange answer:

In this org file:

* TODO Organize party [2/4]
  - [-] call people [33%]
    - [ ] Peter
    - [X] Sarah
    - [ ] Sam
  - [X] order food
  - [ ] think about what music to play
  - [X] talk to the neighbors

The [2/4] and [33%] are statistics cookies. They describe the completion status of the children of the thing they’re on.

They’re pretty useful, because they update automatically as you update the status of children. You can also use them to show the status of child TODO tasks:

* TODO bake a cake [3/6]
** DONE buy ingredients
** DONE start cooking
** DONE realize you forgot eggs, dammit
** TODO drive back to the store and buy eggs
** TODO wait, I needed THREE sticks of butter?
** TODO drive back to the store and just buy a damn cake

The [2/4] and 33% and [3/6] parts are all cookies. See the docs for a longer explanation.

Of course I don’t want to update them manually! org-mode does that for me, and there’s C-c # (invoking org-update-statistics-cookies) just in case. Cookie updates happen as I complete items, both in checkbox lists and TODO items.

Automatic Parent-Child State Updates

Very closely tied to this is an addition in my code that, when the cookie is updated, automatically completes the parent item.

* TODO complete these! [2/3]
- [X] first step
- [X] second step
- [ ] last step

Once I hit C-c C-c with the cursor in the last line to tick off the checkbox, the cookie is updated to [3/3] and the whole item changes to this state:

* DONE complete these! [3/3]
- [X] first step
- [X] second step
- [X] last step

It transitions from TODO to DONE automatically.

When I untick a checkbox, it switches back to TODO again, too.

This works the same when you replace checkboxes with sub-items where some are DONE and some are still TODO. The cookie policies shown above apply.

Introducing an Intermediate State to the Auto-Update

With the new DOING state, I needed the cookie update code to change a bit, because when I set an item to DOING and ticked off a checkbox, my code would see that it wasn’t yet finished and needed to transition to TODO. The whole point of the DOING state is to mark an item as work-in-progress and then keep it in that state.

So I changed the policy to take all three states into account. The implementation for sub-items with their own DONE states is simpler, so I’ll show it first:

(defun ct/org-summary-todo-cookie (n-done n-not-done)
  "Switch header state to DONE when all subentries are DONE, to TODO when none are DONE, and to DOING otherwise"
  (let (org-log-done org-log-states)   ; turn off logging
    (org-todo (cond ((= n-done 0)
                    ((= n-not-done 0)
(add-hook 'org-after-todo-statistics-hook #'ct/org-summary-todo-cookie)

It simple because the hook already reports how many sub-items are done, and how many aren’t. (For checkboxes, I am going to need to parse the [x/y] cookie value.)

  • org-log-done and org-log-states are declared as local variables, overriding the global settings, and thus effectively turning off org-mode’s logging. I don’t use these and found it worked well to disable it here.
  • org-todo is a function that takes a new state and in this case updates the parent item. You don’t need to tell the function which item to update. The correct item is being activated, i.e. point moved there if needed, when the hook is called.
  • The trigger is in org-after-todo-statistics-hook, when the cookie is updated.

The three conditions are:

  • When the n-done count of DONE sub-items is 0 after the last change, i.e. when I uncomplete the last completed sub-item, it may be not a work-in-progress anymore. I change the state to TODO then. This doesn’t activate when there are no sub-items at all, because I need to toggle a sub-items state programmatically to make the hook execute.
  • When the n-not-done count of sub-items with other states, like TODO or DOING, is 0, that means we’ve completed everything. This might be a bit roundabout because of the negation you have to do in your head: When there are no not-done items, all items are done. There’s no other way to express “are all items completed” available here. (If we had n-total and n-done, we could test (= n-total n-done).)
  • The fallback/else clause: When 1 or more, but not all items are complete, then it’s a work in progress, so apply the DOING state.

How to Approach Auto-Updating the State (TODO/DOING/DONE) Based on Checkboxed

I already mentioned in passing that it’s a bit more work we have to do to achieve the same for checkboxes, because the built-in hooks don’t provide the same convenience. We don’t get a n-done count for a “checkbox changed” hook.

Instead, we have to rely on the “cookie updated” hook. This requires use of a cookie in the first place. The sub-item approach above works with and without cookies.

I’ll show the complete code for everything below, but here’s the approach I stole from the aforementioned StackExchange post years ago and adapted to my 3-state requirements:

  • Find the affected item’s line;
  • Use regular expressions to extract the [x%] or [n/m] cookies from the heading line;
  • Handle both percent and fractional cookies separately and update the state via org-todo like above.

The regex handling and the two cookie variants make the code a bit longer. Please see below for the implementation.

Complete Code

If you paste this into your init.el, you’ll get my whole implementation:

  • Change item state to TODO if no sub-items are DONE, or if the cookie reports [0/m] or [0%] completion.
  • Change item state to DOING when one but not all sub-items are DONE, or when the cookie contains a value above 0% and below 100% (aka for [n/m] where n < m and n > 0).
  • Change item state to DONE when all sub-items are DONE, or if the cookie reports [100%] or [m/m].

Please note that none of the hooks this relies on are called if you type the changes. If you type D-O-N-E for DONE, none of the org-mode facilities will note the state change.

You need to go through the interactive org-todo state change function (C-c C-t) or the Shift+Arrow_keys based state cycling to trigger hooks on the parent item in the outline.

For checkboxes, you need to tick them off with C-c C-c.

In case you forgot this and now nothing’s up-to-date anymore, you can trigger a cookie refresh by hitting C-c C-c with the cursor inside the cookie. So don’t be afraid.

(defun org-todo-if-needed (state)
  "Change header state to STATE unless the current item is in STATE already."
  (unless (string-equal (org-get-todo-state) state)
    (org-todo state)))

(defun ct/org-summary-todo-cookie (n-done n-not-done)
  "Switch header state to DONE when all subentries are DONE, to TODO when none are DONE, and to DOING otherwise"
  (let (org-log-done org-log-states)   ; turn off logging
    (org-todo-if-needed (cond ((= n-done 0)
                              ((= n-not-done 0)
(add-hook 'org-after-todo-statistics-hook #'ct/org-summary-todo-cookie)

(defun ct/org-summary-checkbox-cookie ()
  "Switch header state to DONE when all checkboxes are ticked, to TODO when none are ticked, and to DOING otherwise"
  (let (beg end)
    (unless (not (org-get-todo-state))
        (org-back-to-heading t)
        (setq beg (point))
        (setq end (point))
        (goto-char beg)
        ;; Regex group 1: %-based cookie
        ;; Regex group 2 and 3: x/y cookie
        (if (re-search-forward "\\[\\([0-9]*%\\)\\]\\|\\[\\([0-9]*\\)/\\([0-9]*\\)\\]"
                               end t)
            (if (match-end 1)
                ;; [xx%] cookie support
                (cond ((equal (match-string 1) "100%")
                       (org-todo-if-needed "DONE"))
                      ((equal (match-string 1) "0%")
                       (org-todo-if-needed "TODO"))
                       (org-todo-if-needed "DOING")))
              ;; [x/y] cookie support
              (if (> (match-end 2) (match-beginning 2)) ; = if not empty
                  (cond ((equal (match-string 2) (match-string 3))
                         (org-todo-if-needed "DONE"))
                        ((or (equal (string-trim (match-string 2)) "")
                             (equal (match-string 2) "0"))
                         (org-todo-if-needed "TODO"))
                         (org-todo-if-needed "DOING")))
                (org-todo-if-needed "DOING"))))))))
(add-hook 'org-checkbox-statistics-hook #'ct/org-summary-checkbox-cookie)

Possible Improvements

The hook for checkbox state updates is different. But to figure out if the item holding all checkboxes is complete, a cookie is required. Checkbox-ticking should also trigger the cookie statistics hook, though. So I think both implementations could be merged into one callback.

The basic code is 3 years old now. I guess org-mode v9.4 comes with new stuff that helps dealing with this, but which I haven’t discovered yet.

Are there any suggestions from your side, dear reader?

Receive Christian’s new posts via email

-1:-- Emacs Org-Mode: Automatic Item TODO/DOING/DONE State Transitions for Checkbox Changes (Post)--L0--C0--February 18, 2021 06:42 PM

Irreal: Exporting Org to HTML

Jake B has a helpful video on exporting Org files to HTML. Irreal readers almost certainly knows how to do this so why am I writing about it? As you know, you can tweak your Org file to pull in CSS files that alter what the exported HTML will look like when you export it with org-export-dispatch (Ctrl+c Ctrl+e) so that it will appear nicer than the default plain HTML output. The video shows how easy this is.

Jake B starts with getting rid of section numbering and the Table of Contents. That’s simply a matter of a couple of options but the real win comes with using Fabrice Niessen’s readtheorg CSS files that provide a really beautiful layout. I always thought that using Niessen’s themes involved a bunch of cloning and configuration but that’s not true. As Jake B shows, all you need do is add the line

where NAME is either readtheorg or bigblow.

Finally, Jake B shows how to add your own CSS. With the exception of the CSS file itself, that’s also a one-liner:

#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="styles.css"/>

assuming your CSS file is styles.css.

I started by saying Jake B’s post is helpful because it shows how easy it is to improve the default HTML exported from an Org file. If you use one of Niessen’s templates, it’s a matter of adding a single line. Use one of those templates or your own CSS and increase the beauty in the world.

-1:-- Exporting Org to HTML (Post jcs)--L0--C0--February 18, 2021 12:25 AM

Toby 'qubit' Cubitt: Evil cursor model


I recently got enticed by Vim's text editing model, and began my own personal descent into evil-(mode): the full-featured Vim implementation within Emacs itself.

However, even viewed purely as a text editor, Vim doesn't get everything right in my not-so-humble opinion.

The cursor in a text editor indicates the location where the next editing operation should act, both visually to the user and internally to the text editor. There are two conceptually different ways to model the cursor location. You can consider the cursor to be located in between two consecutive characters. Or you can consider it to be located on top of a particular character. Emacs, like almost every other text editor, uses the first model. If the cursoris at location 3, say, Emacs considers it to be between the 2nd and 3rd character in the text.Typing a character will insert it in between these two characters; deleting backwards will delete character 2; deleting forwards will delete character 3.

Vim also uses this cursor model in insert mode.But in normal mode, it uses the other cursor model: if the cursor is at location 3, in normal mode Vim considers it to be located on top of the 3rd character in the text. There are therefore two insersion commands: i will start inserting text just before the 3rd character (i.e. in between characters 2 and 3); a will start inserting text just after the 3rd character (i.e. in between characters 3 and 4). Similarly, p pastes text before the character under the cursor, whereas P pastes it after that character.

I think Vim got this one wrong.Having to keep two different cursor models in mind adds cognitive burden, for little gain.

-1:-- Evil cursor model (Post Toby Cubitt ( 18, 2021 12:00 AM

Andrea: Save your memory when compiling Scala

-1:-- Save your memory when compiling Scala (Post)--L0--C0--February 18, 2021 12:00 AM

Amit Patel: Building Emacs 27 on Apple ARM M1

On Mac, I sometimes run a prebuilt binary and sometimes compile my own. For Apple M1 (ARM) I started by using the x86 binaries from but I wanted to try compiling a native ARM version too. I saw that the work branch of Mitsuharu Yamamoto's Mac port has M1 patches applied, so I decided to try it.

Screenshot of Emacs 27 compiled on Apple ARM M1

Make sure /opt/homebrew/bin (ARM homebrew) is earlier in your path than /usr/local/bin (Intel homebrew).

brew install coreutils pkg-config libxml2 jansson gnutls autoconf gnu-sed
git clone --depth 1 --single-branch --branch work \
cd emacs-mac

and then build:

make clean
find . -name \*.elc -exec rm '{}' ';'

./configure \
     --with-mac-metal --with-xml2 --without-imagemagick --with-json \
     --with-modules --without-makeinfo \
     --prefix=$EMACSAPP/ \
     --enable-mac-app=$EMACSAPP --enable-mac-self-contained
make -j3
mac/ -q # test it
make install

You should see it bring up a window with:

This is GNU Emacs 27.1 (build 1, aarch64-apple-darwin20.1.0, Carbon Version 164 AppKit 2022.1)
 of 2020-11-30
Copyright (C) 2020 Free Software Foundation, Inc.


As various packages were made available in Homebrew, the situation improved.

  • [2020-11-30] Other parts of homebrew weren't complete enough for me to compile modules like vterm, so I temporarily switched back to emacs
  • [2020-12-01] The version flickrs a lot when using Rust + LSP + posframe, due to this issue, so I switched back to the Mac Port, but compiled for x86.
  • [2020-12-03] I had some issues with *.elc files from previous compiles not being recompiled so I ended up deleting all the *.elc files in the emacs build folder, and that resolved the problem.
  • [2020-12-05] I also had to recompile all the *.elc files in elpa modules, with (byte-recompile-directory "~/.emacs.d/elpa" 0 t).
  • [2020-12-07] I switched back to the ARM version, which works now. It seems faster but I don't know a good way to measure.
  • [2020-12-13] Modules like vterm seem to work now.
  • [2021-01-07] I learned that Homebrew emacs, emacs-plus, and railwaycat emacs now work on arm. I'm happy with the version I compiled, but these would be the first things to try if you don't want to compile your own.
-1:-- Building Emacs 27 on Apple ARM M1 (Post Amit ( 16, 2021 04:40 PM RSS Feeds by Email

While RSS is great, it’s not easy to explain to those who haven’t heard of it before. Plus, it’s hard to get someone started on using RSS since it requires a separate application. TwoBitHistory has an great post on the history of RSS that covers it’s fall from grace.

Without RSS, keeping up-to-date on your favorite websites from the independent web becomes a bit more difficult. Most sites now feature a newsletter and email is a great alternative to RSS. Julia Evans describes the MailChimp process to turn an RSS feed into a weekly digest.

I’ve decided to use something even simpler: the service. provides a daily email with posts from this (or any) RSS feed. It is entirely managed by the subscriber via email (see the website for details on how to subscribe and various preferences you can set).

To facilitate the subscription process, I added an HTML mailto link to create the subscribe email for this site:

<a href=""><img src="/images/rss-email.png" id="rss"></a> will automatically unsubscribe any websites that are not updated within 90 days… which should inspire me to post with some frequency.

-1:-- RSS Feeds by Email (Post Elsa Gonsiorowski)--L0--C0--February 16, 2021 12:00 AM

Sacha Chua: 2021-02-15 Emacs news

Links from, r/orgmode, r/spacemacs, r/planetemacs, Hacker News,, YouTube, the Emacs NEWS file and emacs-devel.

-1:-- 2021-02-15 Emacs news (Post Sacha Chua)--L0--C0--February 15, 2021 05:29 AM