Alex Schroeder: Emacs as a way of life

I’m sitting on some cushion on the floor, headphones on, because I just listened to some talks. Time to take them off and start writing something.

I learned about the conference 15min before it started. Not great timing, I know. But I stumbled into three great talks that I want to summarise. I think writing is a way of learning, and Emacs is a tool for writing, and I’m writing this post in Emacs, so you know where this is going. It’s going to be meta! 😅

Yeah. I’m mostly interested in the social and philosophical aspects of Emacs.

The first talk I want to mention is by @acdw. He runs Breadpunk, “a shared Unix computer focused on bread”. I’ve mentioned them before because I like their manifesto:

Breadpunk rejects the commoditization of life by market capitalism. Breadpunk is an attitude that something our ancestors made largely for free is not something we should be spending money on. Breadpunk is the idea that we have time again, that industrialism gives us time to bake bread. – manifesto

Ah, perfect!

I wrote frowny.el to scratch someone else’s itch as a joke on IRC, but it has been called “pretty useful, for a joke package.” I feel like that encapsulates the spirit of Emacs and that’s why I want to present on this topic. – The True Frownies are the Friends We Made Along the Way: An Anecdote of Emacs's Malleability

Case Duckworth’s talk was simple. He talked about the meandering journey that led him to Emacs, and specifically, the community around it: how he rewrote his init files a few times; how he watched the conference videos; how he started reading /r/emacs on Reddit; how he joined on IRC. And how one day he’s talking to this other person called alphapapa, and they talk about that tiny problem they have in chat: when they write a frownie – apparently a common occurrence in chat, the “electric parenthesis mode” they are using automatically adds a closing parenthesis. So every frownie 😟 turns into the world’ biggest gaping mouth, 😟). so they write a tiny little minor mode for chat, which is called whenever they type the opening parenthesis, and if the previous character look like “eyes” then the “electric parenthesis” magic doesn’t happen. And then the code is shared. And improved. And shared again. And there you are: your first Emacs package.

It resonated with my own experience. When I was in my twenties, I was into Usenet. I just logged into Google Groups (yikes!) and searched for “Alex Schroeder” and “emacs” and got about 900 conversations. I remember doing a similar search many years ago and getting nearly 2000 messages. I participated a lot. I also knew a lot, even though I hadn’t done a lot of programming. I joined on IRC. I created Emacs Wiki! The first edit to the SiteMap page of Emacs Wiki was 2001-05-14. That was a long time ago. And soon after I stopped hanging out on Usenet. But I had joined the community, and I liked it. I liked answering questions. I liked writing stuff up. I still feel like I must have written the first 1000 pages of Emacs Wiki all by myself, basically by answering questions on IRC with a wiki page.

And eventually I did get some code into Emacs. A SQL mode I used for work. I worked on the Emacs IRC client (ERC) with Mario Lang and herded all the cats so we got add it to Emacs. Back then, I don’t remember anybody using git. Was it all CVS? Or did we have SVN and SourceForge already? I don’t remember. It was important to get packages added to Emacs itself because there was no Emacs package management. We all just downloaded files from gnu.emacs.sources back then, stuffed them into an “~/elisp” directory, added it to our load-path, and loaded it. It worked well enough, but back then, there was no ELPA, no MELPA, no GitHub. It was a different world.

And yet, we had communities, we had questions, we had answers, and we shared code. We helped each other use Emacs and make it our own.

The second talk I want to mention is @kheya’s talk about Emacs being a “prepared environment”. Last year, he had an interesting talk about the Lakota language and Emacs! 😍

This talk introduces the concept of Emacs as an educational environment and how it expresses elements of Montessori psychology regarding “Human Tendencies”. Human tendencies are innate drives present in everybody that allow us to explore and make sense of our world. – Emacs and Montessori Philosophy

Grant Shangreaux went through human tendencies according to the Montessori understand of human tendencies. I have no idea about Montessori. All I know is that they run a bunch of kindergartens here in Switzerland and they seem to be well regarded even if they don’t belong to the mainstream. I have no children and haven’t talked to anybody about their Montessory kindergarten time, so all I was listening to are the human tendencies Grant mentioned, how he explained them, and how you can something within Emacs to satisfy them all: Orientation, Order, Exploration, Communication, Activity, Manipulation, Work, Repetition, Exactness, Abstraction, and Perfection.

Let’s go through them.

Orientation is the tendency to touch things, to know where you are, where you fit in, and where to go from here. Emacs is an apparently endless environment. Most people start with text editing, and I’m writing this post in Emacs right now, but in the back there’s IRC running, and a browser, and a mail client, and sometimes I play music from Emacs… So not only is there all the Emacs functionality it comes with, but there are megabytes of more functionality to load into your Emacs that are distributed with it, and there is more to loaded from packages distributed separately, many ways to connect it to the Internet, to your operating systems, to the programs you have installed. And thus, orientation is important. Orientation means that there are signposts that tell you what to do in order to find more. Manuals. Help about the current mode. Help about the key bindings. Help about these functions. Help about the options. Help setting those options. And so, slowly, it pulls you in.

Order is the tendency to follow rules, to obey conventions. We both impose it on each other, telling each other to follow naming conventions, or how loading our code should not change the behaviour of Emacs unless the user makes an explicit change, activates a mode, or something like that. And once we’ve adapted to it, we can take advantage of it. Knowing the community expectations makes it easier to explore new code. We expect documentation, manuals, comment, hooks, web sites, repositories. Order helps us get things done once we bend to it.

Exploration is the tendency to go where no human has gone before, or so it would seem to us once we start up Emacs. You hit “M-x” and are faced with a gazillion commands you can call, some of them auto-loading more code into your Emacs environment. It’s daunting, it’s intimidating, but it’s also … exciting! And if you join a community, the suggestions keep on coming. Have you tried swiper? Do you use occur? Have you tried moccur? What about all the other variants? There are so many ways to search for occurrences of text in your buffers.

Communication is the tendency to talk to anything: other humans, pets, animals, plants, chatting, posting, tooting, mailing, writing, printing… It’s an endless list. And that’s why Emacs is so much more than a text editor. It’s a platform with which we interact with other people. We make friends, inside Emacs. Some of us fall in love, inside Emacs. This communication enables the community that strengthens us. We have our backs.

Activity is the tendency to do things because we don’t like being bored. Boredom is what drives us. Perhaps these days it’s easy to be distracted. To lose yourself on social media, to let yourself be pulled this way or that way by the algorithms on Facebook, Instagram, or Twitter. You think you have picked the right people, but still the algorithm surfaces and emphasises, hides and reorders. After dinner, I just like to open Emacs, maximise the window, disconnect from IRC, and write. I write blog posts, programs, random tables for my games, and more besides. I sometimes need to focus on doing something, but on my own schedule.

Manipulation is the tendency to fiddle with your tools, to use them, to improve them. We use Emacs to improve Emacs, to examine how it does the things it does, to change them, to adapt them. I’m not even saying that it’s “better” in some way. But perhaps it’s “different” and for my monkey brain, that’s also a reward. When somebody else needs to use my computer to do something, it’s probably hard for them, and the groan and complain. But for me, it’s my self-made multi-tool. Who cares if it’s fast? I made it mine! I changed the colours, and then I changed everything else.

Repetition is the tendency to do what you have always done. When in doubt, do it again. Redo it, but different. Experiment. The doing provides you with the dexterity to do the things without sleeping. You reformat the paragraphs, you save the buffers, you switch, you search, you return to where you just were, and half the time you cannot remember how you did it. C-x b, C-s M-C-%, C-z, C-u SPC, whatever. Your fingers know the drill. All of that motor pattern learning is valuable. It means you get to wield your tool without thinking. It also means that the UI can’t change dramatically. That would invalidate all our drills. But you can change it at your own pace. And so your tool grows with you, at the speed you’re comfortable with.

Exactness is the tendency to have things exactly as you want them. And with Emacs, you can hone that. Everything you don’t like, you can fix and improve until it is exactly so. And if you need to be exact in your text editing, you can program it; you can use keyboard macros, Lisp code, shell commands, and more. It’s satisfying to be exact!

Abstraction is the tendency to learn about the principles governing a thing, and then taking advantage of your new understanding. Text buffers, echo area, text properties, overlays, processes, functions, hooks, variables, and on and on. Of course, programming is like that. But the world in between, when you’re a user and you’re not yet programming, that is important as well. A bit like the use of spreadsheets. Once people understand how they work, they can build their own applications using them. Programming, data storage, computation, it all happens “in there” somewhere. And the understanding of how that works, it’s powerful. You don’t need to learn how to write code in a programming language to benefit from these things.

Perfection is the tendency to improve ourselves, and the tools we use. I used to joke that we keep configuring our Emacs because we wouldn’t know what else to do with it. Of course we do. But working on our tools is a joy in itself. The other day somebody commented on the fediverse: “This is probably why I am a vim user: nobody ain’t got no time to tinker for years with an editor. Once you learn enough vim to work correctly, you are set.” Well… I guess you’re set for text editing. But hopefully you’ve seen that there’s more to life. On IRC we used to say that “Emacs is the editor that keeps on giving.” And it does.

OK. This is going to be my longest blog post ever. I fear that if I stop now, I’ll never finish. The third talk I want to mention is Greta Goetz’s talk about Emacs being the kind of tool and experience that embodies and teaches you the design patterns you need to make it your own.

By championing the opportunity for users to also be co-creators (cf. Beaty et al.), the free software design at the core and center of Emacs teaches us a way of “being” (Alexander, Gabriel) that can be extended to both the Emacs community and beyond, in a knowledge of how to live (Stiegler, Illich). – Emacs as Design Pattern Learning

This last one was an eye opener. Wow! Greta Goetz manages to pull together Christopher Alexander’s thoughts patterns, Ivan Illich’s thoughts on conviviality, and more. While I was listening to the talk, I felt like I wanted to pull quotes from it every minute or two.

Before we continue, let me say this: if you haven’t read Christopher Alexander’s book, A Timeless Way of Building, I recommend it wholeheartedly. It’s about quality, and how to communicate it. The second book is essentially an example of the idea introduced in this first book: to collect specific solutions to specific problems in a kind of “library”, a collection of design patterns that captures good solutions and scales horizontally (you can always write more of them) and vertically (higher order solutions can build on more concrete solutions), that can be communicated effectively, partially, incrementally, that can be improved upon. It’s fantastic, and I loved the style it was written in, too.

The patterns are written for practitioners. They are concrete like that. The pattern language for an architect is different than for a programmer. In all cases, however, it is intended for the person that needs the information to learn from it. There is great vision, no master plan, no theoretical background. There is just the problem, and the solution.

Now you know why I love wikis. The first wiki was exactly that: a pattern language. Every page name a pattern, a problem, a solution, or a discussion. And you kept using the page names on other pages, with all the terms links to their pages. A “link language”, as Lion Kimbro said.

Goetz then starts talking about what makes Emacs an ideal learning environment. We’re back to the human tendencies that Grant Shangreaux described, and back the experience Case Duckworth described. You can use Emacs as text editor, but you can also learn about Emacs, extend it, for as far as you want. It keeps on giving. It grows with you.

Emacs can be used for a variety of things, and in each of them, we recursively find new “centres”. Emacs the text editor, but also Emacs the IRC client, the mail reader, the user-interface for git, for other version control software, for file management, and on and on. You can grow along these lines, and you can find the particular solutions to your individual problems, right here, right now. It’s situated, grounded in your reality.

It can turn non-programmers into programmers. First we fiddle with our init files, then we write our customisations, then write our packages, then we contribute them to MELPA, then we get them added to Emacs itself. There’s a spiral of involvement. You can go along, if you want to. You can partake in and contribute to the evolution of the tool you are using. You don’t need to be disintermediated. You are not a “user” separated from the secret world of “developers”. No, we are all users, and you can be as much part of it as you want to.

This is why interacting with Emacs is a rich experience. It’s not an app where you swipe left or right, or up and down, you don’t click on stars and thumbs up and move on. Emacs is life. It is complex. It supports our decision making, problem solving, it engages our interactions with other humans. We are asked to think about sharing, contributing, about our responsibility towards our fellow humans.

We learn from each other. We see how help is given on the social media of our choice, be it IRC, the fediverse, or some other site; we are socialised into a better society. We learn to help our fellow humans, we learn how to do it in a way that enables others to do the same, and we grow, together.

How different this is from a world where you are only interacting with the software. Or the help system of the software. How alienating that is, in comparison. Seeking help turns into a problem. If we do get help, it’s from some representative who is paid to do it, some help desk, controlled by tickets and service level agreements. But not us.

Now, I realise that much of what was said is not unique to Emacs. The only problem is, I don’t know those other communities, those other tools. I don’t know of another tool that I can use as an interface to nearly everything I do with my laptop. Emacs essentially is my laptop. I need a window manager because I need to switch to some terminal or to a web browser every now and then. But I hate the web browser and the exploitative relation I have with many websites, and I wish eshell were better so that I don’t need a real terminal anymore. I don’t know of another tech community that is so helpful as the Emacs community. I’m sure it exists, I just don’t know it. And I’m sure the bad apples exist in the Emacs community, too. After all, I do have a bunch of them on my IRC ignore list… But on the whole, I think the combination of an extensible, well-documented tool that can encompass all my computing needs, and a friendly and helpful community, have resulted in the development of a strange beast that comes very close to my dream computing. On my own terms.

I love it.

-1:-- Emacs as a way of life (Post)--L0--C0--November 27, 2021 11:27 PM

Irreal: Tree Sitter and Syntax Highlighting

Mickey Petersen author of the the excellent book Mastering Emacs and the blog of the same name has another of his comprehensive and informative articles on his blog. This time it’s about tree sitter and its application to syntax highlighting in Emacs.

Even though we take it mostly for granted, syntax highlighting is actually a devilishly difficult problem. Emacs and almost every other editor does it with a witches’ brew of regular expressions and ad hoc functions. The results are usually, but not always, good enough. The correct method, of course, is to build a syntax tree of the code and use that to inform the highlighting. There’s a whole host of problems with that approach. In the first place, the code you’re editing probably isn’t syntactically correct because it’s incomplete. Secondly, the naive solution of rebuilding the tree with every keystroke is too slow to be practical and there are other problems as well.

Mickey has a solution: use tree sitter to drive the highlighting. If you don’t know about tree sitter or what it’s used for, head on over to Mickey’s post for the details. Tree sitter can do more than just figure out syntax highlighting. Mickey mentions the excellent ParEdit and its use in Lispy languages. Mickey wanted to extend that capability to other languages, Python in particular.

He’s built a package to do just that. He calls it combobulate. It’s still alpha software but you can try it out if you like. Mickey says he’ll put it on Melpa as soon as he works out a few more issues. Mickey believes that the tree sitter approach is the future for addressing these types of problems.

I know I keep saying this but tree sitter and Emacs’ embrace of it once again puts the lie to the notion that Emacs is moribund technology. The reverse is true. Emacs keeps introducing new capabilities that other editors copy and then use to support their claims of superiority.

-1:-- Tree Sitter and Syntax Highlighting (Post jcs)--L0--C0--November 27, 2021 04:57 PM

Magnus: Fallback of actions

In a tool I'm writing I want to load a file that may reside on the local disk, but if it isn't there I want to fetch it from the web. Basically it's very similar to having a cache and dealing with a miss, except in my case I don't populate the cache.

Let me first define the functions to play with

loadFromDisk :: String -> IO (Either String Int)
loadFromDisk k@"bad key" = do
    putStrLn $ "local: " <> k
    pure $ Left $ "no such local key: " <> k
loadFromDisk k = do
    putStrLn $ "local: " <> k
    pure $ Right $ length k

loadFromWeb :: String -> IO (Either String Int)
loadFromWeb k@"bad key" = do
    putStrLn $ "web: " <> k
    pure $ Left $ "no such remote key: " <> k
loadFromWeb k = do
    putStrLn $ "web: " <> k
    pure $ Right $ length k

Discarded solution: using the Alternative of IO directly

It's fairly easy to get the desired behaviour but Alternative of IO is based on exceptions which doesn't strike me as a good idea unless one is using IO directly. That is fine in a smallish application, but in my case it makes sense to use tagless style (or ReaderT pattern) so I'll skip exploring this option completely.

First attempt: lifting into the Alternative of Either e

There's an instance of Alternative for Either e in version 0.5 of transformers. It's deprecated and it's gone in newer versions of the library as one really should use Except or ExceptT instead. Even if I don't think it's where I want to end up, it's not an altogether bad place to start.

Now let's define a function using liftA2 (<|>) to make it easy to see what the behaviour is

fallBack ::
    Applicative m =>
    m (Either String res) ->
    m (Either String res) ->
    m (Either String res)
fallBack = liftA2 (<|>)
λ> loadFromDisk "bad key" `fallBack` loadFromWeb "good key"
local: bad key
web: good key
Right 8

λ> loadFromDisk "bad key" `fallBack` loadFromWeb "bad key"
local: bad key
web: bad key
Left "no such remote key: bad key"

The first example shows that it falls back to loading form the web, and the second one shows that it's only the last failure that survives. The latter part, that only the last failure survives, isn't ideal but I think I can live with that. If I were interested in collecting all failures I would reach for Validation from validation-selective (there's one in validation that should work too).

So far so good, but the next example shows a behaviour I don't want

λ> loadFromDisk "good key" `fallBack` loadFromWeb "good key"
local: good key
web: good key
Right 8

or to make it even more explicit

λ> loadFromDisk "good key" `fallBack` undefined
local: good key
*** Exception: Prelude.undefined
CallStack (from HasCallStack):
  error, called at libraries/base/GHC/Err.hs:79:14 in base:GHC.Err
  undefined, called at <interactive>:451:36 in interactive:Ghci4

There's no short-circuiting!1

The behaviour I want is of course that if the first action is successful, then the second action shouldn't take place at all.

It looks like either <|> is strict in its second argument, or maybe it's liftA2 that forces it. I've not bothered digging into the details, it's enough to observe it to realise that this approach isn't good enough.

Second attempt: cutting it short, manually

Fixing the lack of short-circuiting the evaluation after the first success isn't too difficult to do manually. Something like this does it

fallBack ::
    Monad m =>
    m (Either String a) ->
    m (Either String a) ->
    m (Either String a)
fallBack first other = do
    first >>= \case
        r@(Right _) -> pure r
        r@(Left _) -> (r <|>) <$> other

It does indeed show the behaviour I want

λ> loadFromDisk "bad key" `fallBack` loadFromWeb "good key"
local: bad key
web: good key
Right 8

λ> loadFromDisk "bad key" `fallBack` loadFromWeb "bad key"
local: bad key
web: bad key
Left "no such remote key: bad key"

λ> loadFromDisk "good key" `fallBack` undefined
local: good key
Right 8

Excellent! And to switch over to use Validation one just have to switch constructors, Right becomes Success and Left becomes Failure. Though collecting the failures by concatenating strings isn't the best idea of course. Switching to some other Monoid (that's the constraint on the failure type) isn't too difficult.

fallBack ::
    (Monad m, Monoid e) =>
    m (Validation e a) ->
    m (Validation e a) ->
    m (Validation e a)
fallBack first other = do
    first >>= \case
        r@(Success _) -> pure r
        r@(Failure _) -> (r <|>) <$> other

Third attempt: pulling failures out to MonadPlus

After writing the fallBack function I still wanted to explore other solutions. There's almost always something more out there in the Haskell eco system, right? So I asked in the #haskell-beginners channel on the Functional Programming Slack. The way I asked the question resulted in answers that iterates over a list of actions and cutting at the first success.

The first suggestion had me a little confused at first, but once I re-organised the helper function a little it made more sense to me.

mFromRight :: MonadPlus m => m (Either err res) -> m res
mFromRight = (either (const mzero) return =<<)

To use it put the actions in a list, map the helper above, and finally run asum on it all2. I think it makes it a little clearer what happens if it's rewritten like this.

firstRightM :: MonadPlus m => [m (Either err res)] -> m res
firstRightM = asum . fmap go
    go m = m >>= either (const mzero) return
λ> firstRightM [loadFromDisk "bad key", loadFromWeb "good key"]
local: bad key
web: good key

λ> firstRightM [loadFromDisk "good key", undefined]
local: good key

So far so good, but I left out the case where both fail, because that's sort of the fly in the ointment here

λ> firstRightM [loadFromDisk "bad key", loadFromWeb "bad key"]
local: bad key
web: bad key
*** Exception: user error (mzero)

It's not nice to be back to deal with exceptions, but it's possible to recover, e.g. by appending <|> pure 0.

λ> firstRightM [loadFromDisk "bad key", loadFromWeb "bad key"] <|> pure 0
local: bad key
web: bad key

However that removes the ability to deal with the situation where all actions fail. Not nice! Add to that the difficulty of coming up with a good MonadPlus instance for an application monad; one basically have to resort to the same thing as for IO, i.e. to throw an exception. Also not nice!

Fourth attempt: wrapping in ExceptT to get its Alternative behaviour

This was another suggestion from the Slack channel, and it is the one I like the most. Again it was suggested as a way to stop at the first successful action in a list of actions.

firstRightM ::
    (Foldable t, Functor t, Monad m, Monoid err) =>
    t (m (Either err res)) ->
    m (Either err res)
firstRightM = runExceptT . asum . fmap ExceptT

Which can be used similarly to the previous one. It's also easy to write a variant of fallBack for it.

fallBack ::
    (Monad m, Monoid err) =>
    m (Either err res) ->
    m (Either err res) ->
    m (Either err res)
fallBack first other = runExceptT $ ExceptT first <|> ExceptT other
λ> loadFromDisk "bad key" `fallBack` loadFromWeb "good key"
local: bad key
web: good key
Right 8

λ> loadFromDisk "good key" `fallBack` undefined
local: good key
Right 8

λ> loadFromDisk "bad key" `fallBack` loadFromWeb "bad key"
local: bad key
web: bad key
Left "no such local key: bad keyno such remote key: bad key"

Yay! This solution has the short-circuiting behaviour I want, as well as collecting all errors on failure.


I'm still a little disappointed that liftA2 (<|>) isn't short-circuiting as I still think it's the easiest of the approaches. However, it's a problem that one has to rely on a deprecated instance of Alternative for Either String, but switching to use Validation would be only a minor change.

Manually writing the fallBack function, as I did in the second attempt, results in very explicit code which is nice as it often reduces the cognitive load for the reader. It's a contender, but using the deprecated Alternative instance is problematic and introducing Validition, an arguably not very common type, takes away a little of the appeal.

In the end I prefer the fourth attempt. It behaves exactly like I want and even though ExpectT lives in transformers I feel that it (I pull it in via mtl) is in such wide use that most Haskell programmers will be familiar with it.

One final thing to add is that the documentation of Validation is an excellent inspiration when it comes to the behaviour of its instances. I wish that the documentation of other packages, in particular commonly used ones like base, transformers, and mtl, would be more like it.



I'm not sure if it's a good term to use in this case as Wikipedia says it's for Boolean operators. I hope it's not too far a stretch to use it in this context too.


In the version of base I'm using there is no asum, so I simply copied the implementation from a later version:

asum :: (Foldable t, Alternative f) => t (f a) -> f a
asum = foldr (<|>) empty
-1:-- Fallback of actions (Post)--L0--C0--November 27, 2021 10:31 AM

Bozhidar Batsov: A Decade with Jekyll

2021 is the year of anniversaries for me:

Probably I’m forgetting some other important anniversaries, especially those that were not related to technology. 2011 was a really big year for me!

Today I’d like to look back on my experience with Jekyll, the static site generator (SSG) that I’m using to publish this site and my other blogs Meta Redux and Emacs Redux. Back in the day Jekyll was a trend-setter - it basically defined the SSG category and every subsequent tool in it was compared to Jekyll. A lot has happened since 2011:

  • Jekyll has a ton of great alternatives today (e.g. Hugo, Ghost, Cryogen, etc)
  • For a while Octopress was all the rage in the world of Jekyll (basically Octopress was a highly customized Jekyll setup that many people were using, including me)
  • Jekyll’s development lost momentum over time. For a while the project was supported by GitHub engineers directly, but I believe this is no longer the case.
  • Ruby was all the rage back then, now that’s no longer the case. Part of the allure of the alternatives is that they are not based on Ruby and supposedly are easier to use as you don’t have to deal with gems, Gemfiles, etc.

I definitely had a troubled relationship with Jekyll myself. Early on I was quite annoyed that you had to setup everything in Jekyll manually, even basic things like an Atom feed or archive/tags pages. I was also frustrated that I had to fiddle with the themes a lot, as HTML and CSS were never my strong suites. If I recall correctly the early versions of Jekyll used some horrible Markdown parser that caused all sorts of problems for me. Still, for all its shortcomings Jekyll was a huge win for me as it allowed me to do exactly what I wanted to do:

  • Write my articles in Emacs using my beloved Markdown format.
  • Store my blog under version control and treat it like any other software project.
  • Host my blog for free on GitHub Pages.

I guess the first point was the only important point, though. When it comes to writing there’s a single tool I want to use everywhere and that’s Emacs. In hindsight I realize that Jekyll and Emacs are quite similar in some ways - they are both building material and not some end user products. Jekyll is a framework for building sites and this requires you to invest a lot in tweaking the setup to your liking. Emacs is a framework for building the ultimate editor. We’ve already established numerous times that’s a life-long endeavor.

Over the years I considered replacing Jekyll with something else a few times, especially when Hugo was all the rage and I was still stuck with a semi-broken Octopress setup. I remember playing with Hugo and thinking that it’s not really that different from Jekyll. Sure, it generated sites faster, but I never cared much about this. Frankly, I almost never run Jekyll locally - I simply write and push to GitHub when I feel I’ve written something that’s already in a readable form. Production is my preview - unlike with software I think for blogs that’s fine. The fact that Jekyll is written in Ruby is a problem for most people, but for me it’s a feature. After all, I was a Ruby programmer back in 2011 and I still involved with Ruby to this day.

Most importantly, however, Jekyll is as simple as it gets. I guess pretty much everyone can setup a Jekyll blog in 5 minutes if they don’t need to do customize some theme. When it comes to writing the thing that truly matters is the content and not its appearance. The more time you spend on customizing your blogging tool, the less time you have for the actual process of writing.1 Jekyll gets the job done for me and I simply don’t want to invest a lot of time to learn properly another SSG (e.g. Hugo) when I can be writing new articles instead. Time is our most precious resource and the older I get the more I value it.

I’ve had a productive decade with Jekyll, sans the end of the Octopress era, and I think I won’t be moving away from Jekyll any time soon. Yeah, there’s always some room for improvement and probably many of the newer tools do the job better in our area or another, but Jekyll covers well my use-cases and that’s what matters the most to me. I recall back in my Linux days I spent countless hours doing distro-hopping, with the misguided notion that some Linux distro will be massively better than all the others. A classic example of missing the forest for the trees. At this point I’m fairly certain that no SSG is significantly better than the alternatives and the only practical differences for me are their communities and how much do I have to learn to use one of them.

And that’s a wrap. This happens to be the 132th article I publish here since adopting Jekyll. I’ve also published exactly 280 articles on “Emacs Redux” and “Meta Redux”. Here’s to the next 10 years of blogging with Jekyll and Emacs! I hope I’ll do better this time around.2

  1. I guess that’s why I always opted to use relatively simple Jekyll themes. Often I think that minima is the greatest theme ever invented. 

  2. In terms of quality, not quantity. 

-1:-- A Decade with Jekyll (Post Bozhidar Batsov ( 27, 2021 08:54 AM

Manuel Uberti: A job for VC

Some days ago I briefly wrote about my willingness to give Emacs built-in VC system a try for real. For real means that it’s easy to praise the beauties of vc-git when working on personal projects such as this blog, but is VC actually worth it on bigger projects where different people commit and push regularly, rebasing is a habit, and merge conflicts are unavoidable necessities?

A warning first. This article is not intended as a VC tutorial. It aims to be an example of how I use it or, to phrase it better, how I started to use it. As Mickey Petersen suggests in the “Exploring Emacs” section of his great Mastering Emacs book, if you want to know more about VC there is plenty of information right within our favourite text editor. Furthermore, Protesilaos Stavrou has a couple of nice videos on VC you might want to check out: Introduction to VC and Workflow with VC for Git.

Now, let’s break down a common workflow of mine:

  • A new ticket is assigned to me
  • I create a new branch for this ticket, starting from the master one
  • I code my thing
  • I commit and push my code
  • I file a new merge request ready to be reviewed
  • The review may require changes to my code
  • I may need to rebase my changes onto master because other developers have merged their branches before me
  • Merge conflicts may arise and need to be fixed
  • I push my updated code ready to be reviewed again
  • If everything’s fine I merge my changes, otherwise back to my edit/rebase/merge process until it’s properly done
  • Meanwhile, it may happen that I need to stash my changes and quickly fix a higher priority bug

This more or less happens on a daily basis, so the interaction with Git (the only VCS I have used in the last ten years) must be smooth. On the other hand, Git-wise the above workflow is not that complicated. For instance, I rarely use features such as cherry-picking or bisecting.

On the surface, the main difference between Magit and VC is transient. Magit transient menus make all the operations I described above1 a breeze. From checking out a branch to interactive rebasing, Magit requires few key strokes to accommodate my needs. The blatant truth is that Magit wraps everything I want from Git and much more in a user interface that just works.

VC, however, is not tightly coupled to Git, so it does not cover all of its many options. And yet I was able to manage my work projects with VC alternatives to Magit commands.

Operation VC Magit
Project status project-vc-dir (C-x p v) magit-status (C-x g)
Pull vc-update (F, in my case) magit-pull (F p)
New branch vc-retrieve-tag (C-u B s) magit-branch (b c)
Commit vc-next-action (C-x v v) magit-commit (c c)
Rebase shell-command (M-!) + git rebase master magit-rebase (r p)
Push vc-push (P or C-u P) magit-push (P p)
Stash mu-vc-git-stash (z) magit-stash (z)
Log vc-print-root-log (L) magit-log (l l)

VC has its own vc-git-stash, vc-git-stash-pop, and vc-git-stash-delete commands, but instead of calling them via M-x every time I devised mu-vc-git-stash and bound it to z in vc-dir-mode-map:

(defun mu-vc-git-stash (pop-or-delete)
  "Create, pop, or delete Git stashes.
With no POP-OR-DELETE call `vc-git-stash'. With one prefix
argument call `vc-git-stash-pop'. With two prefix arguments call
  (interactive "P" vc-dir-mode)
  (cond ((= (prefix-numeric-value pop-or-delete) 4)
         (call-interactively #'vc-git-stash-pop))
        ((= (prefix-numeric-value pop-or-delete) 16)
         (call-interactively #'vc-git-stash-delete))
        (t (call-interactively #'vc-git-stash))))

As you can see, C-u z issues vc-git-stash-pop while C-u C-u z runs vc-git-stash-delete.

One thing that Magit really shines at for me is interactive rebasing (r i). I haven’t had the opportunity so far to check how I can handle this with VC. I guess a combination of shell-command and something I have yet to discover would do, probably.

Anyway, I’ll keep using VC in the next days and report back if I manage to adapt more of my Git workflows to it. I suspect Magit will outshine the humbler Emacs built-in eventually, but who knows. Reading on the emacs-devel mailing list that some wild Emacs developers prefer VC to Magit seems to confirm that the world is still full of surprises.


  1. Well, only the ones related to Git of course. 

-1:-- A job for VC (Post)--L0--C0--November 27, 2021 12:00 AM

Irreal: Emacs as a Lifestyle

Bozhidar Batsov made an interesting observation that several people have mentioned or commented on. The TL;DR is that Batsov thinks that Emacs can be considered a lifestyle. If you’re an Emacser your reaction is probably like mine: it’s not literally true but it does capture a certain truth concerning how we feel about Emacs.

For me, the essence of that feeling is captured by Stephen Ramsey’s reply to the tweet that started the whole thing off.

I usually express this by comparing my Emacs configuration to a Japanese garden: It’s a work that’s always in progress but never finished. The gardener spends his life improving the garden little by little and striving for a perfection that is never reached. So it is with our Emacs configurations: A neverending search for an ideal never achieved.

-1:-- Emacs as a Lifestyle (Post jcs)--L0--C0--November 26, 2021 06:08 PM

Meta Redux: Automate Spell-checking in Your Projects with GitHub Actions

A couple of years ago I wrote an article about dealing with typos in your source code. Today I’ll follow up with a simple recipe to automate this spell-checking process using GitHub Actions (GHA).1

Lately I’ve been adding the following GHA workflow to all of my OSS projects:

name: Spell Checking

on: [pull_request]

    name: Check spelling with codespell
    runs-on: ubuntu-latest
        python-version: [3.8]
      - uses: actions/checkout@v2
      - name: Set up Python $
        uses: actions/setup-python@v2
          python-version: $
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install codespell
          if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
      - name: Check spelling with codespell
        run: codespell --ignore-words=codespell.txt || exit 1
    name: Check spelling with misspell
    runs-on: ubuntu-latest
      - uses: actions/checkout@v2
      - name: Install
        run: wget -O - -q | sh -s -- -b .
      - name: Misspell
        run: ./misspell -error

There’s nothing fancy here. We’re just installing a couple of popular spell-checkers for code and we run them on everything within the Git repository. If they discover any problems the build will fail.

Just save the code above under .github/workflows/spell_checking.yml and you’re good to go. The workflow will get triggered for each subsequent pull request.

A couple of things to note:

  • This workflow uses both codespell and misspell. Using both might be an overkill for some of you. Personally, I like misspell more, as it’s super fast.
  • It’s a good idea to run both tools locally first and address any existing typos.
  • You may want to limit the checks only to files that were changed in the pull request.
  • You may want to specify a locale for misspell if you want to enforce a specific flavor of English (e.g. misspell -locale US).
  • This should probably be made a reusable workflow. I won’t be surprised if someone actually has created a public reusable workflow for spell-checking code already.

That’s all I have for you today. Big thanks to my fellow OSS hacker Koichi Ito, who came up with the idea of making spell-checking a CI step. In hindsight it seems like a very obvious thing to do, but it was always an afterthought for me. I’d be curious to hear how others are dealing with typos in their codebases.

  1. The outlined approach can easily be adapted for any other CI. 

-1:-- Automate Spell-checking in Your Projects with GitHub Actions (Post Bozhidar Batsov)--L0--C0--November 26, 2021 08:51 AM

Emacs TIL: Hide leading/trailing emphasis markers in Org mode

When you edit org files, sometimes you want to emphasize words like code or verbatim.

By default, Doom Emacs shows the leading or trailing marker characters like = or ~. So the org file looks funny.

Naturally, you want to hide the these characters, like an org-link.

This SO answer provides a solution: Toggle on org-hide-emphasis-markers


before tweaking


font screenshot

To further customize each emphasis face, you can tweak the org-emphasis-alist variable and pick or customize each face, like org-verbatim. Here is an example.

-1:-- Hide leading/trailing emphasis markers in Org mode (Post Junji Zhi)--L0--C0--November 26, 2021 12:18 AM

Jeremy Friesen: Adding Emacs Function for my Forem Pull Requests

Automating the Repetetive while also Learning a Bit More about My Editor

In I joined Forem as the lead engineer for the content experience team. I’ve been contributing to open source software for 9 years; Hello; I miss you but I promise I’m in a good place.

Coming from one open source community to another, I brought with me different workflows. I favor writing verbose commit messages. I like to use that as the text for my pull requests. The benefits are that commit messages travel with the code-base. I can use git annotate to help me understand the situation around a chunk of code.

But, in an open source community with over 600 contributors, the commit message as pull request strategy is inadequate. We could use git hooks to provide commit message templating, but that’s not enough for conversations around the pull request.

Forem provides a pull request template to guide contributors through all of the considerations that go into the pull request review and acceptance.

The template provides a nice pre-amble comment to help new contributors. Then provides clear sections and instructions for a contributor to fill out:

  • What type of Pull Request
  • Description
  • Related Tasks & Documents
  • QA Instructions, Screenshots, and Recordings
  • Accessibility Concerns
  • Added/updated Tests
  • How will this change be communicated? (A Forem Core Team only section)
  • Any post deployment tasks to complete
  • A GIF that Expresses How You Feel About this Contribution

As a new contributor to Forem, I love this guidance. And as I began reviewing other pull requests, I appreciated the structure even more.

My Current Pull Request Workflow

When I’m working on the code, I continue to write verbose commit messages. Then, when I’m ready, I push up my branch and push the button to create a pull request for the branch.

By default, Github prepends the last commit message to the text of the pull request template. I focus my browser into that text area and use the editWithEmacs.spoon to copy that text and paste it into a new Emacs buffer on my machine.

In that Emacs buffer, I then go about editing the pull request text.

When I’m done, I type Ctrl+c then Ctrl+c (e.g., C-c C-c in Emacs parlance) to copy the text from my Emacs buffer and paste it back into the browser’s text area. Magit and Org Mode use that key combination for confirmation of commands.

And I submit my pull request.

Automating My Workflow

Once I started editing these pull requests in Emacs, I started to see the clean-up work that I was regularly doing before I started filling out the checkboxes. And because I was now in my text editor, I chose to write a script to do that clean-up.

Without reading the elisp code, it:

  • Removes the comment preamble
  • It adds the last commit message as the description
  • It tidies up the comments of two sections

Below is the lisp code to do the tidying up:

(defun jnf/forem-tidy-pull-request ()
  "Perform some quick tidying of the Forem PR template."
  ;; Start from the beginning.

  ;; The text before the first HTML/Markdown
  ;; comments is the commit message.  Cut that
  ;; text...
  (search-forward "<!--")
  (kill-region 1 (- (point) 4))

  ;; ...and paste it inside the description
  ;; section.
   "## Description\n\n"
   (concat "## Description\n\n"
           (format "%s" (car kill-ring))))

  ;; We've moved point (e.g., the cursor) so let's
  ;; jump back to the beginning of the buffer.

  ;; Remove HTML/Markdown comments

  ;; Clean out the comments for QA instructions;
  ;; I'll write them, but the notes are
  ;; unnecessary.
   "QA Instructions, Screenshots, Recordings\\([^#]\\)*"
   "QA Instructions, Screenshots, Recordings\n\n")

  ;; Clean out accessibility concerns; I'll write
  ;; them, but the notes are unnecessary.
   "UI accessibility concerns?\\([^#]\\)*"
   "UI accessibility concerns?\n\n"))

Then comes the keyboard bindings to make this easier.

When copying from browser to Emacs, the editWithEmacs.spoon toggles on the hammerspoon-edit-minor-mode for the buffer. See the code for those details. The following code adds a new key binding Ctrl+c then t to the keyboard mappings.

  (kbd "C-c t")

Kind of nice. Load the content into an Emacs buffer, type Ctrl+c then t and I’m a few steps closer to completing my pull request.

What remains?

I wrote a script to build a pull request message from commit messages. Note, at my previous employer they chose to keep using—and keep choosing to use—the branch name master hence the code defaults to that.

I would like to better incorprate that conceptual script into my workflow.

And if I’m feeling up for the challenge, I’ll grab any Github links from the commit messages and add those to the related tasks and documents.


Since joining Forem, I’ve issued 32 pull requests. And as I started doing this task more, I started wondering, “How might I tweak my tooling to address some repetetive tasks?”

I let that question linger as I wrote several pull request messages in Emacs. And then, with a bit of time, I chose to spend a bit of time writing the above script. I don’t know how many pull requests I’ll need to write to “make up” for the time spent on the script.

But that is a lesser concern. I’m more concerned with getting comfortable understanding the interplay of the various systems I use and how I can mold them to assist in the tasks at hand.

When I start to create a pull request, I can quickly run the clean up task so that I can then focus on writing the pull request. In other words, I automated away a “distraction” so I could stay closer to the area of focus.

-1:-- Adding Emacs Function for my Forem Pull Requests (Post Jeremy Friesen ( 25, 2021 09:44 PM

Irreal: Proportional Fonts in the Mode Line

Lars Ingebrigtsen has an interesting post about proportional fonts in the Emacs mode line. His post shows the same mode line in both fixed and proportional fonts. There’s no arguing that the proportional fonts look better and that they allow for the display of more information on the mode line.

Still, the suggestion to move to proportional fonts is an old one and has always been controversial. There are some serious objections. For one, things like the point position are updated with every character typed and that can cause the mode line display to shift right or left.

Ingebrigtsen says that they’re running a month long test on Emacs Master in which proportional fonts on the mode line are enabled by default. They’ve installed a fix for the problems of things like the point position and the developers are hoping that that will address previous objections to using proportional fonts.

Regular readers know that I don’t care much about this sort of thing. All in all, I’m happy with a fixed width font mode line but I don’t find the idea of proportional fonts objectionable either. If you’re tracking Emacs Master, be sure to let the developers know what you think.

UPDATE [2021-11-26 Fri 13:15] Emacs 28 Master → Emacs Master.

-1:-- Proportional Fonts in the Mode Line (Post jcs)--L0--C0--November 25, 2021 06:53 PM

T. V. Raman: Emacspeak In The Age Of Cloud Computing

Emacspeak In The Age Of Cloud Computing

1. Executive Summary

Emacspeak has supported Cloud Computing since 1995, i.e., long before the term was invented. I have used Emacs with Emacspeak running on remote servers (called cloud-top in the rest of this article) since that time, with a local speech server on my client machine providing spoken feedback. The underlying ssh-based scripts have changed over time; this article documents what I have been using for the last 7 years or more. As with everything else Linux, you should not use this without understanding how it works. All of the relevant code is checked into GitHub, but if you use it without understanding, you are likely to get 2 for the price of 1😀.

2. The Basics

  1. Emacspeak produces all spoken and non-spoken feedback via a speech server — see Emacspeak: Beautiful Code for the detailed architecture overview.
  2. This server runs as a separate process and can either run locally i.e. on the machine running emacs; it can also run remotely, e.g. your laptop from which you login to your cloud-top.
  3. Note the local and remote terminology in the above — to Emacspeak, the machine where Emacs runs is the local machine, so your machine in the cloud is local to Emacspeak.
  4. Consequently, the machine from where you SSH to the cloud, a laptop, a Raspberry Pi, or in a future a tin-can that you use as a client is remote to emacspeak.

3. How It Works

  1. When you start Emacs with Emacspeak loaded, Emacs starts the speech-server as the first step in the emacspeak startup. normally this starts the local server for your prefered TTS engine.
  2. See the emacspeak manual for how this speech-server is determined.
  3. When running Emacspeak on a cloud-top, this local speech server is just a simple shell script that connects to a local port — by default 2222.
  4. When you connect to your cloud-top via SSH, you first reverse port forward port 2222 from the cloud-top back to your client. This causes data sent to port 2222 on the cloud-top by Emacs to show up on port 2222 on the local machine where your speech server is listening.
  5. With that reverse port forwarding in place and assuming that espeak is your TTS engine, running the speech-server cloud-espeak on the cloud-top connects back to your client to produce spoken output.
  6. For the previous step to work, something (or someone) needs to be listening on port 2222 on your client.
  7. So you need to start the relevant speech server on your client before you ssh to your cloud-top — in the case of espeak, this is ssh-espeak.

    See directory bash-utils in your emacspeak Git checkout for the relevant Bash scripts.

4. Workflow

Here is what the workflow looks like, again, use this only if you have read and understood the previous section. SeeBash Utils for the scripts mentioned below. Everything below assumes a Bash Shell.

On your cloud-top, specify the speech-server to use by running

export DTK_PROGRAM=cloud-espeak

You can put the above in your .bash_profile on your cloud-top.

On your client device, run

. <emacspeak_dir>/bash-utils/remote

This need be done only once per interactive shell.It defines bash functions remote and rtts.

Next, run Bash function remote defined in the script you just loaded.

remote  speech-server espeak

This does the following:

  1. Starts a local speech server for the TTS engine espeak.
  2. Opens an SSH session to the cloud-top
  3. Plays a musical chime (using sox) to cue completion.
  4. Depending on your SSH setup, you may or may not need to type your ssh password at this point; avoiding having to type a password is beyond the perview of this article, consult the SSH manual pages.
  5. Now, run Emacs on the cloud-top. Assuming that you have updated your Emacs initialization to load Emacspeak, this will get Emacspeak running on the cloud-top talking on your client.
  6. Note that typically, you should run something like screen on the cloud-top and run Emacs within that screen session; this will let you persist a running Emacs across multiple login/logout.

5. Experience On A Well-Configured Setup

On a well-configured setup, you typically need only do:

  1. Run the bash function that starts the local TTS server, and then connects to the cloud-top via SSH with reverse-port forwarding active.
  2. Assuming there is an Emacs session running under screen at the remote end, it'll start talking on your local client.
-1:-- Emacspeak In The Age Of Cloud Computing (Post T. V. Raman ( 25, 2021 03:09 PM

Emacs Redux: Redo Complex Command with Consult

This article is a quick follow-up on yesterday’s post on redoing complex commands. I’ve noticed today that the popular Emacs package consult offers a much more powerful version of the built-in repeat-complex-command command. The consult version is named consult-complex-command and has a couple of nice advantages:

  • candidate filtering
  • TAB-completion


Basically, it’s lot faster to find what you’re looking for. If you’re into consult I’d suggest just using its version in place of the built-in command:

(global-set-key [remap repeat-complex-command] #'consult-complex-command)

You can invoke consult-complex-command with C-x M-: or C-x ESC ESC.

That’s all I have for you today. The consult package is full of powerful versions of built-in Emacs commands, so you’ll do well to spend some time exploring it. I know I will!

-1:-- Redo Complex Command with Consult (Post Bozhidar Batsov)--L0--C0--November 25, 2021 11:15 AM

Lars Ingebrigtsen: The Most Controversial Change In Emacs History

Just a scant handful of decades after XEmacs introduced a mode line with proportional fonts, we’re thinking about doing the same in Emacs.

Here’s how the mode line looks (by default) in Emacs 28:

Here’s how we’re considering having it look (by default) in Emacs 29:

See? Huge difference. Huge.

The attractive thing about this change is that, well, it’s prettier, but it’s also more consistent with the other elements at the margins of the Emacs frame: The menus and the toolbar have used proportional fonts for a long time, so doing the same in the mode line might also be nice. And you can generally squeeze in more information when using proportional fonts, which is helpful if you’re jamming a lot of stuff into the mode line:

Changing this has been brought up a number of times over the years, but there’s been pushback because some of the elements in the mode line are pretty dynamic, and it’d suck if everything moved around. For instance, when displaying the column number in the mode line, it might be annoying to have the rest of the line shift to the left/right when moving the cursor around in the window.

So we’ve now added a new display spec (called ‘min-width’) today that you can slap around bits of text (and in the mode line) that ensures that the width never decreases beyond a certain point.

Perhaps that’ll make a difference in the level of resistance? I guess we’ll find out, because starting today, we’re doing a one month long test on “master”: This new mode line look is enabled by default now, and in a month we’ll evaluate based on feedback.

So give it a whirl for a few weeks, and vote on emacs-devel mailing list. (And report any glitches, of course. And suggestions for improvements are always welcome.)

-1:-- The Most Controversial Change In Emacs History (Post larsmagne23)--L0--C0--November 24, 2021 05:05 PM

T. V. Raman: Announcing Emacspeak 55.0 (CalmDog)

Announcing Emacspeak 55.0—CalmDog!

The enjoyment of one's tools is an essential ingredient of successful work. – Donald E. Knuth

1. For Immediate Release:

San Jose, CA, (Nov 24, 2021)

1.1. Emacspeak 55.0 (CalmDog) Unleashed! 🦮

— Making Accessible Computing Effortless!

Advancing Accessibility In The Age Of User-Aware Interfaces — Zero cost of Ownership makes priceless software Universally affordable!

Emacspeak Inc (NASDOG: ESPK) — announces immediate world-wide availability of Emacspeak 55.0 (CalmDog) 🦮 — a powerful audio desktop that leverages today's evolving Data, Social and Assistant-Oriented Internet cloud to enable working efficiently and effectively from anywhere!

2. Investors Note:

With several prominent tweeters expanding coverage of #emacspeak, NASDOG: ESPK has now been consistently trading over the social net at levels close to that once attained by DogCom high-fliers—and is trading at levels close to that achieved by once better known stocks in the tech sector.

3. What Is It?

Emacspeak is a fully functional audio desktop that provides complete eyes-free access to all major 32 and 64 bit operating environments. By seamlessly blending live access to all aspects of the Internet such as ubiquitous assistance, Web-surfing, blogging, remote software development, social computing and electronic messaging into the audio desktop, Emacspeak enables spoken access to local and remote information with a consistent and well-integrated user interface. A rich suite of task-oriented tools provides efficient speech-enabled access to the evolving assistant-oriented social Internet cloud.

4. Major Enhancements:

  1. Speech-enable Emacs Application Framework Ÿ
  2. Updated Soundscapes 🔊
  3. Updated Auditory Icons 🎧
  4. Updated Transient Support 𝥍
  5. Speech-Enabled CalibreDB 📚
  6. External Browsers From EWW 🕸

    — And a lot more than will fit this margin. … 🗞

Note: This version requires emacs-27.1 or later.

5. Establishing Liberty, Equality And Freedom:

Never a toy system, Emacspeak is voluntarily bundled with all major Linux distributions. Though designed to be modular, distributors have freely chosen to bundle the fully integrated system without any undue pressure—a documented success for the integrated innovation embodied by Emacspeak. As the system evolves, both upgrades and downgrades continue to be available at the same zero-cost to all users. The integrity of the Emacspeak codebase is ensured by the reliable and secure Linux platform and the underlying GIT versioning software used to develop and distribute the system.

Extensive studies have shown that thanks to these features, users consider Emacspeak to be absolutely priceless. Thanks to this wide-spread user demand, the present version remains free of cost as ever—it is being made available at the same zero-cost as previous releases.

At the same time, Emacspeak continues to innovate in the area of eyes-free Assistance and social interaction and carries forward the well-established Open Source tradition of introducing user interface features that eventually show up in luser environments.

On this theme, when once challenged by a proponent of a crash-prone but well-marketed mousetrap with the assertion "Emacs is a system from the 70's", the creator of Emacspeak evinced surprise at the unusual candor manifest in the assertion that it would take popular idiot-proven interfaces until the year 2070 to catch up to where the Emacspeak audio desktop is today. Industry experts welcomed this refreshing breath of Courage Certainty and Clarity (CCC) at a time when users are reeling from the Fear Uncertainty and Doubt (FUD) unleashed by complex software systems backed by even more convoluted press releases.

6. Independent Test Results:

Independent test results have proven that unlike some modern (and not so modern) software, Emacspeak can be safely uninstalled without adversely affecting the continued performance of the computer. These same tests also revealed that once uninstalled, the user stopped functioning altogether. Speaking with Aster Labrador, the creator of Emacspeak once pointed out that these results re-emphasize the user-centric design of Emacspeak; “It is the user — and not the computer– that stops functioning when Emacspeak is uninstalled!”.

6.1. Note from Aster,Bubbles and Tilden:

UnDoctored Videos Inc. is looking for volunteers to star in a video demonstrating such complete user failure.

7. Obtaining Emacspeak:

Emacspeak can be downloaded from GitHub — see you can visit Emacspeak on the WWW at You can subscribe to the emacspeak mailing list — The Emacspeak Blog is a good source for news about recent enhancements and how to use them.

The latest development snapshot of Emacspeak is always available at GitHub.

8. History:

  • Emacspeak 55.0 (CalmDog) attempts to be as calm as Tilden.
  • Emacspeak 54.0 (EZDog) learns to take it easy from Tilden.
  • Emacspeak 53.0 (EfficientDog) focuses on efficiency.
  • Emacspeak 52.0 (WorkAtHomeDog) makes working remotely a pleasurable experience.
  • Bigger and more powerful than any smart assistAnt, AssistDog provides

instant access to the most relevant information at all times.

  • Emacspeak 50.0 (SageDog) embraces the wisdom of stability as opposed to rapid change and the concomitant creation of bugs.🚭: Naturally Intelligent (NI)™ at how information is spoken, Emacspeak

is entirely free of Artificial Ingredients (AI)™.

  • Emacspeak 49.0 (WiseDog) leverages the wisdom gleaned from earlier releases to provide an enhanced auditory experience.
  • Emacspeak 48.0 (ServiceDog) builds on earlier releases to provide continued end-user value.
  • Emacspeak 47.0 (GentleDog) goes the next step in being helpful while letting users learn and grow.
  • Emacspeak 46.0 (HelpfulDog) heralds the coming of Smart Assistants.
  • Emacspeak 45.0 (IdealDog) is named in recognition of Emacs' excellent integration with various programming language environments — thanks to this, Emacspeak is the IDE of choice for eyes-free software engineering.
  • Emacspeak 44.0 continues the steady pace of innovation on the audio desktop.
  • Emacspeak 43.0 brings even more end-user efficiency by leveraging the ability to spatially place multiple audio streams to provide timely auditory feedback.
  • Emacspeak 42.0 while moving to GitHub from Google Code continues to innovate in the areas of auditory user interfaces and efficient, light-weight Internet access.
  • Emacspeak 41.0 continues to improve on the desire to provide not just equal, but superior access — technology when correctly implemented can significantly enhance the human ability.
  • Emacspeak 40.0 goes back to Web basics by enabling efficient access to large amounts of readable Web content.
  • Emacspeak 39.0 continues the Emacspeak tradition of increasing the breadth of user tasks that are covered without introducing unnecessary bloatware.
  • Emacspeak 38.0 is the latest in a series of award-winning releases from Emacspeak Inc.
  • Emacspeak 37.0 continues the tradition of delivering robust software as reflected by its code-name.
  • Emacspeak 36.0 enhances the audio desktop with many new tools including full EPub support — hence the name EPubDog.
  • Emacspeak 35.0 is all about teaching a new dog old tricks — and is aptly code-named HeadDog in on of our new Press/Analyst contact. emacspeak-34.0 (AKA Bubbles) established a new beach-head with respect to rapid task completion in an eyes-free environment.
  • Emacspeak-33.0 AKA StarDog brings unparalleled cloud access to the audio desktop.
  • Emacspeak 32.0 AKA LuckyDog continues to innovate via open technologies for better access.
  • Emacspeak 31.0 AKA TweetDog — adds tweeting to the Emacspeak desktop.
  • Emacspeak 30.0 AKA SocialDog brings the Social Web to the audio desktop—you cant but be social if you speak!
  • Emacspeak 29.0—AKAAbleDog—is a testament to the resilliance and innovation embodied by Open Source software—it would not exist without the thriving Emacs community that continues to ensure that Emacs remains one of the premier user environments despite perhaps also being one of the oldest.
  • Emacspeak 28.0—AKA PuppyDog—exemplifies the rapid pace of development evinced by Open Source software.
  • Emacspeak 27.0—AKA FastDog—is the latest in a sequence of upgrades that make previous releases obsolete and downgrades unnecessary.
  • Emacspeak 26—AKA LeadDog—continues the tradition of introducing innovative access solutions that are unfettered by the constraints inherent in traditional adaptive technologies.
  • Emacspeak 25 —AKA ActiveDog —re-activates open, unfettered access to online information.
  • Emacspeak-Alive —AKA LiveDog —enlivens open, unfettered information access with a series of live updates that once again demonstrate the power and agility of open source software development.
  • Emacspeak 23.0 — AKA Retriever—went the extra mile in fetching full access.
  • Emacspeak 22.0 —AKA GuideDog —helps users navigate the Web more effectively than ever before.
  • Emacspeak 21.0 —AKA PlayDog —continued the Emacspeak tradition of relying on enhanced productivity to liberate users.
  • Emacspeak-20.0 —AKA LeapDog —continues the long established GNU/Emacs tradition of integrated innovation to create a pleasurable computing environment for eyes-free interaction.
  • emacspeak-19.0 –AKA WorkDog– is designed to enhance user productivity at work and leisure.
  • Emacspeak-18.0 –code named GoodDog– continued the Emacspeak tradition of enhancing user productivity and thereby reducing total cost of ownership.
  • Emacspeak-17.0 –code named HappyDog– enhances user productivity by exploiting today's evolving WWW standards.
  • Emacspeak-16.0 –code named CleverDog– the follow-up to SmartDog– continued the tradition of working better, faster, smarter.
  • Emacspeak-15.0 –code named SmartDog–followed up on TopDog as the next in a continuing series of award-winning audio desktop releases from Emacspeak Inc.
  • Emacspeak-14.0 –code named TopDog–was

the first release of this millennium.

  • Emacspeak-13.0 –codenamed YellowLab– was the closing release of the 20th. century.
  • Emacspeak-12.0 –code named GoldenDog– began leveraging the evolving semantic WWW to provide task-oriented speech access to Webformation.
  • Emacspeak-11.0 –code named Aster– went the final step in making Linux a zero-cost Internet access solution for blind and visually impaired users.
  • Emacspeak-10.0 –(AKA Emacspeak-2000) code named WonderDog– continued the tradition of award-winning software releases designed to make eyes-free computing a productive and pleasurable experience.
  • Emacspeak-9.0 –(AKA Emacspeak 99) code named BlackLab– continued to innovate in the areas of speech interaction and interactive accessibility.
  • Emacspeak-8.0 –(AKA Emacspeak-98++) code named BlackDog– was a major upgrade to the speech output extension to Emacs.
  • Emacspeak-95 (code named Illinois) was released as OpenSource on the Internet in May 1995 as the first complete speech interface to UNIX workstations. The subsequent release, Emacspeak-96 (code named Egypt) made available in May 1996 provided significant enhancements to the interface. Emacspeak-97 (Tennessee) went further in providing a true audio desktop. Emacspeak-98 integrated Internetworking into all aspects of the audio desktop to provide the first fully interactive speech-enabled WebTop.

9. About Emacspeak:

Originally based at Cornell (NY) — —home to Auditory User Interfaces (AUI) on the WWW, Emacspeak is now maintained on GitHub — The system is mirrored world-wide by an international network of software archives and bundled voluntarily with all major Linux distributions. On Monday, April 12, 1999, Emacspeak became part of the Smithsonian's Permanent Research Collection on Information Technology at the Smithsonian's National Museum of American History.

The Emacspeak mailing list is archived at Emacspeak Mail Archive –the home of the Emacspeak mailing list– thanks to Greg Priest-Dorman, and provides a valuable knowledge base for new users.

10. Press/Analyst Contact: Tilden Labrador

Going forward, Tilden acknowledges his exclusive monopoly on setting the direction of the Emacspeak Audio Desktop (🦮) and promises to exercise this freedom to innovate and her resulting power responsibly (as before) in the interest of all dogs.

*About This Release:

Windows-Free (WF) is a favorite battle-cry of The League Against Forced Fenestration (LAFF). –see for details on the ill-effects of Forced Fenestration.

CopyWrite )C( Aster, Hubbell and Tilden Labrador. All Writes Reserved. HeadDog (DM), LiveDog (DM), GoldenDog (DM), BlackDog (DM) etc., are Registered Dogmarks of Aster, Hubbell and Tilden Labrador. All other dogs belong to their respective owners.

-1:-- Announcing Emacspeak 55.0 (CalmDog) (Post T. V. Raman ( 24, 2021 04:30 PM

Emacs Redux: Redo Complex Command

I don’t know about you, but from time to time I definitely have the need to re-run some Emacs command that takes user input (e.g. query-replace). For the purpose of this article let’s call such commands “complex” commands. Obviously we can just invoke the same command, provide again the input (directly or using some parameter history if available), but it would be nice if there was a faster way to do this.

As it’s usually the case with Emacs, such a way already exists - the built-in command repeat-complex-command. By default it’s bound to both C-x M-: and C-x M-ESC.1 When you invoke the command you’ll see in the minibuffer the last Emacs command you ran and you can use M-n and M-p to move forward and backward in the command history.

You’ll notice that the commands are listed as Emacs Lisp code that you can edit directly if needed. You’ll also notice there are no commands that don’t any parameters on the list. Imagine something like:

(describe-key '(("\272" . [134217786])))
(occur "emacs" nil)
(projectile-ag "emacs" nil)
(markdown-insert-gfm-code-block "emacs-lisp" nil)

This might also give you a hint as to why the keybinding C-x M-: was chosen - it’s pretty close to M-: (eval-expression), which allows you to run arbitrary Emacs Lisp code from the minibuffer.

When it comes to Emacs we’re all constantly learning. I didn’t know about this command until several days ago I saw it in a tweet shared by Mickey Petersen, a true Master of Emacs. Thanks for the tip, Mickey!

  1. Not exactly the most convenient keybindings, right? 

-1:-- Redo Complex Command (Post Bozhidar Batsov)--L0--C0--November 24, 2021 11:28 AM

Bozhidar Batsov: Emacs is a Lifestyle

Recently I came across this tweet about Emacs and its users:

Funny and true at the same time! I casually retweeted it and I immediately forgot about it. A bit later, however, I was mentioned in one response to the tweet that really caught my attention:

Configuring Emacs is more of a lifestyle choice than a task that one completes.

– Stephen A. Ramsey

I think that perfectly captures the spirit of Emacs and the nature of its (most devoted) users. I’d even go a bit farther and make the claim that (using) Emacs is essentially a lifestyle (choice).

After all, none of us were forced to use Emacs. None of us were forced to dedicate years of our lives to building the perfect Emacs configuration. None of us were forced to preach the gospel of the Church of Emacs. We do it all, because in Emacs we find the creative outlet that we’ve been always looking for. We do it, because Emacs gives us the choices that others don’t. We do it, because being pragmatic all the time is boring.

For us Emacs is much more than a mere text editor - it’s part of who we are. Emacs is a lifestyle. Emacs is our lifestyle!

-1:-- Emacs is a Lifestyle (Post Bozhidar Batsov ( 24, 2021 08:49 AM

Meta Redux: An Update on CIDER 1.2

When clj-refactor 3.0 was released, I promised you that the release of CIDER 1.2 wasn’t far behind. However, an entire month has passed since then and CIDER 1.2 is still brewing. Turned out there was more work to be done than I expected, that’s why I decided to provide a short progress update.

Several things contributed to the delay. Here’s a brief rundown in no particular order:

  • nREPL 0.9 was delayed a bit by some problems we’ve discovered with the new Unix socket transport. The problems have been addressed and I expect that we’ll finalize nREPL 0.9 in the next week or so.
  • Due to the nREPL issues mentioned above, we still haven’t added support for the new Unix socket transport to CIDER.
  • There’s some cleanup work that has to be done in Orchard with respect to switching from dynapath to enrich-classpath for automatically adding Java sources and Javadoc to the classpath. That cleanup is optional for this particular release, but I’d rather do it sooner rather than later.
  • I want us to support properly nbb in CIDER 1.2. This requires some changes to the ClojureScript bootstrap logic in CIDER, as nbb is a native Node.js implementation that works differently from all the ClojureScript REPLs we’re currently supporting (notably you don’t need to evaluate any code in a Clojure REPL to “upgrade” it to a ClojureScript REPL).
  • I still haven’t submitted CIDER and its dependencies to NonGNU ELPA, so that people would be able to install CIDER out-of-the-box on Emacs 28.
  • I’ve been crazy busy at work, which limited the amount of time I could allocate to CIDER and friends.

In light of everything listed above, right now I’m aiming to release CIDER 1.2 around Christmas. Note that the current CIDER snapshot is in a pretty good shape overall and you can upgrade to it without any concerns about the stability issues.

If you want to know more about the current state of affairs, please check out this meta ticket, which tracks all the remaining work. As usual any help with the outstanding tasks will be greatly appreciated!

To wrap up on a positive note - in the mean time we released clj-refactor 3.1 and 3.2 with a bunch of small improvements! We might be moving a bit too slow at times, but we’re always moving forward!

-1:-- An Update on CIDER 1.2 (Post Bozhidar Batsov)--L0--C0--November 24, 2021 08:00 AM

Gretzuni: FOSS as polyphonic, interrelational traces

It is on all of us to decide how it is that we are working with and using tech in 2021 as even the smallest decision has a cumulative effect. … Which ideology are we supporting through our software use/contributions and why?

-1:-- FOSS as polyphonic,  interrelational traces (Post Greta)--L0--C0--November 23, 2021 09:56 AM

Bozhidar Batsov: Small Improvements to the Blog

After switching (think) to Minimal Mistakes I’ve been doing some small improvements to the site’s structure and content. I thought it might be a good idea to summarize them here:

  • I’ve updated the About page. It now includes a lot more information about me and (think)’s background and mission.
  • I’ve moved the contact information from the About page to a dedicated page.
  • I’ve added a simple lunr-powered search. I should have done this a while ago, but Minimal Mistakes made this so easy that I finally had no excuse not to do it. It’s not as fancy as Algolia-powered search, but it mostly gets the job done.
  • I’ve replaced the old custom Archive and Tags pages, with the versions of those pages provided by Minimal Mistakes. Now they look much better as a result.
  • I’ve added dedicated Atom feeds for the main topics I’ve historically written about:
    • Ruby
    • Clojure
    • Emacs
    • Meta (I use this a replacement for “Misc”, so expect all sorts of disconnected articles here)
  • I’ve added a table of contents to many of my longer articles (here’s an example
  • I’ve been going over some of my old articles and I’ve fixed tags, broken links, typos, grammar and markup here and there.

I have to say that this has been a very fun process and Minimal Mistakes has been an absolute joy to use so far! Next step - finally learn how to use Jekyll’s collections and add something else besides articles to the site.

-1:-- Small Improvements to the Blog (Post Bozhidar Batsov ( 23, 2021 08:40 AM

Emacs TIL: Doom Emacs: How to fold code blocks

Doom Emacs has editor/fold module which makes folding code simple


  • Move cursor to the code block opening
  • M-x +fold/toggle or C-c C-f C-f

Demo (folding a large hash in ruby):

fold ruby code

-1:-- Doom Emacs: How to fold code blocks (Post Junji Zhi)--L0--C0--November 22, 2021 11:47 PM

Gretzuni: EmacsConf2021: A few talks I can't wait to watch

I won’t be including all of the talks I will be watching here but those that are aligned with topics I cover on this blog. I tried to keep this short – !

-1:-- EmacsConf2021: A few talks I can't wait to watch (Post Greta)--L0--C0--November 22, 2021 12:27 PM

Sacha Chua: 2021-11-22 Emacs news

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

-1:-- 2021-11-22 Emacs news (Post Sacha Chua)--L0--C0--November 22, 2021 12:00 AM

Andrea: Moldable Emacs: let's make English easy to query!

A prototype of querying English text!
-1:-- Moldable Emacs: let's make English easy to query! (Post)--L0--C0--November 22, 2021 12:00 AM

Gretzuni: EmacsConf2021: Emacs as design pattern learning

I will be giving a talk at this year’s EmacsConf2021 that was an indirect exercise in considering the new wave of programming that is upon us.

-1:-- EmacsConf2021: Emacs as design pattern learning (Post Greta)--L0--C0--November 21, 2021 07:23 PM

Irreal: Lisp at Kina

I haven’t talked about Common-Lisp on Irreal for a long time. That’s mostly because the majority of my recent Lisp programming has been in Elisp but I still love Common-Lisp and Scheme and am always happy when I find an interesting article about them. I particularly like articles that show how Lisp is being used to solve real world problems.

For a long time, the canonical example of this has been ITA Software, but there are others and azzamsa and his collaborators have a list. When he saw the list, Alex Nygren told them about his company Kina Knowledge that makes extensive use of Common-Lisp and its homegrown lisp, DLisp, that compiles to Javascript. That led to a nice blog post by vindarel that describes the Kina system and how Lisp fits into it.

You should read the post for the details but the TL;DR is that their technology stack is made up of Ruby/Rails, Javascript, Common-Lisp, and DLisp. Most of their front end is written in DLisp and is available to the end user. The back end is Common-Lisp that does much of the heavy lifting. And, as a bonus, Nygren uses Emacs for his Lisp coding and documentation. It makes sense; if you’re a Lisper, Emacs is a natural fit.

The post is well worth a read if you’re interested in how Lisp is being used today. There aren’t, I’m sure, enough Lisp jobs for everyone who wants one but they aren’t non-existent either. Paul Graham famously described Lisp as their secret weapon at Viaweb and related how they tried to prevent their competitors from finding out they were using it. Perhaps more companies will get the message and the number of Lisp jobs will increase.

-1:-- Lisp at Kina (Post jcs)--L0--C0--November 21, 2021 04:47 PM

yuri tricys: Emacs Conference Update 2021

Emacs Updates For those of you interested in Emacs, I've checked out a few of the annual Emacs conferences and they're usually pretty good. Lots of interesting speakers with typically new Emacs related perspectives. See poster below for details. Here's a link to the conference page: The organizer's are: Amin Bandali, Leo Vivier, and Sacha Chua. If you want to keep up everything in the Emacs world, I recommend following Sacha Chua's Blog.
-1:-- Emacs Conference Update 2021 (Post)--L0--C0--November 21, 2021 12:00 AM

Manuel Uberti: On Eglot and VC

I have been pretty busy since my last update here, but that does not mean I haven’t had the time to explore a couple of things for my everyday Emacs usage.

Lately I had to deal with some Java and some JavaScript. No fancy libraries on top of them, no languages built upon them, just plain, old Java and JavaScript. I took that as a chance to familiarize myself with LSP and especially with Eglot, one of the two (to my knowledge) packages that add LSP support to Emacs. Why Eglot and not lsp-mode? Simple: I like how Eglot leverages project.el and Flymake, tools I heavily rely on, and I also like how quickly it enabled me to type Java and JavaScript code.

(add-hook 'java-mode-hook #'eglot-ensure)
(add-hook 'js-mode-hook #'eglot-ensure)

Neat, huh?

Eglot works well with Company, Xref, and ElDoc, so coding in Java finally makes sense in Emacs. Granted, I haven’t used it on a big project and I am sure the likes of IntelliJ IDEA and Eclipse do wonders, but none of them has the editing capabilities or the openness to infinite customization that Emacs offers.

Another tool that entered my day-to-day computing is the built-in version-control system, or VC for short. My love for Magit is well-known, but on my way to a vanilla Emacs appreciation I thought I could give VC a try. It turns out most of the things I need to do with my Git-versioned projects can be done from vc-dir. This means that instead of C-x g for magit-status I have been using C-x p v for project-vc-dir. When it’s time to get my hands dirty with some advanced Git-fu, Magit is always next to me.

One thing should be obvious here: Magit is more powerful and feature rich than the built-in VC, so I do not intend to drop Magit as quickly I dropped Projectile and Flycheck. Why don’t I just use Magit, then, you ask. For the same reason I tried Eglot instead of installing Eclipse, I’d reply. Curiosity will not kill any cat in my house.

-1:-- On Eglot and VC (Post)--L0--C0--November 21, 2021 12:00 AM

Irreal: Git History for Selected Text

Here’s a nice tip for finding all the commits related to some selected text in Magit:

I haven’t tried this in anger but it seems as if it could be useful when trying to figure out how a bit of code has changed over time.

-1:-- Git History for Selected Text (Post jcs)--L0--C0--November 20, 2021 06:32 PM

Emacs TIL: Anki <-> Org

This post is about how to sync notes between Org and Anki manually.

Background: In an effort to consolidate all my notes into *.org files, I need to deal with the old Anki decks.

Luckily, Anki supports exporting notes into plaintext files.

Anki export

If you want to import the same file, you need an add-on to generate the Node ID for each note.

Make sure Node ID field is added in the deck setup:

make sure Node ID field is added

Sample exported txt file:

9162f8c6-4942-11ec-8423-acde48001122 front 1 updated back 1 updated 98699bac-4942-11ec-8423-acde48001122 front 2 updated back 2 updated

With this plaintext file, you can use whatever you are comfortable to convert them into your org format.

For example, if you are using Org-Roam, the first note can be converted to:

:ID:       9162f8c6-4942-11ec-8423-acde48001122
#+title: front 1 updated
* Front
front 1 updated
* Back
back 1 updated

After you are done editing on org, it is a matter of converting them back to the plaintext files and importing them into Anki again:

import into anki

In this way, you can manually sync notes between Org and Anki.

-1:-- Anki &lt;-&gt; Org (Post Junji Zhi)--L0--C0--November 19, 2021 02:31 PM

Protesilaos Stavrou: Emacs: mct version 0.3.0

Below are the release notes. If you have no idea what mct is, it is a very thin layer of interactivity on top of the default completion user interface. Watch the video demo of the initial release.

Version 0.3.0 on 2021-11-19

This entry describes the changes to Minibuffer and Completions in Tandem (mct) since the release of version 0.2.0 on 2021-11-12. There have been more than 40 commits since then. For further details, please consult the manual online: Or evaluate the following expression if you have the mct package installed:

(info "(mct) Top")

As this release is a continuation of version 0.2.0, the changelog for that version is also provided below (I released version 0.2.0 earlier than anticipated so that users could get a stable package on GNU ELPA). Here is a brief description of what has been achieved in 0.3.0.

MCT on Emacs 27

  • MCT now works on Emacs 27. This was not possible in the past because mct-mode was originally designed to operate with the one-column style of the completions-format, which was added in Emacs 28. To make everything behave intuitively, several parts of the code had to be abstracted and refactored (the changelog of version 0.2.0 (further below) covers everything not mentioned here).

  • The scenaria where the functionality was thoroughly tested involve all the available formats and cover commands that fulfil the following criteria:
    • Plain completion candidates, as in switch-to-buffer.
    • Dynamic completion like that of find-file.
    • Annotated candidates, as seen in describe-symbol for versions of Emacs 28 or higher.
    • Commands where candidates are grouped by heading, as done by various extensions of the consult package, such as consult-imenu.
    • Commands where no completion category is associated with them.
  • The only change which is visible to the user is the implementation of a bespoke overlay to highlight the current candidate. In previous versions, this was provided by the built-in hl-line-mode, though that does not work as intended with either the vertical or horizontal layouts of the completions-format as it covers the whole line instead of the candidate at point.

  • The highlight extends to the edge of the window when the one-column format is used for the completions-format (Emacs 28 or higher). In the other views it stretches from the beginning to the end of the completion candidate.

  • Thanks to Case Duckworth for the initial request and subsequent testing in issue 1:

Miscellaneous changes

  • There is a new command that is active in the minibuffer which allows to complete and exit immediately: C-RET (mct-complete-and-exit). This economises on key presses when all the user wants is to select the top-most candidate (or last highlighted one) without first switching to the Completions’ buffer and then confirming it from there (RET in the *Completions* buffer completes and exits directly).
  • The mct-mode does not get activated in contexts where (i) the minibuffer is involved but (ii) no completion takes place. For example, the eval-expression command (bound to M-: by default).

  • mct-mode no longer remaps the faces of the display-line-numbers-mode. This was a useful experiment from the early days of the code base, although it is bad practice for a user-facing package.

  • Various tweaks and refinements to the manual.

  • Retroactive introduction of a file and coverage of all noteworthy changes hitherto.

0.2.0 on 2021-11-12

This entry describes the changes to Minibuffer and Completions in Tandem (mct) since the release of version 0.1.0 on 2021-10-22. There have been 70 commits since then. For further details, please consult the manual online: Or evaluate the following expression if you have the mct package installed:

(info "(mct) Top")

Packaged version of MCT

mct is now available on the official GNU ELPA archive for users of Emacs version 28 or higher. One can install the package without any further configuration. The following commands shall suffice:

M-x package-refresh-contents
M-x package-install RET mct

Changes to the format and placement of the Completions

  • The user option mct-live-completion controls how and when the Completions’ buffer should be placed in a window and be updated live in response to user feedback. Copying from the doc string:

    mct-live-completion is a variable defined in ‘mct.el’.

    Its value is t

    Control auto-display and live-update of Completions’ buffer.

    When nil, the user has to manually request completions, using the regular activating commands. The Completions’ buffer is never updated live to match user input. Updating has to be handled manually. This is like the out-of-the-box minibuffer completion experience.

    When set to the value visible, the Completions’ buffer is live updated only if it is visible. The actual display of the completions is still handled manually. For this reason, the visible style does not read the mct-minimum-input, meaning that it will always try to live update the visible completions, regardless of input length.

    When non-nil (the default), the Completions’ buffer is automatically displayed once the mct-minimum-input is met and is hidden if the input drops below that threshold. While visible, the buffer is updated live to match the user input.

    Note that every function in the mct-completion-passlist ignores this option altogether. This means that every such command will always show the Completions’ buffer automatically and will always update its contents live. Same principle for every function declared in the mct-completion-blocklist, which will always disable both the automatic display and live updating of the Completions’ buffer.

  • As with all buffers, the placement of the *Completions* can be controlled with the display-buffer machinery. The default is to show the completions at the bottom of the frame, though users can easily move it to, say, the left side window. The doc string of the user option mct-display-buffer-action explains how to do so.
    • Thanks to Philip Kaludercic for the initial implementation in commit 436b24e (was sent via email as a patch).

    • Thanks to Kostadin Ninev for reporting a bug where the Completions’ buffer would proliferate during completion: It was fixed by Philip Kaludercic in commit 51c1e17.

  • MCT now supports all the available styles of the completions-format, whereas the original design was only meant to work with the value one-column, which was introduced in Emacs 28. The user option is mct-completions-format. If that variable is set with setq, the mct-mode has to be restarted manually for changes to take effect (setting the variable through customize-set-variable (and related) handles the mode reloading automatically).
    • Thanks to Philip Kaludercic for the patch in commit b392b0b.

    • Several changes were then made to ensure that the cyclic motions that move between the *Completions* and the minibuffer work intuitively in a grid view. In short: C-n, C-p or the down/up arrow keys, perform a vertical motion, while the left/right arrow keys move laterally. Prior to those changes, C-n or down arrow as well as C-p or up arrow, would perform a lateral motion as that is internally the meaning of the next/previous completion candidate.

    • The command mct-choose-completion-number was updated to throw a user error when a grid view is active. That is because it is designed to jump to a given line number, which only works as intended when there is only one candidate per line. (Perhaps a future release should overlay characters over candidates in the grid view to select them directly.)

  • The mct-mode no longer sets the completions-detailed variable. That is a matter of user preference. It is not integral to the functionality of MCT.

Group motions

  • Emacs 28 provides infrastructure for commands to group candidates based on their contents. These groups can have their own heading in the Completions’ buffer, as well as a separator. Overall, it makes things look more organised. The commands mct-next-completion-group and mct-previous-completion-group move between those headings. While in the *Completions* buffer, they are bound to M-n and M-p, respectively. Thanks to James Norman Vladimir Cash for the contribution in merge request 2:

Miscellaneous changes

  • The TAB key in the Completions’ buffer never exits the minibuffer (the command is mct-choose-completion-no-exit). Instead, it expands the current candidate in the minibuffer and switches focus to it. Before, this behaviour would only happen in find-file and related prompts, but consistency/predictability is better.

    [ By contrast, RET (mct-choose-completion-exit) in the Completions buffer always exits with the candidate at point. ]

    Note that in this context “exit” means to close the session and accept the current input.

  • There is a new heuristic to deal with commands that let bind the crm-separator (e.g. org-set-tags-command sets the separator to :). This is used to make M-RET (mct-choose-completion-dwim) in the Completions buffer work in all completing-read-multiple contexts. Thanks to James Norman Vladimir Cash for contributing the heuristic in merge request 1:

  • The aforementioned M-RET command used to have the same effect as RET when not in a completing-read-multiple prompt (“CRM prompt”). This has now been revised to behave like TAB instead (as described further above), which is consistent with the ordinary behaviour of M-RET in CRM prompts where it appends the candidate at point to the minibuffer, without exiting.

  • The check for display-line-numbers-mode tests whether it is bound, thus avoiding possible errors. Thanks to Philip Kaludercic for the patch in commit 6bd2457.

  • Made several improvements to doc strings and various snippets of code.

Updates to the manual

  • All of the aforementioned were documented, where appropriate.
  • A Makefile is now on offer, which is used to generate the and mct.texi files. Thanks to Philip Kaludercic for the patch in commit 295bac0.
  • A sample setup is available for mct as well as several built-in options pertaining to the minibuffer.
  • There are sections about third-party extensions as well as one that describes alternatives to MCT. Thanks to Manuel Uberti for the feedback in issue 5:
  • The “Acknowledgements” section includes the names of people who have contributed to the project in one way or another (code, ideas, user feedback, …).
-1:-- Emacs: mct version 0.3.0 (Post)--L0--C0--November 19, 2021 12:00 AM

Irreal: Bozhidar Batsov Revists “Why Emacs”

Ten years ago, Bozhidar Batsov wrote a post entitled Why Emacs. It was a short essay on why he used Emacs, what was good about it, and what its shortcomings were. Ten years later, Batsov, like most of us, is a different person doing a different job.

Back then he was a programmer, mostly concerned with writing code but also writing a blog, (think), that he also wrote in Emacs so he could be said to be using Emacs for most of his text editing needs. These days he’s moved into management and no longer spends much time coding except for his OSS projects and the majority of his prose is written in Slack and Google Docs.

Still, Batsov continues to love Emacs and be one of the most prominant evangelists for it. He’s just written a retrospective on his post, Why Emacs: Redux. A lot of things haven’t changed: Emacs (and Vim) are still the premier way of editing text and Emacs’ extensibility is still unrivaled and the thing that sets it apart.

On the other hand, Emacs has not stood still. It has more packages than ever, it has rudimentary multithreading, a builtin JSON parser, good support for LSP, and, of course, native compilation. Emacs is definitely not standing still.

All of that is true but for me the real virtue of Emacs is power. The power to efficiently edit text, the power to extend it in virtually any direction I want, and the power to make it a Lisp-Machine-like operating environment.

Take a look at both posts. They’re interesting and a reminder of why we love Emacs so much.

-1:-- Bozhidar Batsov Revists “Why Emacs” (Post jcs)--L0--C0--November 18, 2021 07:13 PM

Meta Redux: Meta Redux: Redux

I created Meta Redux a little over 3 years ago with the goal to start clean and write on topics that were meaningful to me. Today I want to examine how well did I do so far, therefore the extra meta title. And yeah, I’m well aware that I have some infatuation with the word “redux” - perhaps I just like revisiting things too much.

If you don’t remember the Meta Redux backstory, I’ll summarize it here quickly. Basically I had an older blog, that had went dormant around 2015 due to my frustration with Octopress, the tool I used to publish the blog. On top of this, as my original blog was my first attempt to write, I didn’t do well there. I wrote a lot of crappy articles early on, because I neither had anything interesting to share, nor was a skilled writer. I was somewhat embarrassed by this mess and I wanted to distance myself from it and get a fresh start. Also, I thought that starting a new blog would be easier than dealing with a migration away from Octopress. The idea to have a blog with a “cool/original” name was also appealing to me - after all most people never manage to remember my last name (Batsov, frequently misspelled as Bastov). That’s how Meta Redux was born on Oct 13th, 2018, my 34th birthday.1

In the next 3 years I wrote over a hundred article at Meta Redux, which is quite the achievement given that in the previous 3 years I had written a grand total of 3 articles. What’s even better is that I was really happy with the quality of my work. It’s not like a wrote some Peter Norvig-level work of art, but at least it pleased me. Objective achieved!

Still, I had this lingering feeling that I cheated a bit, by starting a new blog. After all, everything I’ve written in the past is still (a reflection/snapshot of) me, regardless of how I feel about it today. I also wanted a clearer focus for Meta Redux, despite its deliberately unfocused name. As I’m writing a lot here about programming and my OSS work, I felt that other topics I’d occasionally write on didn’t quite fit in (e.g. tutorials and musings on hardware and operating systems). Still, such topics have some value to me and potentially to some of my readers. So what do about them?

In the end of the day I’ve decided to revive “(think)”2 and use it to complement the topics I cover here. Basically, going forward I’ll limit myself here to programming (mostly Ruby and Clojure these days) and my OSS work (e.g. CIDER, RuboCop, etc), and everything else will go to (think). I’ve also removed some duplicated pages from Meta Redux (e.g. information about my talks and projects) and just redirected it to (think), for the sake of simplicity. This content originated there and I feel this is its true home.

The two blogs will also retain their different visual styles - I’ve vowed to keep Meta Redux as simple as possible, and to focus solely on the content here. With (think) I’ve taken some artistic liberties and I adopted a “more modern” theme, that seemed better suited for a person site that also doubles as a blog.3

I hope all this makes some sense. In hindsight probably it was a mistake to create a second blog in the first place, but I’m glad I did it. An experience you learn from is an experience worth having. Once again I was reminded that “less is more”.

  1. Knowing me, probably I was also going through all my life failures on that day and decided that I should address at least one of them. 

  2. Now (think) is also using a simple Jekyll setup. 

  3. See

-1:-- Meta Redux: Redux (Post Bozhidar Batsov)--L0--C0--November 18, 2021 09:26 AM

Protesilaos Stavrou: Modus themes 1.7.0 for GNU Emacs

I just released version 1.7.0 of the Modus themes. The release notes are reproduced below. For any questions pertaining to this publication, feel welcome to contact me.

I will now prepare the patch for the master branch on emacs.git (currently this corresponds to Emacs version 29). The modus-themes package in GNU ELPA fetches its contents from emacs.git, so expect an update to trickle down shortly after my patch is merged.

Modus themes version 1.7.0

By Protesilaos Stavrou on 2021-11-18

The present entry records the changes made to the project since the release of version 1.6.0 on 2021-09-29. There have been more than 60 commits since then.

Every modification pertaining to colour combinations referenced herein is implemented in accordance with the primary 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). Edits also account for colour-coding that is optimised for the needs of users with red-green colour deficiency (deuteranopia).

To access the URL of the manual visit this web page: Or read it from Emacs by evaluating this form:

(info "(modus-themes) Top")

The themes are built into Emacs version 28 (next stable release), and are available on GNU ELPA as well as other archives. This release is the first one that is included with Emacs 29, or else the master branch in emacs.git.

Customisation options

  • The modus-themes-no-mixed-fonts has been deprecated and replaced by the modus-themes-mixed-fonts. This is a breaking change for users who want to use “mixed fonts”: they must set the new variable to non-nil.

    As the name implies, the new variable changes the meaning of the feature to make it opt-in by default. This is consistent with the principle of least surprise, as users may not know why some fonts look different than others in certain cases.

    Thanks to Christian Tietze for clarifying the doc string of this new user option in merge request 51:

    For context, “mixed fonts” refers to a design where spacing-sensitive constructs, such as code blocks and Org tables, inherit from the fixed-pitch face to remain monospaced (and properly aligned) at all times. Depending on the user’s configurations, the fixed-pitch face may not use the typeface that the user expects.

    The manual provides information on how to set the desired fonts by editing the default, fixed-pitch, and variable-pitch faces.

  • The new modus-themes-mode-line-padding can be used to control the apparent padding of the mode line when the user option modus-themes-mode-line includes the padded property. The padding must be a positive integer (otherwise the code would be needlessly complex to guard against values that make the mode line look awkward, like anything lower than -3 or maybe even -2).

    Thanks to Guilherme Semente and Manuel Uberti for the feedback in issue 245:

    Note that the out-of-the-box style of the themes has a padding of 1 (technically a :line-width of 1 for the :box attribute), whereas the default style of Emacs has it at -1. This is a design choice to avoid an overlap between the outer boundaries of a font’s glyphs and the borders of the mode line, when using certain common typefaces at various point sizes. Such an overlap can hinder readability.

    The manual contains a new Do-It-Yourself (DIY) section with detailed code samples on how to apply a negative value.

  • The new modus-themes-intense-markup option can be set to non-nil to make constructs such as inline code and verbatim text more colourful. This has a general utility, though its consideration was prompted by a phenomenon reported by Stefan Kangas in issue 238 where the overlay of the hl-line-face overrides the subtle background these constructs use and can thus make them virtually indistinguishable from ordinary text:

    Such is the standard behaviour of hl-line-mode and there is nothing a theme can (or rather “should”) do about it. Thanks to Stefan Kangas for the feedback.

  • The modus-themes-headings option can now accept and apply an exact font weight such as semibold or light. (The list of available weights is the value of the modus-themes--heading-weights internal variable.) This supersedes the now-deprecated no-bold property: no-bold is henceforth understood as the presence of a regular weight.

    Recall that this user option is an alist and can be used to target heading levels individually, which further reinforces the utility of this new property.

    Thanks to Christian Tietze for suggesting this idea in issue 248: And thanks to Daniel Mendler for refining its implementation in commit 54bfd62, which was sent as a patch file (yes, we accept those and I actually prefer them over a web app’s UI).

  • The modus-themes-org-agenda has seen improvements to its event key (this is an alist that has multiple keys). It now accepts a varied property which differentiates between (i) plain timestamp entries and (ii) entries that are generated from either the diary or a symbolic expression. The varied property combines with the other available properties to particularise their effects. Consult the doc string or the manual for the technicalities.

    Thanks to Gustavo Barros for the detailed commentary in issue 241:

  • The modus-themes-lang-checkers now accepts a faint property. This has the effect of toning down the colours in use. By default, the only colour is that of the underline, though more can be added by combining the properties accepted by this user option. Consult its doc string or the manual for further details.

    Thanks to Morgan Smith for suggesting the idea in issue 239:

Add support for new packages or face groups

Changes to existing faces or face groups

  • Added support for the new Org agenda faces that improve the contextuality of various views. We implemented those upstream for Org version 9.5 in close cooperation with Gustavo Barros. Thanks to Gustavo for the detailed feedback in issue 241: The thread about the patch upstream:

  • Refined Org agenda date faces in the interest of consistency and in accordance with the aforementioned change. Thanks again to Gustavo Barros for the discussion in issue 241.

  • Applied the shadow face more consistently across all contexts where only a subtle foreground value is expected. This design choice makes it possible for users to manually edit the foreground colour of shadow to something even more subtle than the fg-alt palette variable we use, which maps to a gray colour (e.g. they could use “gray50”).

  • Implemented a subtle background colour to the widget-inactive face. This makes it easier to discern inactive buttons, checkboxes, and the like, in contexts such as the Customize User Interface. Thanks to Stefan Kangas for the feedback in issue 242:

  • Tweaked file-name-shadow to also use italics (inherit from the italic face) in order to be more easy to distinguish it from ordinary text in the minibuffer.

    Recall that the manual documents the meaning of inheriting from the bold and italic faces instead of hardcoding a bold weight and an italic slant, respectively. In short: users can change the weight to what they want (e.g. semibold) and/or use distinct font families.

  • Amplified the style of Version Control (VC) warnings and errors to let them draw more attention to themselves (because these indicators need to be acted upon).

  • Recoloured the custom-group-tag face to make it fit better in its context and be consistent with the rest of the themes’ established patterns.

  • Made marks for selection in Dired, Ibuffer, and related, conform with the modus-themes-success-deuteranopia option. This means that they use blue colours when the option is non-nil, instead of their default shades of green.

  • Adjusted the box width of key bindings for Emacs 28 or higher. They should no longer cause any alignment issues. This style is now used throughout the themes, including in transient views (e.g. Magit) which were the exception before. Thanks to Manuel Uberti and Kevin Fleming for the feedback in issue 232:


  • Wrote a brief description of every user option in the manual. Also covered its type, as in boolean, alist, et cetera.

  • Corrected the mode line border width for one combination of properties in the modus-themes-mode-line option. This should now have the same height as all others:

    (setq modus-themes-mode-line '(accented borderless))
  • Ensured that mode line attributes would not be set to nil, but kept at an unspecified value instead, where relevant. This avoids problems with [faulty] code that unconditionally depends on something that does not exist, as in the following while :box is nil:

    (face-attribute 'mode-line :box)
  • Expanded, reworded, or otherwise improved the manual, based on the aforementioned.

Thanks once again to everyone involved!

-1:-- Modus themes 1.7.0 for GNU Emacs (Post)--L0--C0--November 18, 2021 12:00 AM

Irreal: Plain Org

For us Emacers, one of the longstanding shortcomings of iOS and, to a lesser extent, the Android ecosystem is the lack of an Emacs app. There are several Org-mode centered apps that allow you to perform various Org functions on your phone and sync the results with your computer through the cloud.

Álvaro Ramírez has another offering in this space. His Plain Org app provides a nice interface to Org’s task lists on your iPhone. Take a look at his post to see some animated Gifs of the app in action.

Until we finally get a native Emacs on iOS, apps like Plain Org will get us by. In the mean time, having a decent Org app is a boon. Most of what I want to do on my phone that involves Emacs involves some sort of Org file so having a good Org implementation that syncs back to my computer’s Org file is great.

-1:-- Plain Org (Post jcs)--L0--C0--November 16, 2021 07:50 PM

Bozhidar Batsov: Why Emacs: Redux


  1. brought back; resurgent:
    the Victorian era redux.

A decade ago, I wrote an article titled Why Emacs?. I came across the article a few days ago and I felt that given its “anniversary” it’d be nice to revisit it.

2011 was an interesting year for me. It was the year in which I adopted Jekyll for this blog, which resulted in my most productive year in terms of articles I wrote. It was also the year which marked the birth of my first OSS projects - Projectile and Emacs Prelude. It was also the final year of my career as an (extra)ordinary programmer.1 Emacs was a huge part of my life back then, and the “Why Emacs?” article was an attempt to share my passion for it with the world.

Fast-forward to the future and my life is very different today. The only programming I do these days is on my OSS projects, but I happen to have a lot of those. On the job most of the typing I do happens in Slack and Google Docs. My views on programming are very different from what they were back in 2011. One thing hasn’t changed though - I still love Emacs and I’m quite passionate about it.

I still write short articles about Emacs over at I still try different Emacs packages from time to time, and try to improve my workflow and my configuration. As I got older I developed a lot of appreciation for the “less is more” mindset and I’m using significantly fewer Emacs packages than before. In particular I stopped using Emacs for things like email, rss, chat, twitter, etc. I’m digressing…

My main aim today is to share how I’d make the case for Emacs today. You’ll notice that in the original article I spent a lot of time focusing on technicalities:

  • editing experience
  • overall feature set (mostly how Emacs compares to popular IDEs)
  • resource utilization

They are important, of course, but they are not the most important thing.

I also made some wild claim that using IDEs impairs your thinking. Clearly I was around peak Emacs zealotry back then! Today we have even more IDE features in Emacs and I think that’s a good thing. In the end of the day Emacs has never been about enforcing one particular workflow - quite the contrary. Emacs is all about giving you choices!

Lisp isn’t a language, it’s a building material.

– Ward Cunningham

Emacs is not really an editor either! I believe that Emacs is the ultimate editor building material. The out-of-the-box experience is kind of basic and somewhat weird, but I don’t think that anyone should be using Emacs like this. You take this simple foundation, you shape and mold it to your taste and preferences and you end up with the best possible editor for you and you alone. That’s the reason why you should consider using Emacs.

Of course, one can make pretty much the same argument for our arch rival vim, and perhaps even for the modern king of editors VS Code. I’ve always liked vim and can’t say anything bad about it, other than I still don’t like Vimscript. For me, personally, the ability to extend Emacs easily with Emacs Lisp remains its number one advantage over vim.2 There’s also the fact that you can re-create much of the vim experience with Emacs, but you’ll be hard pressed to re-create the Emacs experience in vim.

For all the good things that VS Code has brought to the table (e.g. LSP), I’m still somewhat skeptical about it in the long run. I don’t like open-source projects that are de-facto owned by one company. There’s always the conflict of interest between the company’s agenda and the needs of its users, and we know that the interests of the company usually come first.

I’ve also seen plenty of new editors and IDEs rise and fall in the past 20 years - Komodo, TextMate, Sublime Text, Atom, Eclipse, etc. Emacs and vim are the only editors that stood the test of time, and I have a feeling they will be with us for decades to come. This means that an investment in them will be likely paying you dividends much longer than an investment in a newer editor or IDE.

I’ll not go into details about the level of customization one can achieve in Emacs, as there are endless possibilities at every conceivable level. Besides thousands of third-party packages and the numerous configuration options (defcustoms) for anything and everything, every long-time Emacs user would have a bunch of custom Emacs commands that are unique to their use-cases and their way of working. The various Emacs distributions that exist today give you a different starting point on which to build upon. I like to think of them as different flavors of building materials, or foundations if you will. Spacemacs, one of the most popular Emacs distributions, has famously proven that you can build a rather faithful version of vim with Emacs.

On a more practical note I’ll also mention that Emacs has improved a lot since the time of my original article. Here are a few highlights:

  • Today we have more great Emacs packages than ever. I blame the rise of GitHub and MELPA for that. The old maxim “Emacs has a mode for it!” is truer than ever.
  • Emacs’s internal APIs are much more powerful than before. One can see that Clojure certainly influenced a few of them (e.g. if-let, thread-first, seq.el, map.el, etc).
  • Emacs now supports a limited form of concurrency (introduced in Emacs 26).
  • Emacs 27 started shipping a built-in JSON parser.
  • Emacs has good support for LSP, which allows us to harvest the efforts of a lot of people for free. The gap between Emacs and VS Code and IDEs is a lot narrower than it used to be.
  • Emacs 28 will bring massive performance gains with native compilation.
  • Emacs has fantastic support for programming in Clojure.3 I think the popularity of Clojure and the fact that Emacs was the only editor to support it well early on gave Emacs a massive boost around the time of my original article.
  • Emacs 29 will bring us proper support for emojis!

And that’s only the tip of the iceberg. Emacs is definitely not standing still and both the core and the third-party package ecosystem are constantly evolving and getting better. It’s safe to say that Emacs is no sinking ship, regardless of its modest usage compared to the likes of vim and VS Code.

So, why should you try Emacs in 2021?

  • You’re a curious person and a constant tinkerer who likes playing with vintage software. You happen to have a lot of extra time at home on your hands because of the pandemic and you want to make the best of it.
  • You want to experience life outside the mainstream.
  • You’ve always wanted to learn a bit of Lisp.
  • You want to build an editor that’s uniquely tailored to your needs and preferences.

Beware - Emacs is highly addictive and it might easily consume years of your life! I guess I’ve spent just as much time on Emacs projects as I did on refining my Emacs configuration.

So, we’re almost at the end. There’s just one more thing to do at this point - repeat after me the following chant4 3 times:

Emacs is power!

Emacs is magic!

Emacs is fun!

Emacs is forever!

You’re now ready to begin your life-long journey to Emacs mastery. Meta-x forever! In parentheses we trust!

P.S. I’m including here the discussion threads for the article on:

  1. Or an individual contributor (IC), as this is known in some companies. 

  2. You know me - I love Lisps! 

  3. Just google for CIDER. :-) 

  4. If you need some inspiration just watch the first 30 seconds of this video

-1:-- Why Emacs: Redux (Post Bozhidar Batsov ( 16, 2021 08:20 AM

Irreal: Hacking y-or-n-p

Marcin Borkowski (mbork) has a short post on how to make y-or-n-p return t when the user types Return. Check his post for the details but the TL;DR is that he temporarily extends the y-or-n-p keymap to have Return return as if y had been pressed.

It’s a fairly unique requirement but his approach works for other use cases where we want to add or change a key to an existing keymap. If you have such a need, take a look at mbork’s post.

As an aside, I should mention that mbork’s new book is finished and available. I read a draft of his early chapters and thought it was well done. Take a look if you’re interested in Emacs books.

-1:-- Hacking y-or-n-p (Post jcs)--L0--C0--November 15, 2021 05:39 PM

Bozhidar Batsov: .net Forever

Let’s talk a bit about .net. No, not Microsoft’s .NET, but the other .net - one of the original top-level internet domains. Given how popular .com has become, I find it really strange that .net failed to reach such prominence. Even .org is more popular than .net!

Statistic: Most popular top-level domains worldwide as of April 2021 | Statista

That’s quite disappointing, as I think that historically .net was the best domain for personal sites, for various reasons:

  • .com used to stand for “commerce”, so it’s a bit weird to be using such a domain for a personal site
  • .org used to stand for a (non-profit) organization, so it’s extra weird to use such a domain for a personal site
  • .net stands for “network”, which for personal sites I always interpreted as “my place on the (Inter)net”
  • a lot of good names are still available for .net (compared to .com at least), as the domain is not super popular

Of course, today we have a lot more top-level domain options to choose from:

  • .info, the first additional domain, that never took off
  • a ton of country domains that can result is some cool looking domain names (e.g.
  • all the recent additions like .blog, .site, .name, etc

Still, I like the appeal of the original domains as they are all:

  • cheap (usually around $10/year, while some “modern” domains go as high as $35/year)
  • short (I prefer typing .net or .com compared to .engineer)
  • widely known and recognized. I don’t know about you, but I’m still a bit surprised when I see sites using the newer “more exotic” domain names.

And of the originals, .net has the most appeal for me, at least when it comes to personal sites/blogs/etc.

Obviously, this wasn’t always the case - after all this site uses the domain, and I own domains like and Let’s just say that back then I didn’t really think about the semantics of domain names that much. By the way, I do own as well, and I actually use it for my personal email address.1 I would have changed the domain for this site as well, if it was easier to setup redirects on GitHub Pages. Anyways, that’s not a big deal for me.

I guess the original domains have long lost their original semantics. I guess search engines tilted the scales in favor of .com (and .org to some extent). Still, there’s always some meaning behind a name and the best names tend to have a strong bond to that meaning. Naming is hard, but it’s also extremely rewarding once you get it right. I hope I’ve managed to spark your interest in .net and that over time you’ll grow to love and cherish it as I do. .net forever!

  1. Now the shorthand for my email address is BBN, rather than BBC. That’s a big win! 

-1:-- .net Forever (Post Bozhidar Batsov ( 15, 2021 10:08 AM

Sacha Chua: 2021-11-15 Emacs news

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

-1:-- 2021-11-15 Emacs news (Post Sacha Chua)--L0--C0--November 15, 2021 12:00 AM

Irreal: Editing macOS Text Fields with Emacs

If you’re like me, you hate dealing with text outside of Emacs. Even those of us who spend as much time as we can inside Emacs have to interact with other applications. In my case, that’s mostly Safari. The problem with Safari is that its architecture doesn’t allow extensions that will call Emacs to edit text fields the way, say, Firefox does.

MacOS, of course, recognizes many of the Emacs keybindings but you can do much better. For many years, I’ve used the operating system’s ability to assign keys to editing functions to install a fairly comprehensive set of Emacs editing keybindings but while that helps with muscle memory, it’s not really like editing with Emacs. I’ve long wished for a way of popping into Emacs to edit the text fields from other apps.

Now, happily, my wish has been answered. Take a look at this video by dmgerman that demonstrates his Edit with emacs Everywhere package. It provides just what you’d want: if you’re in any text field in any Mac application, you can press a key sequence to put up an Emacs buffer in which you can edit the text in the field and then return the edited text to the calling app. The important thing here is that you’re not just using Emacs keybindings but using Emacs itself with all its power. Perfect!

The package depends on Hammerspoon to mediate with the OS. It’s easy to install and, of course, is more generally useful but even if it weren’t, giving us the ability to edit all text fields with Emacs is worth the price of admission.

-1:-- Editing macOS Text Fields with Emacs (Post jcs)--L0--C0--November 14, 2021 05:29 PM

Bozhidar Batsov: Your Name is Your Brand

You never get a second chance to make a first impression.

Your name is your brand. This may sound like a cliche, but it’s true. That’s why it’s a very good idea to make sure that when people search for you online the results they’ll see first are the results you want them to see - e.g. a nice personal site, a solid LinkedIn profile, some videos of you presenting at various conferences, etc.

I think everyone will agree that’s preferable to finding instead some goofy/embarrassing/sloppy content about you.1 I guess all of us have some of it, and that’s okay, as long as it’s not dominating our online “brand”. Online anonymity is another option you can explore, but this will likely cost you all sorts of lost opportunities, so I wouldn’t recommend going in this direction. After all this effectively means that you don’t have an online “brand”.

You might be wondering where am I going with all of this. As usual - there’s a story behind the article. I recently Googled my name and I noticed that the first matches people get about me are:

Not too bad, given my 23 years of roaming the Internet, but still a bit disappointing, as I would have preferred for my personal sites to have ranked a bit higher.2 At any rate - this search gave me a clear idea of what people come across when they look for “Bozhidar Batsov/bbatsov”, so now I know where should I focus my efforts if I want to build a strong personal brand. I search for myself every few months and I would recommend to everyone to do the same from time to time. Lately I’ve also been spending a lot time on updating and cleaning up (think) and Meta Redux, which made me ponder on the topic of personal brand even more.

So, how do you build a good online brand? In general it seems prudent to me that everyone should:

  • have some (simple) personal site
  • have a clean and up-to-date LinkedIn profile/public resume (especially if you’re looking for better gigs)

Why so? Well, this ensures you’re associated online with something other than your Facebook/Instagram accounts. Something you’ve crafted carefully and optimized for public consumption. You can obviously have a lot more online presence if you wish to - e.g. I like writing, so I have several blogs. If you don’t like writing there’s no need to force yourself to maintain a blog.

Here are a few guidelines for a good personal site:

  • focus on the content, not the visuals3
  • less (good) content is better than lots of (any) crappy content
  • use a custom domain for your site, ideally something with your name in it (e.g. or in my case) - remember your name is your brand
  • highlight there everything you think reflects the brand you’re aiming for (background, work, causes you’re passionate about, hobbies, life goals, etc)
  • keep the site up-to-date - a broken or outdated site may reflect poorly on you

If you’re working in tech like me, and you’ve worked on some interesting OSS/hobby projects you might want to highlight those as well. If you’re working in another industry - I guess you know way better than me what to highlight.

All of these guidelines sound pretty basic, but it took me a few years to discover them organically myself. Much of my earlier articles here are so bad, that I’d happily delete them, but I keep them around to remind myself of the lessons I’ve learned and the experience I’ve gained. I don’t like LinkedIn much, so for many years my profile there was almost empty, but knowing that’s the first result many people get about me, I consider ignoring it a mistake. It’s not about getting more job offers, it’s about people finding something meaningful attached to my name.

When it comes to writing I strongly prefer to publish my articles on my own sites, instead of 3rd party services like Medium,, platforms that pay external authors for content and so on. Anything (meaningful) I wrote is a reflection of myself, so I’d rather it be closely associated with my name and my brand. That’s another argument in favor of picking domains with your name in it, instead of cool domains like Still, the content matters much more than the domain under which it’s published. There’s no substitute for good content.

That’s all I have for you today. A personal brand has many aspects, and the Internet is just one of them. There’s also the brand you have built in your community, on your job, etc. Those, however, are outside the scope of today’s short post on the subject. My thoughts were a bit messier than usual, but I hope I managed to get the message across. Now go create a great personal brand for yourselves!

  1. E.g. a video of me practicing for karaoke some 15 years ago! You’ll have to look very hard to find this one, though. 

  2. Level-up my SEO skills. 

  3. Unless the visuals are the content (e.g. you’re an artist or a designer). In general good visuals never hurt, but the content is king. 

-1:-- Your Name is Your Brand (Post Bozhidar Batsov ( 14, 2021 04:43 PM