Protesilaos Stavrou: Coding blog Coding blog https://protesilaos.com/codelog Mon, 16 Mar 2026 05:51:23 +0000 Computing in freedom with GNU Emacs A holistic introduction to Emacs: how useful it is and how it champions free software. Fri, 13 Mar 2026 00:00:00 +0000 https://protesilaos.com/codelog/2026-03-13-computing-in-freedom-with-gnu-emacs/ https://protesilaos.com/codelog/2026-03-13-computing-in-freedom-with-gnu-emacs/ Raw link: https://www.youtube.com/watch?v=M6ZHDJeG-dI

This is a holistic introduction to Emacs: how useful it is and how it champions free software. It is a modified version of the talk I did for the “FLOSS @ Oxford” event, organised by people at the University of Oxford. This is the page I wrote about that event: https://protesilaos.com/codelog/2026-03-12-my-emacs-talk-floss-oxford/.


Table of Contents

  1. This is a holistic introduction to Emacs
  2. Emacs as a capable text editor
  3. Support for Unicode
  4. Include several fonts on the same page
  5. Emacs can display graphics alongside text
  6. Emacs is an extensible text editor
  7. Extending Emacs creates a community
  8. The extensibility of Emacs happens live
  9. My view without the “presentation mode”
  10. Emacs puts you in control of your computing
  11. Your control extends to all workflows
  12. For an integrated computing environment
  13. Many apps do not combine nicely
  14. Emacs makes your workflow consistent
  15. Integrated computing in practice
  16. Emacs makes integration easier
  17. Integration gives you emergent properties
  18. This is plain text that works like a slideshow
  19. Consistency facilitates productivity
  20. Consistency remove the cognitive burden
  21. The consistency of Emacs in action
  22. Use Emacs Lisp to configure everything
  23. Learning Emacs Lisp improves the experience
  24. Emacs embodies software freedom
  25. The freedom of Emacs helps with learning
  26. Emacs is not only for programmers
  27. You benefit from all the Emacs extensions
  28. Some powerful extensions are built-in
  29. The documentation culture of Emacs
  30. Most packages have high quality manuals
  31. Emacs has a steep learning curve
  32. Do not skip the manuals
  33. Adjust your expectations
  34. Why it is worth learning how to use Emacs
  35. The initial effort pays off long-term
  36. Good luck and have fun!

Hello everyone! My name is Protesilaos, also known as “Prot”.

This presentation is a modified version of the talk I gave last night at the FLOSS @ Oxford event: https://ox.ogeer.org/event/computing-in-freedom-with-gnu-emacs-protesilaos-stavrou.

It was an event organised by people from the University of Oxford. I thank them for giving me the opportunity to participate in their programme.

I want to have this modified version here for people who do not read my website. They may not be aware that I talked at this Oxford event.

Having the video on this platform means that everyone can benefit from it.

1 This is a holistic introduction to Emacs

In this presentation I will talk to you about GNU Emacs, or simply, “Emacs”. Emacs is a program you run on your computer. I am using it right now for this presentation.

Emacs is free or libre software. It allows you to read all of its source code, to modify it, and to share it with your customisations. Thus you contribute to—and benefit from—a community of welcoming Emacs users.

I will tell you what all this means in practice and how you can improve your computing experience by switching to Emacs.

2 Emacs as a capable text editor

When you first start using Emacs, it feels like a regular text editor program.

You move the cursor around and edit text. Nothing obviously impressive out-of-the-box.

As a text editor, Emacs is highly capable. It has all sorts of keyboard shortcuts that let you efficiently operate on text.

You can control Emacs without relying on the mouse, if you want.

3 Support for Unicode

Emacs supports the Unicode standard, which is essential for inclusivity of peoples.

The world’s scripts can be expressed in Emacs. I am a native Greek speaker.

I can use functionality that is built into Emacs to switch to the Greek alphabet in order to write something, such as to say «καλησπέρα», which means “good evening”.

I can even spell out “Dao De Jing” (道德经), which is the title of a book from ancient China.

Plus emoji: 🦚🦬🐉.

4 Include several fonts on the same page

The multitude of scripts can be present in the same document.

This is an advantage for multilingual people like myself or those who do research that involves many natural languages.

Emacs can combine several fonts in the same page as well as different colours.

Each fonts can have its own attributes, such as for its relative size and typographic intensity.

Same idea for colours.

On my screen right now, I am already combining two different font styles: that of the heading and the body of the text.

5 Emacs can display graphics alongside text

Emacs does not limit you to a text-only interface. It can also display images and PDF documents. Below I have a link to an image file. I will now type a keyboard shortcut to reveal this image. And I will do it again to hide it.

This, by the way, is a spot somewhere in my mountains.

6 Emacs is an extensible text editor

Although you can benefit from using Emacs as a generic text editor, what really appeals to people like me is the option to extend Emacs.

“Extend” here means to introduce new functionality; functionality that is not available in the default program you install on your computer.

These extensions are written in the same programming language as most of Emacs. It is a programming language called “Emacs Lisp” or “Elisp”.

You can extend Emacs on your own, by writing some program in Elisp, or you can download an existing extension that the community has made available.

7 Extending Emacs creates a community

For example, when I create a new extension for Emacs, I publish it under the terms of a free software license—the same terms that Emacs uses.

Others can then download my extension and use it as they prefer. If they want, they can make their own modifications on top, which may introduce other extensions that I had not thought of in my original implementation.

And if those users follow my example, then I can also benefit from their additions once they publish them.

As such, there exists a community of enthusiastic users of Emacs who care about sharing their works with the rest of the world.

8 The extensibility of Emacs happens live

Users can extend Emacs by running some Emacs Lisp program. Such a program can be as short as a single line. Or it can be as long as it needs to be. It does not matter.

Users run the program and Emacs immediately does what the program renders possible.

For example, I am doing this presentation inside of Emacs. But Emacs does not have a “presentation mode” built into it. I thus developed my own extension which empowers me to do what I am doing right now.

Let me toggle off my presentation mode to show you what I mean.

9 My view without the “presentation mode”

Notice that the display has changed.My main font is monospaced now.

The headings are smaller than they were before: they are the same size as the rest of the text. There is no number next to the heading anymore.

Then, there is a bar at the bottom of my screen, with information about what I am working on. On the side, there are line numbers, indicating where my cursor is in this file. Plus, my current line is highlighted with a distinct background colour. Let me shift it up and down to illustrate this point.

All those elements are useful while I am programming. But they look distracting when I wish to focus on some portion of text. So, I just type the keyboard shortcut I have and—voilà!—I get the style I prefer.

10 Emacs puts you in control of your computing

You may wonder: why do I even need a customisable text editor?

The answer is about control. You are in charge of what you use and how you use it. You can piece together a workflow that works the way you prefer.

This presentation mode I toggled on and off earlier behaves exactly how I want. I decided which set of interface tweaks to apply. Another user may have a different preference in this regard.

For instance, they may like having line numbers on the side of the screen. There is no right or wrong answer. What matters is that Emacs gives us the means to do what makes sense to us.

11 Your control extends to all workflows

Now apply this principle to everything you can use Emacs for: this will generally be a text-centric project.

I run my agenda exclusively through Emacs.

I handle all my email correspondence with Emacs.

I do programming and I write prose, such as blog posts for my website and books or technical manuals.

For each of these, I know that Emacs will empower me to perform my tasks without arbitrary restrictions.

Emacs lets me use Elisp to modify how I do my emails, for instance, and how I present tasks in my custom agenda view.

12 For an integrated computing environment

Without Emacs, I would not be in a position to control my computing experience to the extent I do.

The reason is that I would be relying on many different applications. Each application has its own interface and design paradigms.

Each application is configured, if at all, in a way that is specific to it. Customisations in one application do not carry over to other applications.

And, if we consider the important implementation details, each application may configurable in its own programming language.

In other words, that is not an integrated computing experience.

13 Many apps do not combine nicely

To have the same degree of control that Emacs makes possible, I would have to hope that somehow all those disparate applications would conspire in my favour.

That is wishful thinking.

The reality is that piecing together many different applications is an exercise in frustration and the path to a life of ever-distracting context switching.

14 Emacs makes your workflow consistent

Having everything I need inside of Emacs ensures that things happen in a manner that is consistent.

All customisations are written in the same programming language, namely, Emacs Lisp.

What I define for one context, such as this “presentation mode”, can be used in another context.

For example, I can have this presentation style enabled when I read emails. Why?

Because it can make it more comfortable for me at a certain hour. And I can even automate this with conditional logic, so it happens on its own when I open a new email under certain circumstances.

15 Integrated computing in practice

When you work with many applications that do not play nicely together, you cannot do something that the developers have not envisaged.

For example, your email client likely does not have access to a “presentation mode”. Same for your other applications.

Similarly, your many applications will not necessarily know how to read and interpret the configurations you have in one application.

Suppose you define your favourite colour scheme for your email client. You take the time to consider the harmonies and use precise typography to your liking.

Now, you switch to your calendar application and none of that work carries over: you have to do it again, assuming it is even possible.

16 Emacs makes integration easier

Colours and styles may seem like relatively small issues. But they are indicative of something greater: disparate applications do not work together seamlessly.

Emacs does not have this problem. You define something for one context you have in mind and, eventually, it can be used in another context that initially you had not even thought of.

For example, in my Emacs I wrote a small function to quickly copy the “thing” at where the cursor is. This is useful when I do programming, as the “thing” can be an entire expression, like the definition of a function. But the “thing” may also be a link that I got in my email.

I had not thought of that use-case in advance. Yet it was trivial to have my function do what I need in this once unforeseen situation.

17 Integration gives you emergent properties

The integrated computing environment of Emacs is more than the sum of its parts.

This is because you can combine different pieces of functionality in ways that the original developer had not foresaw.

You do not simply have your writing, your email, your agenda, et cetera, in Emacs.

You have the functionality of one in tandem with the functionality of another. And you draw linkages between them as you see fit.

Consider once again this presentation I am now doing. What I have in front of me is the transcript of my talk. This is a plain text document, which I can edit live. Let me CAPITALISE THIS to illustrate the point.

18 This is plain text that works like a slideshow

I have made this file look a little bit like a series of slides.

Notice that if I scroll up and down, which I will do shortly, you only get the current section I am reading from: you do not have access to the rest of the document. I will scroll up and down now.

This is a feature known as “narrowing”. Let me “widen” the view and then try to scroll again. You will now be exposed to the rest of the text.

The original developer of this “narrowing” facility did not know how someone like me would make use of it.

I have it here for my presentation. Each heading becomes its own pseudo-slide. I have narrowing for my emails, when I want to read a portion of the text in a more focused way. It is all about how I choose to do my computing.

19 Consistency facilitates productivity

For many years before switching to Emacs, I did not enjoy using the computer.

I needed too much time to accomplish every single task.

I could never find any of my files in a timely fashion because there was no program that would enforce on my behalf a predictable file-naming scheme.

All my notes were eventually not retrievable. This made them useless. Data you save is only good if you can find what you are searching for.

My music collection was inconsistent because I needed special software to write the metadata… In short, I was not as productive as I would like to be.

And, above all, it was not fun.

20 Consistency remove the cognitive burden

Most of my work at the time was centred around the email client and a word processor.

The email client had its own subsystem for handling reminders for tasks. The format of those tasks was not interoperable with other programs.

I could not access the tasks with my favourite text editor. I thus had to use the clunky interface of the email client, which was never designed for task management—and was not configurable.

And then I had all the cognitively burdensome annoyances of my two applications looking quite different from each other.

My emails did not behave like my documents, which made it harder for me to flip between the two and continue writing. I would roll my eyes each time.

21 The consistency of Emacs in action

Emacs has elevated my computing experience.

I have been much more productive ever since I switched to it. Allow me to demonstrate a tiny bit of what I do each day.

I will temporarily exit the presentation mode in this window.

Then, in the bottom half of my screen, I will open my email client to read a message I got.

Once you follow my switch to the email client, I will hide the window that shows this presentation.

After that I will switch to my agenda to record a task and review what I have to do.

All this is done inside of Emacs. Time for action!

22 Use Emacs Lisp to configure everything

What I just demonstrated is a very small part of what I do every single day.

There is much more, though I cannot cover it all in this presentation.

The point, however, is the consistency of the experience; consistency throughout.

I have customised my email client by writing some Emacs Lisp code for it. I have done the same for the custom agenda I have. And much more.

Every time I work with Emacs Lisp, I acquire skills that are applicable outside the confines of the problem I am solving.

For example, by configuring email the way I want, I pick up programming skills that I can then apply to the design of my custom agenda.

23 Learning Emacs Lisp improves the experience

This is an investment that pays off more and more.

Emacs will adapt to match my evolving needs. Each new workflow I incorporate in my Emacs setup will thus benefit from all the knowledge and features I have accumulated.

I do not have to relearn everything because I am not switching to another application.

I do not have to throw away all the work I did all those years. It is here to stay.

I do not feel the pressure to try the new shiny app of the day. I did that many times and always regretted it. I lost my data and time in the process.

Because I am rooted in this stability of Emacs, I remain productive and efficient.

24 Emacs embodies software freedom

I mentioned earlier that Emacs is free or libre software. This means that you can read its source code, modify it, and share your changes with others.

Emacs has a license that gives users power. There is no corporation that can take Emacs away from us. It belongs to the community and we all tend to its wellness.

In the case of Emacs, software freedom is not just about the license. It informs how you use the program. Emacs makes such freedom an irriducible part of its functionality.

You can, at any moment, ask Emacs what does a keyboard shortcut actually do. What is the definition of a function. What is the value of a variable. And you may even access the source code to check for yourself.

I will demonstrate this right now.

25 The freedom of Emacs helps with learning

I actually learnt to program in Emacs Lisp by exercising this freedom.

I would tinker with Emacs and continuously check on its state. What does this do? Which function is called by that keyboard shortcut? How is a program able to determine if the file is not saved?

I wanted to learn how, for example, we move down a line. From there, I learnt that we can move down many lines at once.

I then figured that we can move down the lines and then also do something else, such as place the cursor at the end of the line and create a pulse effect to bring attention to it.

Not only did I learn how to configure Emacs, I even wrote tens of extensions for it. I have also authored a libre book titled “Emacs Lisp Elements”. This freedom is not theoretical. I did not have a background in programming, yet was empowered to act and to grow as a person.

26 Emacs is not only for programmers

Emacs is extended with Emacs Lisp. If you know how to program in that language, you can be extra opinionated and particular about the way Emacs facilitates your work.

But even without any expertise of this sort, you can still do much of what you like. Remember that I started using Emacs without a background in programming.

Emacs blurs the distinction between user and developer. Many of the developers actually start out as users like myself. They learn along the way and, eventually, they contribute to the development of Emacs.

I even have written code that is in core Emacs: my modus-themes as well as several other smaller patches.

27 You benefit from all the Emacs extensions

The Emacs community has developed a rich corpus of extensions. You do not need to invent anything right away in order to be productive.

We call these extensions “packages”, as they are distributed in a way that makes them easy to install and then use directly.

The Emacs program you will download on your computer ships with plenty of packages built-in.

Depending on your needs, you may not even have to install anything from what the community has to offer.

Though if you want a package, it is fairly easy to get it and run it on your system.

Emacs is not picky about how you should use it. You are empowered to be opinionated.

28 Some powerful extensions are built-in

For example, Emacs ships with a package called org or “Org mode”. At its core, this is a markup language. I am using it right now in this document.

Notice how lines that start with an asterisk function as headings. This is what the markup does.

Org lets you write documents, including books, handle your tasks, organise your agenda, and much more. It is a powerhouse.

There are so many things to discover in Emacs as well as the broader package ecosystem.

Emacs as a whole provides high quality documentation that explains everything.

29 The documentation culture of Emacs

When you install Emacs, you get with it plenty of technical manuals. There is also an interactive tutorial to help you make sense of the basics.

Furthermore, when you ask Emacs for help about the definition of a function or the value of a variable, you receive the documentation for the thing you are looking for.

The expectation for all contributions to the official Emacs program is that the code is well-documented and the manual is updated accordingly.

30 Most packages have high quality manuals

Core Emacs sets the standard of what good documentation looks like. Package developers follow this practice.

For example, my denote package has a manual that is over 7500 lines long. It exceeds 52000 words. In it users find detailed instructions as well as code snippets that they can copy and use outright. And this is not the exception. All my packages are like that, to the extent necessary. Most other developers do the same.

As a community, we have access to so much knowledge for free and in freedom. If we are committed enough, we can learn from others and thus become better ourselves. We do so in a spirit of sharing and caring. For me, specifically, all this was of great help. I am self-taught because I received all those great resources from the community. I consider it my duty to give back in kind.

31 Emacs has a steep learning curve

Because Emacs is extensible, there is practically no limit to what you can do with it. At least this is the case for all tasks that are text-heavy.

Emacs will just gracefully evolve to match your requirements, provided you can extend it on your own or with a relevant package.

The downside, however, is that it is not easy to become proficient in it. If you are committed, you can learn the basics within the first few days.

Though you will need to invest a few weeks or months to become skillful. It depends on how much effort you put into it, what sort of work you are doing, and what your background is.

I learnt the basics within a few days. I started writing my own Emacs Lisp within weeks. And within a year I had my modus-themes moved into core Emacs.

32 Do not skip the manuals

Several “starter kits” are available to help you get started. They set things up so that you do not need to discover everything at the outset.

The new version of Emacs (Emacs 31) will even come with a “newcomers theme”, which configures several settings in advance.

These can make the learning curve a bit smoother. For me, anything that improves the onboarding experiences is a plus.

Though I do not think that Emacs will ever become “plug and play”. This is due to its sheer depth and extensibility. It does so much that you still need to invest the time and effort into learning it.

However you start, the most reliable study involves the manuals. Those are written for the benefit of the user. Read them carefully.

33 Adjust your expectations

What I can say with confidence is that Emacs is not for tourists. You cannot switch to it with the expectation that you will have a good time right away.

No. That will not work. There simply is no shortcut to excellence.

I encourage you to take it one step at a time. Emacs will make you more productive, provided you are patient enough to unlock its virtually boundless potential.

Take it slow and be methodical. Rely on the official manual no matter your starting point. Read from it and gradually incorporate its insights into your workflow.

The community—myself included—has plenty of resources to complement that study. Blog posts, video tutorials, books… But do not skip the official manual. Learning it slowly means that you will become proficient faster than you otherwise would.

34 Why it is worth learning how to use Emacs

I already talked about the technical side of things with regard to the integrated computing environment. Now combine that with two facts:

  1. Emacs is free software. This means that we as a community are its custodians.
  2. GNU Emacs has been around since the 1980s. It will stay relevant for decades to come.

Emacs is not old, it is timeless. This is because it can be extended in a spirit of freedom.

Whatever new technology or idea we have as a collective, we can eventually bring it into Emacs.

This way, our integrated computing environment adapts with the times.

Thus Emacs remains ever-relevant.

35 The initial effort pays off long-term

Couched in those terms, the initial effort you will put into learning Emacs is actually not that much.

You have to maintain a longer-term view of this project.

If you are patient, Emacs will be one of the most reliable tools you will ever use throughout your life. And I say this as a handy man myself, someone who uses many tools for manual labour, having built the house I am in, among others.

I switched to Emacs in the summer of 2019. It is almost 7 years already. I see no reason not to use it for the next 7 years, if I can.

I will still want to write articles, do programming, maintain my agenda, and probably make presentations like this one.

36 Good luck and have fun!

Remember that you will not learn Emacs over the weekend. You are in it for the long-term. Take it slow and you will enjoy the experience.

This is all I have for you today folks. Thank you very much for your attention!

You can find this and everything else I publish on my website: https://protesilaos.com.

]]>
My Emacs talk for FLOSS @ Oxford I talked about how to do computing in freedom with GNU Emacs. Thu, 12 Mar 2026 00:00:00 +0000 https://protesilaos.com/codelog/2026-03-12-my-emacs-talk-floss-oxford/ https://protesilaos.com/codelog/2026-03-12-my-emacs-talk-floss-oxford/ Earlier today, at 20:00 Europe/Athens time, I provided an introduction to Emacs at the event FLOSS @ Oxford: https://ox.ogeer.org/event/computing-in-freedom-with-gnu-emacs-protesilaos-stavrou.

I had written the transcript ahead of time to make my presentation more accessible. The event was held live as a Jitsi call. There were questions from participants, which I answered. A recording of the event will be available before the end of this week. I will update this article to include a link to the video.

UPDATE 2026-03-16 07:49 +0200: The video is here: https://ogeer.org/ox/rec/emacs/.

Below is the text of my talk. It is titled “Computing in freedom with GNU Emacs”. Note that some parts of my presentation only make sense in the video format, though I tried to describe in the transcript what I was demonstrating.


Table of Contents

  1. Emacs as a capable text editor
  2. Emacs can display graphics alongside text
  3. Emacs is an extensible text editor
  4. The extensibility of Emacs happens live
  5. Emacs puts you in control of your computing
  6. The promise of an integrated computing environment
  7. The integrated computing environment in practice
  8. Integration gives you emergent properties
  9. Consistency facilitates productivity
  10. The consistency of Emacs in action
  11. Use Emacs Lisp to configure everything
  12. Emacs is the embodiment of software freedom
  13. You do not need to be a programmer to use Emacs
  14. The documentation culture of Emacs
  15. Emacs has a steep learning curve
  16. Why it is worth learning how to use Emacs
  17. Good luck and have fun!

Hello everyone! My name is Protesilaos, also known as “Prot”. I am joining you from the mountains of Cyprus. Cyprus is an island in the Eastern Mediterranean Sea.

In this presentation I will talk to you about GNU Emacs, or simply, “Emacs”. Emacs is a program you run on your computer. I am using it right now for this presentation.

Emacs is free or libre software. It allows you to read all of its source code, to modify it, and to share it with your customisations. Thus you contribute to—and benefit from—a community of welcoming Emacs users.

I will tell you what all this means in practice and how you can improve your computing experience by switching to Emacs.

Emacs as a capable text editor

When you first start using Emacs, it feels like a regular text editor program. You move the cursor around and edit text. Nothing obviously impressive out-of-the-box. As a text editor, Emacs is highly capable. It has all sorts of keyboard shortcuts that let you efficiently operate on text. You can control Emacs without relying on the mouse, if you want.

Emacs supports the Unicode standard, which is essential for inclusivity of peoples. The world’s scripts can be expressed in Emacs. I am a native Greek speaker. I can use functionality that is built into Emacs to switch to the Greek alphabet in order to write something, such as to say «καλησπέρα», which means “good evening”. I can even spell out “Dao De Jing” (道德经), which is the title of a book from ancient China. Plus emoji: 🙃.

The multitude of scripts can be present in the same document. This is an advantage for multilingual people or those who do research that involves many natural languages.

Emacs can combine several fonts in the same page as well as different colours. Each fonts can have its own attributes, such as for its relative size and typographic intensity. Same idea for colours. On my screen right now, I am already combining two different font styles: that of the heading and the body of the text.

Emacs can display graphics alongside text

Emacs does not limit you to a text-only interface. It can also display images and PDF documents. Below I have a link to an image file. I will now type a keyboard shortcut to reveal this image. And I will do it again to hide it.

[Here is an image that I do not need to reproduce on my website: the specific image does not matter]

This, by the way, is a spot somewhere in my mountains.

Emacs is an extensible text editor

Although you can benefit from using Emacs as a generic text editor, what really appeals to people like me is the option to extend Emacs. “Extend” here means to introduce new functionality; functionality that is not available in the default program you install on your computer.

These extensions are written in the same programming language as most of Emacs. It is a programming language called “Emacs Lisp” or “Elisp”. You can extend Emacs on your own, by writing some program in Elisp, or you can download an existing extension that the community has made available.

For example, when I create a new extension for Emacs, I publish it under the terms of a free software license—the same terms that Emacs uses. Others can then download my extension and use it as they prefer. If they want, they can make their own modifications on top, which may introduce other extensions that I had not thought of in my original implementation. And if those users follow my example, then I can also benefit from their additions once they publish them.

As such, there exists a community of enthusiastic users of Emacs who care about sharing their works with the rest of the world.

The extensibility of Emacs happens live

Users can extend Emacs by running some Emacs Lisp program. Such a program can be as small as a single line. Or it can be as long as it needs to be. It does not matter. Users run the program and Emacs immediately does what the program renders possible.

For example, I am doing this presentation inside of Emacs. But Emacs does not have a “presentation mode” built into it. I thus developed my own extension which empowers me to do what I am doing right now. Let me toggle off my presentation mode to show you what I mean.

Notice that the display has changed. My main font is monospaced now. The headings are smaller than they were before: they are the same size as the rest of the text. There is no number next to the heading anymore. Then, there is a bar at the bottom of my screen, with information about what I am working on. On the side, there are line numbers, indicating where my cursor is in this file. Plus, my current line is highlighted with a distinct background colour. Let me shift it up and down to illustrate this point.

All those elements are useful while I am programming. But they look distracting when I wish to focus on some portion of text. So, I just type the keyboard shortcut I have and—voilà!—I get the style I prefer.

Emacs puts you in control of your computing

You may wonder: why do I even need a customisable text editor? The answer is about control. You are in charge of what you use and how you use it. You can piece together a workflow that works the way you prefer.

This presentation mode I toggled on and off earlier behaves exactly how I want. I decided which set of interface tweaks to apply. Another user may have a different preference in this regard. For instance, they may like having line numbers on the side of the screen. There is no right or wrong answer. What matters is that Emacs gives us the means to do what makes sense to us.

Now apply this principle to everything you can use Emacs for: this will generally be a text-centric project. I run my agenda exclusively through Emacs. I handle all my email correspondence with Emacs. I do programming and I write prose, such as blog posts for my website and books or technical manuals.

For each of these, I know that Emacs will empower me to perform my tasks without arbitrary restrictions. Emacs lets me use Elisp to modify how I do my emails, for instance, and how I present tasks in my custom agenda view.

The promise of an integrated computing environment

Without Emacs, I would not be in a position to control my computing experience to the extent I do. The reason is that I would be relying on many different applications. Each application has its own interface and design paradigms. Each application is configured, if at all, in a way that is specific to it. Customisations in one application do not carry over to other applications. And, if we consider the important implementation details, each application may configurable in its own programming language.

In other words, that is not an integrated computing experience. To have the same degree of control that Emacs makes possible, I would have to hope that somehow all those disparate applications would conspire in my favour. That is wishful thinking. The reality is that piecing together many different applications is an exercise in frustration and the path to a life of ever-distracting context switching.

Having everything I need inside of Emacs ensures that things happen in a manner that is consistent. All customisations are written in the same programming language, namely, Emacs Lisp. What I define for one context, such as this “presentation mode”, can be used in another context. For example, I can have this presentation style enabled when I read emails. Why? Because it can make it more comfortable for me at a certain hour. And I can even automate this, so it happens on its own when I open a new email.

The integrated computing environment in practice

When you work with many applications that do not play nicely together, you cannot do something that the developers have not envisaged. For example, your email client likely does not have access to a “presentation mode”. Same for your other applications.

Similarly, your many applications will not necessarily know how to read and interpret the configurations you have in one application. Suppose you define your favourite colour scheme for your email client. You take the time to consider the harmonies and use precise typography to your liking. Now, you switch to your calendar application and none of that work carries over: you have to do it again, assuming it is even possible.

Colours and styles may seem like relatively small issues. But they are indicative of something greater: disparate applications do not work together seamlessly.

Emacs does not have this problem. You define something for one context you have in mind and, eventually, it can be used in another context that initially you had not even thought of. For example, in my Emacs I wrote a small function to quickly copy the “thing” at where the cursor is. This is useful when I do programming, as the “thing” can be an entire expression, like the definition of a function. But the “thing” may also be a link that I got in my email. I had not thought of that use-case in advance.

Integration gives you emergent properties

The integrated computing environment of Emacs is more than the sum of its parts. This is because you can combine different pieces of functionality in ways that the original developer had not foresaw. You do not simply have your writing, your email, your agenda, et cetera, in Emacs. You have the functionality of one in tandem with the functionality of another. And you draw linkages between them as you see fit.

Consider once again this presentation I am now doing. What I have in front of me is the transcript of my talk. This is a plain text document, which I can edit live. Let me CAPITALISE THIS to illustrate the point. But I have made this file look a little bit like a series of slides. Notice that if I scroll up and down, which I will do now, you only get the current section I am reading from: you do not have access to the rest of the document. This is a feature known as “narrowing”. Let me “widen” the view and then try to scroll again. You will now be exposed to the rest of the text.

The original developer of this “narrowing” facility did not know how someone like me would make use of it. I have it here for my presentation. Each heading becomes its own pseudo-slide. I have narrowing for my emails, when I want to read a portion of the text in a more focused way. It is all about how I choose to do my computing.

Consistency facilitates productivity

For many years before switching to Emacs, I did not enjoy using the computer. I needed too much time to accomplish every single task. I could never find any of my files in a timely fashion because there was no program that would enforce on my behalf a predictable file-naming scheme.

All my notes were eventually not retrievable. My music collection was inconsistent because I needed special software to write the metadata… In short, I was not as productive as I would like to be. And, above all, it was not fun.

Most of my work at the time was centred around the email client and a word processor. The email client had its own subsystem for handling reminders for tasks. The format of those tasks was not interoperable with other programs. I could not access it with my favourite text editor. I thus had to use the clunky interface of the email client, which was never designed for task management—and was not configurable.

And then I had all the cognitively burdensome annoyances of my two applications looking quite different from each other. My emails did not behave like my documents, which made it harder for me to flip between the two and continue writing.

The consistency of Emacs in action

Emacs has elevated my computing experience. I have been much more productive ever since I switched to it. Allow me to demonstrate a tiny bit of what I do each day. I will temporarily exit the presentation mode in this window. Then, in the bottom half of my screen, I will open my email client to read a message I got. After that I will switch to my agenda to record a task and review what I have to do. All this is done inside of Emacs. Time for action!

Use Emacs Lisp to configure everything

What I just demonstrated is a very small part of what I do every single day. There is much more, though I cannot cover it all in this presentation. The point, however, is the consistency of the experience; consistency throughout.

I have customised my email client by writing some Emacs Lisp code for it. I have done the same for the custom agenda I have. And much more.

Every time I work with Emacs Lisp, I acquire skills that are applicable outside the confines of the problem I am solving. For example, by configuring email the way I want, I pick up programming skills that I can then apply to the design of my custom agenda.

This is an investment that pays off more and more. Emacs will grow or shrink to match my evolving needs. Each new workflow I incorporate in my Emacs setup will thus benefit from all the knowledge and features I have accumulated.

I do not have to relearn everything. I do not have to throw away all the work I did. It is here to stay. I do not feel the pressure to try the new shiny app of the day. And, because I am rooted in this stability, I remain productive and efficient.

Emacs is the embodiment of software freedom

I mentioned earlier that Emacs is free or libre software. This means that you can read its source code, modify it, and share your changes with others. Emacs has a license that gives users power. There is no corporation that can take Emacs away from us. It belongs to the community and we all tend to its wellness.

Software freedom is not just about the license. Emacs makes such freedom an irriducible part of its functionality. You can, at any moment, ask Emacs what does a keyboard shortcut actually do. What is the definition of a function. What is the value of a variable. And you may even access the source code to check for yourself.

I actually learnt to program in Emacs Lisp by exercising this freedom. I would tinker with Emacs and continuously check on its state. I wanted to learn how, for example, we move down a line. From there, I learnt that we can move down many lines at once. I then figured that we can move down the lines and then also do something else, such as place the cursor at the end of the line and create a pulse effect to bring attention to it.

Not only did I learn how to configure Emacs, I even wrote tens of extensions for it. I have also authored a libre book titled “Emacs Lisp Elements”. This freedom is not theoretical. I did not have a background in programming, yet was empowered to act.

You do not need to be a programmer to use Emacs

Emacs is extended with Emacs Lisp. If you know how to program in that language, you can be extra opinionated and particular about the way Emacs facilitates your work.

But even without any expertise of this sort, you can still do much of what you like. This is because the Emacs community has developed a rich corpus of extensions. We call these extensions “packages”, as they are distributed in a way that makes them easy to install and then use directly.

The Emacs program you will download on your computer ships with plenty of packages built-in. Depending on your needs, you may not even have to install anything from what the community has to offer.

For example, Emacs ships with a package called org or “Org mode”. At its core, this is a markup language. I am using it right now in this document. Notice how lines that start with an asterisk function as headings. This is what the markup does. Org lets you write documents, including books, handle your tasks, organise your agenda, and much more. It is a powerhouse. There are so many things to discover. Emacs provides high quality documentation that explains everything.

The documentation culture of Emacs

When you install Emacs, you get with it plenty of technical manuals. There is also an interactive tutorial to help you make sense of the basics. Furthermore, when you ask Emacs for help about the definition of a function or the value of a variable, you receive the documentation for the thing you are looking for.

The expectation for all contributions to the official Emacs program is that the code is well-documented and the manual is updated accordingly.

This is true also for packages that the community develops. For example, my denote package has a manual that is over 7500 lines long. It exceeds 52000 words. In it users find detailed instructions as well as code snippets that they can copy and use outright. And this is not the exception. All my packages are like that, to the extent necessary. Most other developers do the same.

As a community, we have access to so much knowledge for free and in freedom. If we are committed enough, we can learn from others and thus become better ourselves. We do so in a spirit of sharing and caring. For me, specifically, all this was of great help. I am self-taught because I received all those great resources from the community. I consider it my duty to give back in kind.

Emacs has a steep learning curve

Because Emacs is extensible, there is practically no limit to what you can do with it. At least this is the case for all tasks that are text-heavy. Emacs will just gracefully evolve to match your requirements, provided you know how to extend it.

The downside, however, is that it is not easy to become proficient in it. If you are committed, you can learn the basics within the first few days. Though you will need to invest a few weeks or months to become skillful. It depends on how much effort you put into it.

What I can say with confidence is that Emacs is not for tourists. You cannot switch to it with the expectation that you will have a good time right away. No. That will not work. There simply is no shortcut to excellence.

I thus encourage you to adjust your expectations. Emacs will make you more productive, provided you are patient enough to unlock its virtually boundless potential. Take it slow and be methodical. Rely on the official manual. Read from it and gradually incorporate its insights into your workflow. The community has plenty of resources to complement that study. But do not skip the official manual. Learning it slowly means that you will become proficient faster than you otherwise would.

Why it is worth learning how to use Emacs

I already talked about the technical side of things with regard to the integrated computing environment. Now combine that with two facts:

  1. Emacs is free software. This means that we as a community are its custodians.
  2. GNU Emacs has been around since the 1980s. It will stay relevant for decades to come.

Emacs is not old, it is timeless. This is because it can be extended in a spirit of freedom. Whatever new technology or idea we have as a collective, we can eventually bring it into Emacs. This way, our integrated computing environment adapts with the times.

Couched in those terms, the initial effort you will put into learning Emacs is actually not that much. You have to maintain a longer-term view of this project. If are patient, Emacs will be one of the most reliable tools you will ever use throughout your life. And I say this as a handy man myself, having built the house I am in, among others.

I switched to Emacs in the summer of 2019. It is almost 7 years already. I see no reason not to use it for the next 7 years, if I can. I will still want to write articles, do programming, maintain my agenda, and probably make presentations like this one.

Good luck and have fun!

Remember that you will not learn Emacs over the weekend. You are in it for the long-term. Take it slow and you will enjoy the experience.

This is all I have for you today folks. Thank you very much for your attention!

]]>
This Thursday I will talk about Emacs @ OxFLOSS (FLOSS @ Oxford) In this upcoming event I will introduce GNU Emacs to people at the University of Oxford. Mon, 09 Mar 2026 00:00:00 +0000 https://protesilaos.com/codelog/2026-03-09-thursday-emacs-computing-freedom-oxfloss/ https://protesilaos.com/codelog/2026-03-09-thursday-emacs-computing-freedom-oxfloss/ This Thursday, the 12th of March, at 20:00 Europe/Athens time I will do a live presentation of Emacs for OxFLOSS (FLOSS @ Oxford). This is an event organised by people at the University of Oxford. My goal is to introduce Emacs to a new audience by showing them a little of what it can do while describing how exactly it gives users freedom.

The presentation will be about 40 minutes long. I will then answer any questions from the audience. Anyone can participate: no registration is required. The event will be recorded for future reference. The link for the video call and further details are available here: https://ox.ogeer.org/event/computing-in-freedom-with-gnu-emacs-protesilaos-stavrou.

I will prepare a transcript for my talk. This way people can learn about my presentation without having to access the video file.

Looking forward to it!

]]>
Emacs: four new themes are coming to the ‘doric-themes’ I am developing four new themes for my minimalist 'doric-themes' package. Sat, 07 Mar 2026 00:00:00 +0000 https://protesilaos.com/codelog/2026-03-07-emacs-four-new-doric-themes/ https://protesilaos.com/codelog/2026-03-07-emacs-four-new-doric-themes/ I am developing four new themes for my doric-themes package:

  • doric-almond (light)
  • doric-coral (light)
  • doric-magma (dark)
  • doric-walnut (dark)

Each of them has its own character, while they all retain the minimalist Doric style. Below are some screenshots. Remember that these themes use few colours, relying on typography to establish a visual rhythm.

doric-almond

doric-almond theme sample

doric-almond theme sample

doric-almond theme sample

doric-almond theme sample

doric-coral

doric-coral theme sample

doric-coral theme sample

doric-coral theme sample

doric-coral theme sample

doric-magma

doric-magma theme sample

doric-magma theme sample

doric-magma theme sample

doric-magma theme sample

doric-walnut

doric-walnut theme sample

doric-walnut theme sample

doric-walnut theme sample

doric-walnut theme sample

Coming in version 1.1.0

All four themes are in development. I may still make some minor refinements to them, though I have already defined their overall appearance. If you like the minimalism of the doric-themes, I think you will appreciate these new additions.

Sources

The Doric themes use few colours and will appear monochromatic in many contexts. They are my most minimalist themes. Styles involve the careful use of typographic features and subtleties in colour gradients to establish a consistent rhythm.

If you want maximalist themes in terms of colour, check my ef-themes package. For something in-between, which I would consider the best “default theme” for a text editor, opt for my modus-themes.

]]>
I talk with Joshua Blais about Emacs and life issues I had a ~2-hour chat with Joshua Blais, a fellow Emacs user, about Emacs and philosophy. Thu, 05 Mar 2026 00:00:00 +0000 https://protesilaos.com/codelog/2026-03-05-emacs-and-philosophy-chat-with-joshua-blais/ https://protesilaos.com/codelog/2026-03-05-emacs-and-philosophy-chat-with-joshua-blais/ Raw link: https://www.youtube.com/watch?v=1vMlGFELajQ

I had a ~2-hour chat with Joshua Blais, a fellow Emacs user, over at the @JoshuaBlais YouTube channel: https://www.youtube.com/@JoshuaBlais. We covered Emacs at length and also talked about general life issues.

The first topic we cover is how to place constraints on yourself in order to avoid backsliding into bad habits. This ties in to the themes of discipline and productivity that we discuss in some further length.

Joshua asks me how I got into Emacs and how I started writing/maintaining packages for it. We talk about how Emacs provides for an integrated computing experience. Learning Emacs Lisp allows you to have better control of Emacs.

In this light we comment on Guix and how it is also configurable in a dialect of Lisp. Joshua is using Nix and I learn more about that experience.

Coming back to Emacs, we comment on its relationship to the Unix philosophy. I think Emacs is compatible with Unix. Though my main point is how Emacs empowers us to use the computer in a productive way. It augments the experience.

Simple living and financial independence is another topic we cover. Joshua wants to know how I approach this issue. I explain how it is a matter of controlling your wants. Figure out what the parts of your lifestyle that you would not sacrifice. Then you know how much money you need for that lifestyle.

Joshua makes a connection of the simple life to Emacs and Unix tools. I comment on that as well. Once you start using Emacs and friends, you learn to appreciate the essentials. This you can then apply to other parts of your life.

We move to note-taking, where I comment about Denote. I explain how it is a file-naming scheme, which can also be used to write notes. What matters is how well we can retrieve information. Joshua explains how pen and paper helps him express his thoughts.

Learning on your own is our next point. Being an autodidact myself, I comment how it empowers you. You are able to have initiative and be more independent.

We then explore how things have infinite depth. This is how everything in the world is connected. This also relates to the point about the simple living, since you can have relatively few things that you keep understanding in depth.

Joshua asks me about discipline. This is a capacity we can build up. I give some examples.

Next on our list are mechanical keyboards. Joshua and I are using a split keyboard.

Then we explore the theme of using tools the right way. One example is the Internet as a whole. Another is with LLMs. It helps to know “why am I doing this”, as then you can understand when you are meeting your goals and when you are moving away from them. We explore this in further depth.

I comment on a common mistake we make where we think that the complex must be sophisticated and profound. Whereas there is profundity in simplicity.

We connect the dots through all these as we wrap things up.

Thanks to Joshua Blais for this chat. I had a good time and wish him all the best!

]]>
Emacs: confirm package bugs with –init-directory Information on how to use the Emacs --init-directory flag to identify bugs with packages you rely on. Wed, 18 Feb 2026 00:00:00 +0000 https://protesilaos.com/codelog/2026-02-18-emacs-confirm-package-bugs/ https://protesilaos.com/codelog/2026-02-18-emacs-confirm-package-bugs/ Much of the maintenance work I do for my packages involves correspondence with users about potential bugs. Sometimes, a user will encounter a problem that I cannot reproduce on my end. I thus try to recreate the bug in a pristine environment and ask my correspondent to do the same.

This has become easier since Emacs 29, which introduced a command-line flag called --init-directory. It is responsible for loading the init.el that is present in the given directory. For example:

# From a terminal or shell, run something like this:
emacs --init-directory=/tmp/test-emacs/

In other words, you can keep your regular configuration intact while launching Emacs with another set of options.

Create the test init.el file

Have a directory that is unrelated to your regular Emacs configuration. Then write the init.el inside of it.

Because I do this frequently, I prefer to use the standard Linux path /tmp/. Its files get deleted as soon as I switch off the computer, which is exactly what I want in this case.

As such, if there is a bug with, say, the modus-themes, I will work with this file path /tmp/modus-themes/init.el.

But the exact location of the directory does not matter, so choose what makes sense to you.

Write the minimum necessary code

In that init file, include only the code that is needed to reproduce the bug.

Since you want to have the package installed, it makes sense to write a use-package declaration for it. Include the :ensure t directive as it instructs the built-in package manager to install the package if it is not already available.

;; Contents of the init.el...
(use-package modus-themes
  :ensure t
  :config
  (setq modus-themes-common-palette-overrides
        '((fringe unspecified)
          (border-mode-line-active unspecified)
          (border-mode-line-inactive unspecified)))
  (setq modus-vivendi-palette-overrides
        '((bg-main "#1e1f22")
          (fg-main "#bcbec4")))
  (load-theme 'modus-vivendi t))

Install from source, if necessary

If you are using an alternative to package.el like straight or elpaca, then the aforementioned :ensure t will likely not suffice: you need to build the package from source. To this end, Emacs has the function package-vc-install. Some of my recent packages have sample code that relies on this approach. For instance:

(use-package gnome-accent-theme-switcher
  :demand t
  :init
  ;; Then upgrade it with the command `package-vc-upgrade' or `package-vc-upgrade-all'.
  (unless (package-installed-p 'gnome-accent-theme-switcher)
    (package-vc-install "https://github.com/protesilaos/gnome-accent-theme-switcher.git"))
  :bind
  (("<f5>" . gnome-accent-theme-switcher-toggle-mode)
   ("C-<f5>" . gnome-accent-theme-switcher-change-accent))
  :config
  (gnome-accent-theme-switcher-mode 1))

In the above snippet package-vc-install will pull the latest commit from the main branch, though it can even get a specific commit. Read its documentation with M-x describe-function.

What matters is that you fetch the version which you are running in your personaly configuration.

Launch Emacs with this configuration

From the command-line, run something like the following:

emacs --init-directory=/tmp/test-emacs/

This will launch a new instance of Emacs. The use-package you placed there will do the work to install the package. After that you are ready to reproduce the bug in this clean setup.

Write down all the steps

To help the maintainer identify the source of the trouble, keep a record of all the steps you followed. Some bugs show up when the package is loaded, but others are triggered only after a specific action is performed.

Normally, Emacs will pop up a *Backtrace* buffer when it encounters an error. Copy its contents and send them to the maintainer, together with the init.el you used, and the list of the steps you followed.

Sometimes you just need to re-install the package

It sometimes happens that you install a package and it is completely broken. Although this looks bad, it may not even be a bug, but an issue with the old bytecode you had on your system from the previous version of the package.

Do M-x package-delete, select the package, restart Emacs, and then M-x package-install to install the package anew. If everything works, then the problem is gone and you do not need to tell the maintainer about it.

Make it easier for maintainers to help you

With this knowledge, you can provide high quality bug reports for the packages you rely on. Good luck!

]]>
Emacs: I will talk about Emacs and free software (FLOSS @ Oxford) Information about my upcoming Emacs-related talk for the event 'FLOSS @ Oxford'. Mon, 16 Feb 2026 00:00:00 +0000 https://protesilaos.com/codelog/2026-02-16-emacs-talk-oxford/ https://protesilaos.com/codelog/2026-02-16-emacs-talk-oxford/ People from the University of Oxford are organising events related to free software: FLOSS @ Oxford.

On Thursday, the 12th of March 2026, at 6 PM United Kingdom time (GMT) I will give a talk titled Computing in freedom with GNU Emacs. My intention is to introduce Emacs to a wide audience. Participation is open to everyone.

I will post a reminder as we get closer to the date of the event. Looking forward to it!

]]>
Emacs: add custom entity (Austrian school) to my ‘institution-calendar’ This is a guide on how to expand my institution-calendar package to work with your institution. Sat, 14 Feb 2026 00:00:00 +0000 https://protesilaos.com/codelog/2026-02-14-emacs-institution-calendar-add-custom-entity/ https://protesilaos.com/codelog/2026-02-14-emacs-institution-calendar-add-custom-entity/ My institution-calendar package for Emacs displays term+week indicators in the *Calendar* buffer (which, by default, is produced by the calendar command). This is useful, for example, for schools who organise their work by terms, such as winter, spring, and summer, with each having a set number of weeks. This is how the University of Oxford will look like:

Oxford calendar for Emacs

The package supports the universities of Oxford and Cambridge out-of-the-box, though users can define their own institutions. I have two institutions there to provide concrete examples. I am happy to add more, but the idea is for users to maintain their own data.

Below I show a complete example using data for a school in Austria.

Write the calendar data

To make this work, you first need to specify the data. This has the same structure as institution-calendar-oxford-university-dates and thus passes the test of institution-calendar-valid-data-p. Look at the code for Oxford to get an idea. Here is a sample:

(defvar my-austrian-school-dates
  '((2025 (wintersemester ( 9  8 2025) ( 2  6 2026))
          (sommersemester ( 2 16 2026) ( 7 10 2026)))))

This is an Austrian school that has two terms for the academic year starting in 2025: wintersemester and sommersemester. The symbols for those terms can be anything. Internally, the package uses the first letter to form the week indicator, followed by the number of the week within the given term.

Each term defines a start date and an end date as a list of integers of the form (MONTH DAY YEAR). I picked a form that is consistent with the way calendar.el represents the date, otherwise I would have used a different standard.

Register your institution

The variable institution-calendar-user-entities contains all user-defined institutions and their corresponding calendar data. Each entry is a cons cell of the form (ENTITY . CALENDAR-DATA), where ENTITY is an arbitrary symbol and CALENDAR-DATA is the symbol of a variable that holds the data, as shown in the previous section.

Here is how we can add to this list:

(add-to-list 'institution-calendar-user-entities (cons 'austrian-school 'my-austrian-school-dates))

In this example, I am calling the newly registered institution austrian-school, which is how I can refer to it elsewhere. I am associating this austrian-school with the calendar data of the variable my-austrian-school-dates.

Make the institution-calendar-mode work for your institution

With the aforementioned in place, the user option institution-calendar-entity can be set to the value of austrian-school:

(setopt institution-calendar-entity 'austrian-school)

If the institution-calendar-mode is enabled, then the regular calendar command will display week indicators for this school. This is good if you only need one calendar. But if you work with many institutions and thus need to switch between their calendars, then ignore this step and move to the next one. Or ignore it anyway if you prefer to keep the M-x calendar intact.

Define a custom command for your institution

The macro institution-calendar-define-convenience-command makes it trivial to define a command that produces a calendar buffer for the given institution. This is like M-x calendar with the minor mode institution-calendar-mode enabled, except it does not alter the output of the calendar—so you can use them both (or, anyhow, use as many as the institutions you care about).

;; This defines the command `institution-calendar-austrian-school'.
;; Call `institution-calendar-austrian-school' with M-x or bind it to a key.
(institution-calendar-define-convenience-command austrian-school)

Once you evaluate this macro call, you will get the command institution-calendar-austrian-school. Use that to produce a calendar that works with the austrian-school in particular. If you are curious, M-x institution-calendar-oxford-university will still do the right thing for the University of Oxford. Same for the command institution-calendar-cambridge-university.

Use an intermonth header

The user option institution-calendar-include-intermonth-header adds a header above the week numbers. By default, this only works with the universities of Oxford and Cambridge. Though you can extend the package to support your institution by adding to the value of the variable institution-calendar-intermonth-headers. Thus:

(add-to-list 'institution-calendar-intermonth-headers (cons 'austrian-school "AU"))

You can skip this step if you do not plan to display the intermonth header. Those are not shown by default.

Putting it all together

This is how your configuration of the institution-calendar may look like:

(use-package institution-calendar
  :ensure nil ; not in a package archive
  :init
  ;; Install it from source.
  ;; Then upgrade it with the command `package-vc-upgrade' or `package-vc-upgrade-all'.
  (unless (package-installed-p 'institution-calendar)
    (package-vc-install "https://github.com/protesilaos/institution-calendar.git"))
  :config
  (defvar my-austrian-school-dates
    '((2025 (wintersemester ( 9  8 2025) ( 2  6 2026))
            (sommersemester ( 2 16 2026) ( 7 10 2026)))))

  (add-to-list 'institution-calendar-user-entities (cons 'austrian-school 'my-austrian-school-dates))

  ;; This defines the command `institution-calendar-austrian-school'.
  ;; Call `institution-calendar-austrian-school' with M-x or bind it to a key.
  (institution-calendar-define-convenience-command austrian-school)

  (setopt institution-calendar-include-extra-week-numbers t)
  (setopt institution-calendar-include-intermonth-header nil)

  ;; These are optional, if you want `M-x calendar' to work for your institution.
  (setopt institution-calendar-entity 'austrian-school)

  (institution-calendar-mode 1))

Sources

]]>
Emacs: my GNOME accent color theme switcher package Video demo of my new Emacs package that synchronises the theme with that of the GNOME desktop environment. Fri, 13 Feb 2026 00:00:00 +0000 https://protesilaos.com/codelog/2026-02-13-emacs-gnome-accent-theme-switcher/ https://protesilaos.com/codelog/2026-02-13-emacs-gnome-accent-theme-switcher/ Raw link: https://www.youtube.com/watch?v=atKuEh3_ArA

In this short video I demonstate a new package for GNU Emacs that synchronises the Emacs theme with the GNOME settings for accent color and light/dark mode. Git repository here: https://github.com/protesilaos/gnome-accent-theme-switcher.

]]>
Emacs: Lin version 2.0.0 Information about the latest version of my lin package for GNU Emacs. Thu, 12 Feb 2026 00:00:00 +0000 https://protesilaos.com/codelog/2026-02-12-emacs-lin-2-0-0/ https://protesilaos.com/codelog/2026-02-12-emacs-lin-2-0-0/ Lin is a stylistic enhancement for Emacs’ built-in hl-line-mode. It remaps the hl-line face (or equivalent) buffer-locally to a style that is optimal for major modes where line selection is the primary mode of interaction.

The idea is that hl-line-mode cannot work equally well for contexts with competing priorities: (i) line selection, or (ii) simple line highlight. In the former case, the current line needs to be made prominent because it carries a specific meaning of some significance in the given context: the user has to select a line. Whereas in the latter case, the primary mode of interaction does not revolve around the line highlight itself: it may be because the focus is on editing text or reading through the buffer’s contents, so the current line highlight is more of a reminder of the point’s location on the vertical axis.

Below are the release notes


Version 2.0.0 on 2026-02-12

This is the first tagged release since 2024-08-05. The package is in a stable state: it does everything it is meant to. This version makes some small refinements, mostly in how parts of the code are written. Though there also are some nice user-facing changes:

  • The lin-gnome-accent-color-mode synchronises the accent colour of the GNOME desktop environment with Lin’ own lin-face. This happens live, so any buffers that are already using the lin-mode (directly or via lin-global-mode) will get the updated colour.

  • The user option lin-gnome-accent-color-override-foreground controls whether the faces that correspond to GNOME accent colours should override the underlying text colour or not. This is useful for improved colour contrast. The default is to not override the foreground. Setting lin-gnome-accent-color-override-foreground to non-nil changes that so, for example, the lin-face will be set to lin-red-override-fg instead of lin-red (of course, faces can be modified by users/themes to override the foreground anyway, so this is about the default behaviour).

  • New faces to style the current line when lin-mode is enabled include lin-purple, lin-orange, and lin-slate. Those do not override the underlying foreground colours by default. Whereas lin-purple-override-fg, lin-orange-override-fg, and lin-slate-override-fg apply their background while also setting the foreground (remember that you always control which face to use by changing the user option lin-face).

  • The lin-global-mode skips all private buffers. These are buffers that users normally do not interact with directly. Their names are prefixed with a space and, by default, are hidden from the view of switch-to-buffer and related commands.

  • The default value of the user option lin-mode-hooks now includes the world-clock-mode-hook and xref--xref-buffer-mode-hook. The former relates to the command world-clock, while the latter is used by any command that produces Grep-like results via the built-in Xref infrastructure (for example, my Denote package does that for a few of its commands). The lin-mode-hooks is a list of hooks for major modes that should use the Lin style for the selection line highlight.

]]>
Emacs: institution-calendar package (University of Oxford/Cambridge, etc.) The institution-calendar package for GNU Emacs augments the calendar buffer with indicators about term weeks (e.g. for university semesters). Wed, 11 Feb 2026 00:00:00 +0000 https://protesilaos.com/codelog/2026-02-11-emacs-institution-calendar/ https://protesilaos.com/codelog/2026-02-11-emacs-institution-calendar/ Oxford calendar for Emacs

This is about a new package of mine: institution-calendar. It is not going to be available on GNU ELPA. Users will have to install it from source (code for this is further below). The reason is that the predecossor to this package, oxford-calendar, was not accepted:

I will consider my options going forward, with whatever that means for all my packages.

Overview

The institution-calendar package augments the M-x calendar buffer to include indicators about the applicable term. Each term has week numbers, which are displayed on the side of the regular calendar data.

The user option institution-calendar-entity specifies which institution’s data to use. Currently, the value can be either oxford-university or cambridge-university. Contact me and I will add support for your institution.

Each term shows the week numbers it formally defines. For example, the University of Oxford has three terms of 8 weeks each. When the user option institution-calendar-include-extra-week-numbers is set to a non-nil value, then an additional two weeks are added: week 0 for one week before the term starts and an extra number after the term ends. This is useful for scheduling purposes, such as to arrange meetings in preparation of the work ahead or to report on what happened.

The user option institution-calendar-include-intermonth-header writes text above the institution’s week indicators. This makes it a bit easier to tell them apart from the regular calendar data.

Showing the calendar

Enable the minor mode institution-calendar-mode to make all future calls to M-x calendar use the relevant institution data.

If you do not want to affect the M-x calendar output, then use the command institution-calendar: it is functionally equivalent to having the aforementioned minor mode enabled, except it has no permanent effect on M-x calendar—that will keep its original appearance.

If, for whatever reason, you need to check the calendar of a specific institution, then do M-x institution-calendar-cambridge-university or M-x institution-calendar-oxford-university (more such commands will be available to match any other institutions that this package will support).

Installation and configuration

(use-package institution-calendar
  :ensure nil ; not in a package archive
  :init
  (unless (package-installed-p 'institution-calendar)
    (package-vc-install "https://github.com/protesilaos/institution-calendar.git"))
  :commands
  (institution-calendar
   institution-calendar-cambridge-university
   institution-calendar-oxford-university)
  :config
  (setopt institution-calendar-entity 'oxford-university)
  (setopt institution-calendar-include-extra-week-numbers t)
  (setopt institution-calendar-include-intermonth-header nil)

  ;; If you want to permanently change what M-x calendar shows, enable
  ;; this mode.  Otherwise, use the relevant command from the
  ;; :commands listed above.
  (institution-calendar-mode 1))

Sources

]]>
Emacs: doric-themes version 1.0.0 Minimalist themes for GNU Emacs to complement my ef-themes (maximalist) and modus-themes (moderate). Mon, 09 Feb 2026 00:00:00 +0000 https://protesilaos.com/codelog/2026-02-09-emacs-doric-themes-1-0-0/ https://protesilaos.com/codelog/2026-02-09-emacs-doric-themes-1-0-0/ These are my minimalist themes. They use few colours and will appear mostly monochromatic in many contexts. Styles involve the careful use of typography, such as italics and bold italics.

If you want maximalist themes in terms of colour, check my ef-themes package. For something in-between, which I would consider the best “default theme” for a text editor, opt for my modus-themes.

Below are the release notes.


Version 1.0.0 on 2026-02-09

Two new themes

doric-jade is a light theme with a predominantly green feel.

doric-copper is a dark theme with orange, magenta, and cyan colours.

I have update all screenshots: https://protesilaos.com/emacs/doric-themes-pictures.

Revised styles for Org TODO and DONE

The relevant faces now use a colour-coding scheme where TODO states are rendered in red while DONE are green.

This is done to ensure cross-theme consistency. Those faces communicate a certain state and, therefore, it is better to not have to relearn which colour means what while switching between the Doric themes.

Org ~code~ faces stand out more

This is done to differentiate them from =verbatim=. It is especially important for users who choose to hide the markup with the user option org-hide-emphasis-markers (I used to do that but realised that the ambiguity was a problem in many cases, because ~code~ and =verbatim= have different semantics in some exported formats).

Refinements to all Org heading or heading-like faces

This covers the regular Org headings as well as anything that performs the same function, such as in the Org agenda buffer.

All regular headings use the main foreground value. The document title and the Org agenda equivalent of that are rendered in an accent colour for greater effect.

Combined with the aforementioned revision of the TODO and DONE states, Org buffers are easier to read and work with.

Tweaks for the Org agenda faces

The faces that communicate the current time and applicable filters are made more intense. The idea is to spot them more quickly.

Faces that pertain to diary or diary-style events no longer use italics to avoid exaggerations.

Blocked tasks are easier to spot.

The applicable query in the structure header is made more prominent.

Overall, Org agenda buffers should be easier to scan.

More obvious style for Org exporting

The active/available keys in the Org export dispatcher use more intense colours and have greater padding around them. This is what I also do with the Modus themes (and all derivatives) to improve the legibility of those keys.

Magit branch and author faces are redone

The authors in log views and elsewhere have a distinct colour to stand out a bit more. Branches use consistent typography, while the current branch stands out more than the others.

New colours for transient faces with background values

Enabled and disabled keys use a green-red coding scheme.

Active values and arguments have a style that is the same across themes for the same reason as Org TODO and DONE.

Transient headings use the main foreground colour to not draw more attention than they need to.

Git commit faces follow the aforementioned patterns

Those are seen when writing a commit message in Magit.

VC logs better differentiate the commit author

The relevant face uses a distinct foreground. It no longer applies a bold weight, as that had the effect of making the buffers much busier than necessary.

Colour-coded styles for Dired marks

Items that are marked for selection are rendered in a green style, while those marked for deletion are red.

This is done for cross-theme consistency, so that users do not have to think twice before performing the relevant operations.

The doric-themes-with-colors macro for advanced users

This macro is effectively the same as a let for binding the colours of the active Doric theme. Advanced users can rely on this macro to write functions that, for example, set the theme-specific red colour value of a given face.

Miscellaneous

Symlinks in Dired buffers are easier to spot. Same for visited links in Info buffers.

Org definitions no longer override the foreground of any other face present in them. Same for the notmuch header in view buffers.

]]>
Emacs: new Doric themes ‘doric-jade’ and ‘doric-copper’ I am developing two new themes for my minimalistic 'doric-themes' package for Emacs. Thu, 05 Feb 2026 00:00:00 +0000 https://protesilaos.com/codelog/2026-02-05-emacs-new-doric-themes-jade-copper/ https://protesilaos.com/codelog/2026-02-05-emacs-new-doric-themes-jade-copper/ I have added two new themes to my minimalist doric-themes package. The collection is growing to cover styles that range from austere to playful.

doric-jade is a light theme with an emphais on green. doric-copper is a dark theme with mostly orange accents and hints of patina. Both themes retain the Doric quality of using few colours while relying on typography to establish rhythm and structure.

Below are their samples.

[ Or just check all the pictures: https://protesilaos.com/emacs/doric-themes-pictures. ]

doric-jade

doric-jade theme sample

doric-jade theme sample

doric-jade theme sample

doric-jade theme sample

doric-copper

doric-copper theme sample

doric-copper theme sample

doric-copper theme sample

doric-copper theme sample

Coming in doric-themes version 0.7.0

Both doric-jade and doric-copper are in-development. I have already worked on their finer point, but may still make some tweaks before publishing them as part of the next stable version of the doric-themes.

About the Doric themes

The Doric themes use few colours and will appear monochromatic in many contexts. They are my most minimalist themes. Styles involve the careful use of typographic features and subtleties in colour gradients to establish a consistent rhythm. Legibility is still high.

If you want maximalist themes in terms of colour, check my ef-themes package. For something in-between, which I would consider the best “default theme” for a text editor, opt for my modus-themes.

]]>
Emacs: beframe version 1.5.0 Information about the latest version of my beframe package for GNU Emacs. Wed, 04 Feb 2026 00:00:00 +0000 https://protesilaos.com/codelog/2026-02-04-emacs-beframe-1-5-0/ https://protesilaos.com/codelog/2026-02-04-emacs-beframe-1-5-0/ beframe enables a frame-oriented Emacs workflow where each frame has access only to the list of buffers visited therein. In the interest of brevity, we call buffers that belong to frames “beframed”.

Below are the release notes


Version 1.5.0 on 2026-02-04

This version fixes two bugs and makes other minor tweaks.

The first bug pertains to the performance of the command beframe-switch-buffer or the command switch-to-buffer when beframe-mode is enabled: they were really slow when the list of buffers was long. Now they are always fast. Thanks to Alexandre Rousseau for reporting the problem in issue 17: https://github.com/protesilaos/beframe/issues/17.

The second bug is more subtle. It is about persisting the completion metadata category value in all prompts that read a buffer, when beframe-mode is enabled. This change means that users who configure the user option completion-category-overrides will not get the expected results in buffer prompts affected by Beframe.

Thanks to Stefan Monnier for commenting on the initial implementation, specifically telling me that let binding the metadata can affect nested minibuffers, which we do not want. This was done on the emacs-devel mailing list: https://lists.gnu.org/archive/html/emacs-devel/2025-12/msg00264.html.

]]>
Emacs: ef-themes version 2.1.0 Information about the latest version of my colourful-yet-legible themes for GNU Emacs. Tue, 27 Jan 2026 00:00:00 +0000 https://protesilaos.com/codelog/2026-01-27-emacs-ef-themes-2-1-0/ https://protesilaos.com/codelog/2026-01-27-emacs-ef-themes-2-1-0/ The ef-themes are a collection of light and dark themes for GNU Emacs that provide colourful (“pretty”) yet legible options for users who want something with a bit more flair than the modus-themes (also designed by me).

Below are the release notes.


Version 2.1.0 on 2026-01-27

This version introduces two carefully designed, legible and colourful themes: ef-orange (light) and ef-fig (dark). Both draw inspiration from the fruits they are name after.

The convenience commands ef-themes-select-dark and ef-themes-select-light use the minibuffer to select+load an Ef theme that is either dark or light, respectively. The more general command is ef-themes-select.

All screen shots of the themes are updated to reflect their current status: https://protesilaos.com/emacs/ef-themes-pictures.

Remember that since version 2.0.0 the ef-themes are built on top of my modus-themes. This means that most of the changes happen to Modus and are inherited by Ef.

]]>
Emacs: tmr version 1.3.0 Information about the latest version of my TMR package for GNU Emacs. Sun, 25 Jan 2026 00:00:00 +0000 https://protesilaos.com/codelog/2026-01-25-emacs-tmr-1-3-0/ https://protesilaos.com/codelog/2026-01-25-emacs-tmr-1-3-0/ TMR provides facilities for setting timers using a convenient notation. Lots of commands are available to operate on timers, while there also exists a tabulated view to display all timers in a nice grid.

Below are the release notes.


Version 1.3.0 on 2026-01-25

This version adds some user options and new features to an already stable package.

Timers can be paused

The command tmr-toggle-pause will prompt for a running timer and pause it.

Users who have something like the following in their configuration, have access to tmr-toggle-pause under the P key:

;; All TMR commands are behind this prefix key.  So `tmr-toggle-pause' is C-c t P.
(define-key global-map (kbd "C-c t") #'tmr-prefix-map)

In the buffer produced by the command tmr-tabulated-view the pause functionality applies to the timer at point. The tmr-toggle-pause is invoked with the P key.

An extra column in the tabulated view shows whether a timer is paused or not. Here is an example:

Start      End        Duration   Remaining  Paused?  Acknowledge?   Description

08:49:41   09:19:46   30m        29m 17s    Yes                     Work on TMR for 30 minutes
08:49:31   08:54:31   5m         3m 53s                             Prepare tea
08:49:21   08:59:21   10m        8m 42s              Yes            Edit the description with this one instead

Configure the confirmation text for acknowledgements

When a timer is set to be acknowledged (i.e. the user must confirm that they saw it elapse) it prompts for confirmation. The default input text that confirms the acknowledgement is ack. This is now subject to configuration via the user option tmr-acknowledge-timer-text.

Change how frequently the tabulated list is refreshed

The buffer produced by tmr-tabulated-view is set to automatically refresh every 5 seconds by default. In previous versions this was every 1 second. The new user option tmr-tabulated-refresh-interval can be set to a number of seconds or nil. In the latter case, the automatic refresh is disabled.

Removed the long-obsolete tmr-tabulated.el

Its code was merged into tmr.el on 2024-10-30 and all it was doing thenceforth is issue a warning to those who would require the tmr-tabulated feature. Now (require 'tmr-tabulated) produces an error.

]]>
Emacs: easily set timers with TMR Video demo of my 'tmr' package for Emacs. It helps you set timers interactively and provides relevant utilities. Mon, 19 Jan 2026 00:00:00 +0000 https://protesilaos.com/codelog/2026-01-19-emacs-timers-tmr-demo/ https://protesilaos.com/codelog/2026-01-19-emacs-timers-tmr-demo/ Raw link: https://www.youtube.com/watch?v=vLuyt0hq4io

In this ~15-minute video I demonstrate a package of mine called tmr (pronounced as an acronym or as “timer”). It uses a simple notation to set the duration of a timer at the minibuffer prompt. Once the timer elapses, Emacs shows a notification. The desktop environment will also include one, as well as an audio alert (those are configurable). Timers can optionally have a description. They may also be listed in a tabulated/grid view, which makes it easier to work with them (to edit their description, reschedule them, etc.). Running timers may also be displayed on the mode line.

Sample configuration

(use-package tmr
  :ensure t
  :config
  (define-key global-map (kbd "C-c t") #'tmr-prefix-map)
  (setq tmr-sound-file "/usr/share/sounds/freedesktop/stereo/alarm-clock-elapsed.oga"
        tmr-notification-urgency 'normal
        tmr-description-list 'tmr-description-history))

TMR sources

]]>
Emacs: notmuch-indicator version 1.3.0 Information about my notmuch email counter for the mode line of GNU Emacs. Sun, 18 Jan 2026 00:00:00 +0000 https://protesilaos.com/codelog/2026-01-18-emacs-notmuch-indicator-1-3-0/ https://protesilaos.com/codelog/2026-01-18-emacs-notmuch-indicator-1-3-0/ This package renders an indicator with an email count of the notmuch index on the Emacs mode line. The underlying mechanism is that of notmuch-count(1), which is used to find the number of items that match the given search terms. In practice, the user can define one or more searches and display their counters. These form a string which realistically is like: @50 😱1000 ♥️0 for unread messages, bills, and fan letters, respectively.

Below are the release notes.


1.3.0 on 2026-01-18

This version adds quality-of-life refinements to a stable package.

The notmuch-indicator-mode sets up the notmuch-after-tag-hook

The indicator will be updated whenever a message’s tags change. This way users do not need to rely on the timer-based method that we have always had.

The notmuch-indicator-refresh-count can be set to nil

Doing so has the effect of disabling the timer-based refresh of the indicator. It will now be updated only when some event happens, such as with the aforementioned change to tags or after the invocation of any of the commands listed in the user option notmuch-indicator-force-refresh-commands.

More configuration file paths

When checking for the notmuch configuration file, we now also consider these two filesystem paths:

  • $HOME/.config/notmuch/$NOTMUCH_PROFILE/config
  • $HOME/.config/notmuch/default/config

Thanks to Yejun Su for the contribution in pull request 6: https://github.com/protesilaos/notmuch-indicator/pull/6.

The change is small, meaning that Yejun Su does not need to assign copyright to the Free Software Foundation.

]]>
Emacs: doric-themes version 0.6.0 Minimalist themes for GNU Emacs to complement my ef-themes (maximalist) and modus-themes (moderate). Sat, 17 Jan 2026 00:00:00 +0000 https://protesilaos.com/codelog/2026-01-17-emacs-doric-themes-0-6-0/ https://protesilaos.com/codelog/2026-01-17-emacs-doric-themes-0-6-0/ These are my minimalist themes. They use few colours and will appear mostly monochromatic in many contexts. Styles involve the careful use of typography, such as italics and bold italics.

If you want maximalist themes in terms of colour, check my ef-themes package. For something in-between, which I would consider the best “default theme” for a text editor, opt for my modus-themes.

Below are the release notes.


Version 0.6.0 on 2026-01-17

This version adds support for more packages, while it revises some of the faces that were already covered.

Enhanced completion interface

The minibuffer prompt used by the command doric-themes-select now groups themes by their light or dark type. The current theme is at the top.

Avy highlights are easier to spot

The highlights generated by the various commands of the avy package now have a slightly more intense background+foreground colour combination. It should be easier to spot and to differentiate from other highlights such as that of hl-line-mode and the mouse hover effect over links.

Support for all the tmr faces

My tmr package styles timers in its grid/tabulated interface as well as on the mode line. All these now get colours that come directly from the active Doric theme. Before, the colours were defined only in the tmr source code: they were “okay” (because they are based on my modus-themes) but not stylistically optimal.

Support for ruler-mode

The built-in ruler-mode draws a ruler at the top of the current buffer. All of its faces now use appropriate colours.

Trailing spaces have a more refined colour

All packages that have a face that is about highlighting trailing spaces now get a red colour value that is more appropriate for each Doric theme.

SHR buffers can use proportionately spaced fonts

I removed an override for the built-in shr-text face, which was making the nov package display its buffers in a monospaced font.

Thanks to Marcus Kammer for telling that nov-mode buffers were not proportionately spaced by default. This was done in issue 23: https://github.com/protesilaos/doric-themes/issues/23.

]]>
Emacs: my ‘oxford-calendar’ package My new package for Emacs to display Oxford University academic terms in the 'M-x calendar'. Fri, 09 Jan 2026 00:00:00 +0000 https://protesilaos.com/codelog/2026-01-09-emacs-oxford-calendar-package/ https://protesilaos.com/codelog/2026-01-09-emacs-oxford-calendar-package/ UPDATE 2026-02-11 23:08 +0200: This package is discontinued and superseded by my institution-calendar: https://protesilaos.com/codelog/2026-02-11-emacs-institution-calendar/.


The oxford-calendar is a small package that is of interest to students, academics, and staff of the University of Oxford. It augments the M-x calendar buffer with indicators that show the applicable term (Michaelmas, Hilary, Trinity) and week number.

Oxford calendar for Emacs

To show the indicators, enable the oxford-calendar-mode. By default, it includes the extra weeks 0 and 9 at the boundaries of each term. The idea is to make things easier for planning purposes. Remove those extra weeks by setting oxford-calendar-include-extra-week-numbers to nil.

To include a heading above the term indicators, set the user option oxford-calendar-include-intermonth-header to a non-nil value.

I will now do the work to include the package on the GNU ELPA archive.

Sources

]]>
Emacs: Substitute version 0.5.0 Information about the latest version of my 'substitute' package for Emacs. Mon, 05 Jan 2026 00:00:00 +0000 https://protesilaos.com/codelog/2026-01-05-emacs-substitute-0-5-0/ https://protesilaos.com/codelog/2026-01-05-emacs-substitute-0-5-0/ Substitute provides a set of commands that perform text replacement (i) throughout the buffer, (ii) limited to the current definition (per narrow-to-defun), (iii) from point to the end of the buffer, and (iv) from point to the beginning of the buffer. Variations of these scopes are also available.

These substitutions are meant to be as quick as possible and, as such, differ from the standard query-replace (which I still use when necessary). The provided commands prompt for substitute text and perform the substitution outright, without moving the point. The target is the symbol/word at point or the text corresponding to the currently marked region. All matches in the given scope are highlighted by default.

Below are the release notes.


Version 0.5.0 on 2026-01-05

This is a small release that fixes a bug and adds a relevant user option.

The bug pertained to the scope of the substitution when buffer narrowing was in effect. All commands would ignore narrowing and also fail to properly clear the highlights they apply (highlights are transiently in effect to show what the target of the substitution is while the minibuffer is waiting for user input).

Now all commands do the right thing with respect to buffer narrowing. Though their exact behaviour depends on the value of the new user option substitute-ignore-narrowing:

  • When the value of substitute-ignore-narrowing is non-nil, then substitutions apply to the actual scope of the given command. For example, substitute-target-in-buffer will cover the whole buffer from the absolute minimum position to the absolute maximum position even if narrowing is in effect.

  • When the value of substitute-ignore-narrowing is nil, then substitutions apply to their scope subject to the boundaries of the narrowed buffer. For example, substitute-target-in-buffer will understand as “whole buffer” the region between the minimum and maximum positions of the narrowed buffer.

Users can write small convenience commands that do either of those, depending on preference. For example:

(defun my-substitute-target-in-buffer-with-narrowing ()
  "Call `substitute-target-in-buffer' with `substitute-ignore-narrowing' as `nil'."
  (let ((substitute-ignore-narrowing nil))
    (call-interactively 'substitute-target-in-buffer)))

(defun my-substitute-target-in-buffer-without-narrowing ()
  "Call `substitute-target-in-buffer' with `substitute-ignore-narrowing' as non-`nil'."
  (let ((substitute-ignore-narrowing t))
    (call-interactively 'substitute-target-in-buffer)))

Thanks to zauberen for reporting the bug in issue 11: https://github.com/protesilaos/substitute/issues/11.

]]>
Emacs: ef-orange and ef-fig are part of the ef-themes I added a new light and dark theme to my 'ef-themes' package for Emacs. Sun, 04 Jan 2026 00:00:00 +0000 https://protesilaos.com/codelog/2026-01-04-emacs-ef-orange-fig-themes/ https://protesilaos.com/codelog/2026-01-04-emacs-ef-orange-fig-themes/ I just added two new themes to my ef-themes package. ef-orange is a light theme with a noticeably tinted background that combines orange, yellow, and green hues. ef-fig is a dark theme with a dark purple background that relies on green, yellow, and pink hues.

Sample pictures are available below. Check all the items here: https://protesilaos.com/emacs/ef-themes-pictures. Always click to enlarge the image for best results.

ef-orange

ef-orange theme sample

ef-orange theme git sample

ef-orange theme mail sample

ef-orange theme org sample

ef-fig

ef-fig theme sample

ef-fig theme git sample

ef-fig theme mail sample

ef-fig theme org sample

Coming in version 2.1.0 (next stable release)

Both themes are done. Though there may still be some minor refinements. They will be widely available as part of the next stable version of the ef-themes package (maybe end of January 2026).

Remember that since version 2.0.0, the ef-themes are built on top of my modus-themes. This means that they are highly customisable and support a wide range of packages and face groups.

Enjoy!


The ef-themes are a collection of light and dark themes for GNU Emacs that provide colourful (“pretty”) yet legible options for users who want something with a bit more flair than the modus-themes (also designed by me).

]]>
Emacs: modus-themes version 5.2.0 Information about the latest version of my highly accessible themes for GNU Emacs. Wed, 31 Dec 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-12-31-emacs-modus-themes-5-2-0/ https://protesilaos.com/codelog/2025-12-31-emacs-modus-themes-5-2-0/ I just published the latest stable release of the Modus themes. The change log entry is reproduced further below. For any questions, you are welcome to contact me. I will now work to apply these same changes to emacs.git, so please wait a little longer for the updates to trickle down to you.


5.2.0 on 2025-12-31

This version fixes some bugs, adds a new feature for those who want to derive a theme from Modus, and makes other small quality-of-life refinements.

The modus-themes-with-colors should work at all times

In the transition to version 5.0.0, I inadvertently introduced regressions to the behaviour of the modus-themes-with-colors macro. This macro let binds the current theme’s palette around arbitrary Elisp expressions, which allows users to access the named colours therein. In versions 5.0.0 and 5.1.0 the macro could not read variables defined outside its scope. Users needed to write an eval around it, which I did not like. Now the macro should not require such workarounds: it basically is a let that should work as expected everywhere.

This was fixed over a series of Git commits related to issue 170: https://github.com/protesilaos/modus-themes/issues/170. Thanks to Alexandr Semenov and realazy for reporting the problems and testing my revisions.

The modus-themes-generate-palette function to quickly get a palette

Users or package developers who want to create a theme on top of Modus can now get a kickstart by defining their palette with the help of the new modus-themes-generate-palette function. This function is meant to return a complete palette, given a list of basic colours. Users can thus experiment with their new theme while knowing that what they got contains all the definitions; definitions that they may then modify further (e.g. to define different semantic mappings than the defaults such as, for example, to have (fg-heading-1 red-warmer) instead of what originally is (fg-heading-1 fg-main)).

I have written extensive documentation in the manual, which includes a complete example of a Solarized theme that is built on top of Modus. If you have any questions, you are welcome to contact me.

Convenience commands to select only dark or light themes

The commands modus-themes-select-dark and modus-themes-select-light use minibuffer completion to load a theme. The completion candidates are filtered to only dark or light themes, respectively.

This is effectively the same as calling the command modus-themes-select with a prefix argument (C-u by default).

Remember that we also have the commands modus-themes-load-random, modus-themes-load-random-dark, and modus-themes-load-random-light. Otherwise use the command modus-themes-rotate.

Improved prompt for theme selection

The minibuffer prompt used by the various Modus commands to select a theme now has a grouping function in place: it shows the current theme at the top and then all other themes grouped by their dark or light background. This makes it easier to find a relevant theme, especially if lots of them are present, such as when modus-themes-include-derivatives-mode is enabled and relevant packages/themes are available (e.g. my ef-themes and standard-themes).

Semantic colours for transient.el (e.g. in Magit)

The transient.el concept of “semantic colours” is now supported. This is used by default in Magit to denote the different types of keys, such as those that exit the transient, keep it active, move to another transient, and the like. Users who prefer the old style where all key bindings looked the same must customise the user option transient-semantic-coloring.

Note that the deuteranopia- and tritanopia- optimised themes adapt gracefully to such “semantics”, owning to relevant internal refinements I made. Those themes cannot rely on the full colour spectrum to communicate such nuances.

All hl-todo-mode faces use a bold weight if appropriate

When the user option modus-themes-bold-constructs is set to a non-nil value, then all keywords that hl-todo-mode highlights will be rendered in a bold weight (technically, they inherit the bold face). This is how we were doing it before until I undid it by mistake. Thanks to Dominik Schrempf for reporting the bug in issue 177: https://github.com/protesilaos/modus-themes/issues/177.

Theme-sensitive colours for Gnus mail groups

The Gnus mail groups no longer have hardcoded colour values. They will look different depending on the current Modus theme.

Faces that set a :box attribute handle unspecified colours

I updated all faces that use a :box attribute to account for the scenario of a user writing palette overrides that unset the relevant colour. Thanks to JD Smith for reporting a bug along those lines in issue 9 of my standard-themes repository (they are derived from the modus-themes, hence the changes here): https://github.com/protesilaos/standard-themes/issues/9.

The calendar-today and org-date-selected faces are disambiguated

These two faces are no longer using the same styles. This is because they can appear in the same buffer. Thanks to Rudolf Adamkovič for discussing this with me in the context of the same change for my doric-themes (issue 20 in doric-themes.git): https://github.com/protesilaos/doric-themes/issues/20.

The Modus “current theme” respects multiple enabled themes

The Modus concept of “current theme” respects the user’s choice for multiple themes loaded at once. It will return the first Modus theme even if it is not at the front of the list.

[ Emacs will load multiple themes by default, which leads to awkward colour combinations, unless you know what you are doing—as such all the Modus commands that load a theme will disable all others, subject to the user option modus-themes-disable-other-themes. ]

Thanks to Pierre Téchoueyres for reporting the scenario where multiple other themes are loaded on top of a Modus theme. This was done in issue 182: https://github.com/protesilaos/modus-themes/issues/182.

Also thanks to Pierre for covering another snippet that I had missed. This was done in pull request 184: https://github.com/protesilaos/modus-themes/pull/184.

Pierre has assigned copyright to the Free Software Foundation.

Fixed symbol of inherited AUCTeX face

There was a typo which caused an error. Thanks to Rudolf Adamkovič for the patch and also for providing a relevant unit test. This was done in pull request 188: https://github.com/protesilaos/modus-themes/pull/188.

Rudolf has assigned copyright to the Free Software Foundation.

Miscellaneous

  • Thanks to Basil L. Contovounesios for simplifying a couple of expressions. This was done in pull request 190: https://github.com/protesilaos/modus-themes/pull/190. Basil has assigned copyright to the Free Software Foundation.

  • The faces of the built-in completion-preview-mode are now supported. Thanks to Kevin Fleming for asking me about this in issue 178: https://github.com/protesilaos/modus-themes/issues/178.

  • Several faces that had a strike-through effect when they did not really need it are revised to use a wavy underline instead. The idea is to let the text be readable at all times, regardless of the effective font family. With the strike-through effect, some fonts completely obscure the underlying text.Thanks to Morgan Willcock for discussing with me the use of the strike-through style in issue 169: https://github.com/protesilaos/modus-themes/issues/169.

  • All symbol-overlay faces are unique, fixing a mistake I had done before.

  • The org-dispatcher-highlight, which is used to highlight the keys of the Org export interface, now uses the appropriate foreground colour and is always rendered in a bold weight.

  • The org-habit faces no longer call the function readable-foreground-color. This is because that function does not work if the theme is loaded via the early-init.el. Thanks to Gaston Cabotin for reporting the problem in issue 174: https://github.com/protesilaos/modus-themes/issues/174.

  • The gnus-button, which Gnus uses in all sorts of places to mark some text as clickable, is styled with a less intense underline and will no longer follow the style of links, including possible palette overrides. This way, Gnus article buffers will not have visual noise. Thanks to Morgan Willcock for discussing this with me in issue 140: https://github.com/protesilaos/modus-themes/issues/140.

]]>
Emacs Lisp Elements: EPUB and PDF versions now available My free book on the Emacs Lisp programming language is now available in EPUB and PDF formats. Sat, 27 Dec 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-12-27-emacs-lisp-elements-epub-pdf/ https://protesilaos.com/codelog/2025-12-27-emacs-lisp-elements-epub-pdf/ I just added .epub and .pdf versions of my free book Emacs Lisp Elements. All files are available in the Git repository: https://github.com/protesilaos/emacs-lisp-elements.

I produced both of those from the source Org file. Here are the steps for posterity:

  • From the elispelem.org use the Org export mechanism to generate an Info manual (by default: C-c C-e i i).
  • This will generate a .texi file, which is then used as the source for the .info file.
  • From the command-line do texi2any --epub elispelem.texi to get the EPUB file.
  • For the PDF, install the dependencies with something like sudo apt install texlive.
  • Finally, run texi2any --pdf elispelem.texi.
]]>
Emacs: refinements to the Denote file prompt Information about the new Denote file prompt and a screenshot of how it looks like. Tue, 16 Dec 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-12-16-emacs-denote-file-prompt-refinements/ https://protesilaos.com/codelog/2025-12-16-emacs-denote-file-prompt-refinements/ As part of the current development cycle of Denote, I am refining the file prompt. It now has the following:

  • Sorting: Files are sorted by last modified.
  • Grouping: Files are organised by type (remember that the Denote file-naming scheme can be applied to any file—I do so for videos, pictures, PDFs, …).
  • Affixating: Files have their date identifier as a prefix and their keywords as a suffix.

The file prompt is used when linking to a file, like with the denote-link command, or when calling the command denote-open-or-create (and related).

The old style

File names were presented as relative paths without further modifications. This style relies on the Denote file-naming scheme to narrow down the list by typing. For example 202512 finds all files with that in their identifier (i.e. their creation date by default), _emacs finds all files with the given keyword, and -word with that word in their title.

Denote old file prompt

The new style

The file names are still the same behind the scenes, but their data is presented in a more readable way. There is no loss of functionality, meaning that users can still match _keyword, -title, and the like, per the Denote file-naming scheme.

Denote new file prompt

Part of development

I might make further changes, though the idea is clear. Expect to get similar features in my other packages, such as consult-denote, denote-sequence, denote-journal.

For the denote-sequence package, in particular, the file prompt it uses shows sequences instead of identifiers as the prefix of each file. This is because that prompt is relevant for tasks where the user needs to know the exact sequence, such as when they create a note that is the child of another.

Power users can study the functions stored in the variable denote-file-prompt-extra-metadata (same idea for the denote-sequence package: denote-sequence-file-prompt-extra-metadata).

About Denote

Denote is a simple note-taking tool for Emacs. It is based on the idea that notes should follow a predictable and descriptive file-naming scheme. The file name must offer a clear indication of what the note is about, without reference to any other metadata. Denote basically streamlines the creation of such files while providing facilities to link between them.

Denote’s file-naming scheme is not limited to “notes”. It can be used for all types of file, including those that are not editable in Emacs, such as videos. Naming files in a consistent way makes their filtering and retrieval considerably easier. Denote provides relevant facilities to rename files, regardless of file type.

]]>
Emacs: spacious-padding version 0.8.0 Information about the latest version of my 'spacious-padding' package for GNU Emacs. Sat, 13 Dec 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-12-13-emacs-spacious-padding-0-8-0/ https://protesilaos.com/codelog/2025-12-13-emacs-spacious-padding-0-8-0/ This package provides a global minor mode to increase the spacing/padding of Emacs windows and frames. The idea is to make editing and reading feel more comfortable. Enable the mode with M-x spacious-padding-mode. Adjust the exact spacing values by modifying the user option spacious-padding-widths.


This release introduces some nice refinements and fixes a couple of subtle bugs.

Subtle mode and header line

The new user option spacious-padding-subtle-frame-lines supersedes the ~spacious-padding-subtle-mode-line. It does the same thing, namely, of making the mode lines use only a thin line instead of a background. Though it extends this feature to header lines as well.

The documentation string of spacious-padding-subtle-frame-lines describes the technicalities and includes examples. In short, we can associate a keyword with either a face that has a foreground color or a color value directly. For the convenience of the user, the package also defines the faces spacious-padding-line-active and spacious-padding-line-inactive. Here is a sample configuration:

;; Read the doc string of `spacious-padding-subtle-mode-line' as it
;; is very flexible.  Here we make the mode lines be a single
;; overline, while header lines have an underline.
(setq spacious-padding-subtle-frame-lines
      '( :mode-line-active spacious-padding-line-active
         :mode-line-inactive spacious-padding-line-inactive
         :header-line-active spacious-padding-line-active
         :header-line-inactive spacious-padding-line-inactive))

In the future, we might decide that other elements can benefit from this style.

The header line underline is spaced further away from the text

As noted above, when spacious-padding-subtle-frame-lines is configured to cover header lines, those will be drawn with an underline. This will not intersect with the text of the header line.

Normally, underlines cut through letters that descend below the baseline, such as the letters g and y. We choose to avoid that because it makes for a cleaner interface (though I personally think it is not a good style for paragraph text, because of the rivers of negative space it introduces).

This specific design is available for Emacs version 29 or higher. Users of Emacs 28 must set x-underline-at-descent-line to a non-nil value. Though note that this has a global effect: we cannot limit it to a single face.

Thanks to Steven Allen for covering this in pull request 37: https://github.com/protesilaos/spacious-padding/pull/37. Steven has assigned copyright to the Free Software Foundation.

The spacious-padding-widths can affect Custom buttons

This is about the buttons we find in buffers of the Custom system. For example, we get such a buffer after we do M-x customize.

The relevant keyword is :custom-button-width. It is set to a number of spaces for padding. Here is the default value and, as always, the documentation cover the details:

(setq spacious-padding-widths
      '( :internal-border-width 15
         :header-line-width 4
         :mode-line-width 6
         :custom-button-width 3 ; the new one
         :tab-width 4
         :right-divider-width 30
         :scroll-bar-width 8
         :fringe-width 8))

Fixes for the Emacs daemon

There were reports about incorrect face specifications that could happen when Emacs was started as a daemon process. I made the relevant changes. Also thanks to kaibagley for covering a line I had missed. This was done in pull request 43: https://github.com/protesilaos/spacious-padding/pull/43.

Related threads:

]]>
‘Emacs Lisp Elements’ book version 2 Information about the latest version of my 'Emacs Lisp Elements' book. Wed, 10 Dec 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-12-10-emacs-lisp-elements-book-version-2/ https://protesilaos.com/codelog/2025-12-10-emacs-lisp-elements-book-version-2/ I just published a new version of my Emacs Lisp Elements. Below are the release notes.


Emacs Lisp Elements version 2.0.0

This is a major rewrite of the book. It has almost doubled in word count. I explain more concepts and do it from the ground up. Every single one of the original chapters is redone. They now contain insights into functionality they would previously hint at, such as how apply works in practice, what a non-local exit is, and how recursive editing is done.

I have also added several new chapters. As before, chapters have cross references, so you will benefit from revisiting relevant topics.

If you read the Info version of the book, note that all functions, variables, and concepts have their own indices. Use those as another means of navigating the book’s contents. To read the Info version, clone the Git repository, use M-x dired to open its directory, move the cursor over the file elispelem.info and do M-x dired-info.

What follows is a brief description of the new chapters.

  • Basics of how Lisp works: A step-by-step guide to how Lisp code is written and how Emacs can tell apart a function call from a variable even when those have the same symbol.

  • Introspecting Emacs: Explores some of the ways we can learn about the present state of Emacs. The idea is to develop the habit of asking Emacs about itself before we do an online search. This way we can also expose ourselves to Elisp code, which helps us become better programmers.

  • Add metadata to symbols: An explanation of how we can associate symbols with data that can then be used for further computations.

  • What are major and minor modes: Presents the basics of modes in Emacs. It explains what major and minor modes have in common and how they differ, while also discussing relevant concepts of precedence.

  • Hooks and the advice mechanism: Explains what are hooks and how they work. It also covers the powerful advice mechanism, as some uses of it as similar to what hooks are supposed to do.

  • Autoloading symbols: Shows how Emacs manages to “lazy load” code when it needs to. This is especially helpful for package developers.

  • Emacs as a computing environment: A more general view of Emacs that helps us appreciate the value of Emacs Lisp. The more time we put into learning this programming language, the better we will get at controlling large parts of our computing life through Emacs.

]]>
Emacs: pulsar version 1.3.0 Information about the latest version of my pulsar package for GNU Emacs. Sun, 30 Nov 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-11-30-emacs-pulsar-1-3-0/ https://protesilaos.com/codelog/2025-11-30-emacs-pulsar-1-3-0/ This is a small Emacs package that automatically highlights the current line after certain functions are invoked. It can also highlight a line or region on demand. The idea is to make it easier to find where the point is, what was affected, and also to bring attention to something in a buffer. Watch the original demo (2022-03-14).

Below are the release notes.


Version 1.3.0 on 2025-11-30

This version introduces a new feature and makes small refinements to an already reliable base.

Permanent static highlight for a line or region

In the most common use-case, Pulsar produces a highlight that fades in and out of view after a certain amount of time. The idea with such a “pulse effect” is to quickly get a sense of where the cursor is when some change occurs (e.g. switching to another window).

The permanent static highlights differ from pulse effects in two ways: (i) they do not have a fade-in and fade-out phase and (ii) are not removed automatically. These highlights stick around either until the user removes them or their underlying text is deleted. They are meant to be used as intentional highlights, such as to draw attention to a certain statement while doing a presentation.

The command pulsar-highlight-permanently adds a permanent static highlight to the current line. When the region is active, the highlight is applied from the beginning to the end of the region.

The command pulsar-highlight-permanently-remove removes permanent static highlights from the active region or current line. This command operates on the entire buffer when it is called with a universal prefix argument (C-u by default).

The command pulsar-highlight-permanently-dwim adds a permanent static highlight if there is none or removes it if there is one. It operates on the currently active region or line at point.

Permanent static highlights are rendered with the face specified in the user option pulsar-highlight-face.

New name for temporary static highlights

The commands pulsar-highlight-dwim and pulsar-highlight-line are obsolete aliases for pulsar-highlight-temporarily.

Temporary static highlights do not have a fade-in and fade-out phase. They are automatically removed as soon as an action occurs. They are an alternative to the aforementioned permanent static highlights.

The command pulsar-highlight-temporarily will operate on the active region or the current line.

Miscellaneous

  • Thanks to Koloszár Gergely for reporting an intermediate bug where the pulse effect actually did not pulse under certain conditions. This was done in issue 31: https://github.com/protesilaos/pulsar/issues/31.

  • Parts of the code are rewritten in the interest of clarity.

  • The entire manual is redone to better organise the documentation.

]]>
Emacs: Substitute version 0.4.0 Information about the latest version of my 'substitute' package for Emacs. Sat, 29 Nov 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-11-29-emacs-substitute-0-4-0/ https://protesilaos.com/codelog/2025-11-29-emacs-substitute-0-4-0/ Substitute is a set of commands that perform text replacement (i) throughout the buffer, (ii) limited to the current definition (per narrow-to-defun), (iii) from point to the end of the buffer, and (iv) from point to the beginning of the buffer. Variations of these scopes are also available.

These substitutions are meant to be as quick as possible and, as such, differ from the standard query-replace (which I still use when necessary). The provided commands prompt for substitute text and perform the substitution outright, without moving the point. The target is the symbol/word at point or the text corresponding to the currently marked region. All matches in the given scope are highlighted by default.

Below are the release notes.


Version 0.4.0 on 2025-11-29

This version iterates on an already stable package. It introduces a few new commands while making minor internal refinements.

The new commands work exactly like those already on offer, except for their scope of application. Remember that Substitute targets either the symbol/word at point or any occurrences of the currently marked characters/text within the given scope and replaces them with the user’s input. The scope is something like “current function definition”, “current paragraph”, “from here to the end of the buffer”, et cetera. The substitution does not move the cursor.

The new commands:

  • substitute-target-in-outline: Substitute the target across the current outline level. The outline is determined by the buffer-local value of the variable outline-regexp. For example, in Org mode the current outline level includes the heading and any text below it but not any subheadings.

  • substitute-target-in-page: Like the above for the boundaries of the current page. A page is determined by the buffer-local value of the variable page-delimiter.

  • substitute-target-in-paragraph: As above for the current paragraph. Note that in programming modes a “paragraph” is not necessarily the same as with prose (where, in their simplest form, paragraphs are delimited by empty lines). Substitute highlights all matches by default, so users should notice the difference right away.

  • substitute-target-in-defun-and-below: This works in the scope of the current definition (per narrow-to-defun) but only from point onwards. It is the counterpart to the commands we always had in substitute-target-in-defun.

]]>
Emacs: new Modus themes tool to generate a complete palette There is a new function I wrote for my modus-themes that makes it easier for users to create derivative Modus themes palettes. Tue, 25 Nov 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-11-25-emacs-modus-tools-to-generate-complete-palette/ https://protesilaos.com/codelog/2025-11-25-emacs-modus-tools-to-generate-complete-palette/ [ This is of interest to users who want to create a new theme on top of Modus (for private purposes or as a package). ]

The current development target of the Modus themes includes the function modus-themes-generate-palette. I have updated the manual with a detailed, step-by-step guide on how to use that function to derive a custom theme. I am doing it with Solarized, since it is well-known. Start here: https://protesilaos.com/emacs/modus-themes#h:3a7ede17-f0d4-4322-8e69-1804ed69012b

The reason I wrote this function is to make it easier for users to get started with their Modus ports. The common workflow is for someone to copy a colour scheme from their favourite terminal emulator and use it as a starting point for their Emacs theme. Modus will do the heavy lifting in the background.

modus-themes-generate-palette returns a fully fledged Modus palette: the literal hundreds of entries are all defined, even if we only give it a couple of colour values. The more colours we specify, the more defined the character of the resulting palette will be—and we have complete control, as the manual demonstrates.

A good starting point is to provide values for the main background (bg-main), main foreground (fg-main), and the basic hues of red, green, yellow, blue, magenta, and cyan.

Options for power users are available. Though the point is to lower the barrier to entry for those who want to start with something tolerable. Then they can trust that I cover everything they need to gradually evolve their theme to be as complete as core Modus.

In the manual I used Solarized as an example, with usable code snippets that you can copy+paste. Those yield a theme, if you try them. Below is a complete, albeit generic, Modus+Solarized theme. It is a decent starting point.

;; Modus+Solarized dark
(defvar modus-solarized-dark-palette
  (modus-themes-generate-palette
   '((bg-main "#073642")
     (fg-main "#EEE8D5")
     (red "#DC322F")
     (green "#859900")
     (yellow "#B58900")
     (blue "#268BD2")
     (magenta "#D33682")
     (cyan "#2AA198"))))

(modus-themes-theme
 'modus-solarized-dark
 'modus-solarized-themes
 "Sample of a basic Solarized dark port."
 'dark
 'modus-solarized-dark-palette
 nil
 nil)

Do not rush to play around with this snippet. The chapter in the manual I linked to above has much more about this topic. Take some time to read through it. You can extend the port to also map out all the colors you want. Thus:

;; Modus+Solarized dark
(defvar modus-solarized-dark-palette
  (modus-themes-generate-palette
   ;; We provide the two base colors of Solarized, plus most of its
   ;; accents.  These form the BASE-COLORS we pass as an argument.
   ;; All other color values come from those.  The BASE-COLORS here
   ;; are enough to generate a new palatte that has no traces of, say,
   ;; the `modus-vivendi' color values.
   '((bg-main "#073642")
     (fg-main "#EEE8D5")
     (red "#DC322F")
     (green "#859900")
     (yellow "#B58900")
     (blue "#268BD2")
     (magenta "#D33682")
     (cyan "#2AA198"))
   ;; The COOL-OR-WARM-PREFERENCE is derived internally based on
   ;; `bg-main'.  We can pass it here if we feel strongly about it.
   nil
   ;; If we need to specify the CORE-PALETTE from where to inherit any
   ;; missing colors and/or semantic mappings, we can give it here.
   ;; Though nil is the appropriate starting point, as the code will
   ;; handle things internally.
   nil
   ;; And here are our MAPPINGS where we can specify what values apply
   ;; to which semantic color.  The `modus-themes-list-colors' shows
   ;; them all.
   ;;
   ;; Note that in our BASE-COLORS above we never wrote what, say,
   ;; `magenta-warmer' is: it is derived programmatically from the
   ;; `magenta' we have there.  Absent that, it would be taken from
   ;; the CORE-PALETTE.
   '((cursor magenta-warmer)
     (bg-hl-line bg-blue-nuanced)
     (bg-paren-match bg-magenta-subtle)
     (bg-region bg-blue-intense)
     (fg-region fg-dim)
     (bg-mode-line-active bg-blue-nuanced)
     (fg-mode-line-active blue-warmer)
     (border-mode-line-active blue-cooler))))

(modus-themes-theme
 'modus-solarized-dark
 'modus-solarized-themes
 "Sample of a basic Solarized dark port."
 'dark
 'modus-solarized-dark-palette
 nil
 nil)

Using this infrastructure, I am confident that we can implement any colour scheme as a Modus theme—and, again, we can configure every part of it.

The manual is extensive, though remember that I remain at your disposal in case something is unclear: open an issue in the Modus themes repository or contact me and I will help you.

Sources

]]>
Emacs: doric-themes version 0.5.0 Minimalist themes for GNU Emacs to complement my ef-themes (maximalist) and modus-themes (moderate). Sun, 23 Nov 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-11-23-doric-themes-0-5-0/ https://protesilaos.com/codelog/2025-11-23-doric-themes-0-5-0/ These are my minimalist themes. They use few colours and will appear mostly monochromatic in many contexts. Styles involve the careful use of typography, such as italics and bold italics.

If you want maximalist themes in terms of colour, check my ef-themes package. For something in-between, which I would consider the best “default theme” for a text editor, opt for my modus-themes.

Below are the release notes.


Update to doric-themes 0.5.0

Enjoy the two new members of the collection

These are doric-siren and doric-mermaid. The former is a light theme while the latter is dark. Both themes offer a marine vibe combined with warm hues. Check the updated screenshots of all the Doric themes: https://protesilaos.com/emacs/doric-themes-pictures.

Support for transient.el semantic faces

Those are used when the user option transient-semantic-coloring is set to a non-nil value (the default). They are designed to indicate different types of key, such as those that keep the transient in place as opposed to exiting it.

The old style of making all key bindings look the same is still available if transient-semantic-coloring is set to nil.

Semantic Emacs Lisp faces

This is a new feature coming in Emacs 31. Users can opt in to it by setting the user option elisp-fontify-semantically to a non-nil value. When active, Emacs Lisp buffers will apply highlights to more elements of the syntax. Those will still conform with the minimalist style of the Doric themes, but users at least get the benefits of elisp-add-help-echo.

Font-lock faces for function calls and use of variables

Those are typically applied by major modes that are power by tree-sitter. Again, the styles are minimalist.

More faces or face groups are covered

These include:

  • ibuffer’s Emacs 31 faces (patched by me in emacs.git)
  • flymake’s Emacs 31 faces (again, my patch in core)
  • diff-hl package
  • git-gutter package
  • org-habit
  • minibuffer-nonselected for Emacs 31
  • eglot-highlight-symbol-face
  • ert-test-result-unexpected and ert-test-result-expected, courtesy of Rudolf Adamkovič in pull request 19: https://github.com/protesilaos/doric-themes/pull/19.

Refinements to already supported faces

  • The calendar-today and org-date-selected are similar but different enough to stand apart. I initially made them look identical because I thought they would never appear in the same context. Thanks to Rudolf Adamkovič for telling me they could actually be collocated, hence their disambiguation. This was done in issue 20: https://github.com/protesilaos/doric-themes/issues/20.

  • The transient-argument and transient-value have a background to make them easier to spot. This is because they convey information about the state of the transient interface, which typically is important.

  • Transient’s mismatching keys are dimmed out instead of being underlined, because this looks better in context.

  • Similarly, org-agenda-clocking has a more pronounced background.

  • Idem for eldoc-highlight-function-argument and its counterparts in lsp-mode and geiser.

  • The Org check boxes are rendered with a bold weight, while quote blocks are in italics. Thanks to Rudolf Adamkovič for the patch in pull request 18: https://github.com/protesilaos/doric-themes/pull/18.

  • All Notmuch cryptography-related faces have more refined styles to both stand out better while avoiding exaggerations.

  • The Custom user interface buttons inherit from variable-pitch.

  • The current line number in display-line-numbers-mode uses just a bold weight to avoid exaggerations.

]]>
Emacs: new ‘denote-merge’ package Information about my new optional extension to Denote that streamlines the work of merging contents from one file to another. Sat, 22 Nov 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-11-22-new-emacs-denote-merge/ https://protesilaos.com/codelog/2025-11-22-new-emacs-denote-merge/ The denote-merge package is an optional extension to denote. I am providing it in response to requests for functionality that streamlines the work of merging contents from one file into another. Thanks to Sia Piperea for reminding me about it, making a suggestion for region-related functions, and for testing my prototype:

The denote-merge package is a more refined implementation of those ideas, plus more. As of now, the package provides support for two broad kinds of “merging”:

  • Merge one file into another.
  • Merge a region into a file.

For merging a region, in particular, there are options and concomitant convenience commands to format the region in a certain way, such as an Org source block, a Markdown blockquote, a plain indented region, and the like.

The official manual describes the technicalities. In short, I have taken care to make the relevant commands do the right thing, including to update backlinks, annotate the contents, and establish links, where relevant.

Note that the GNU ELPA package is not available yet. I have prepared the relevant patch and am expecting everything to be done in the near future.

Please stay tuned.

Sources

]]>
Emacs: new Doric themes ‘doric-siren’ and ‘doric-mermaid’ I am developing two new themes for my minimalistic 'doric-themes' package for Emacs. These combine marine hues with some warmer accents. Mon, 17 Nov 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-11-17-emacs-new-doric-themes-siren-mermaid/ https://protesilaos.com/codelog/2025-11-17-emacs-new-doric-themes-siren-mermaid/ I am developing two new themes for my minimalistic doric-themes package for Emacs. These combine marine hues with some warmer accents, cast on a fairly prominent backdrop. doric-siren is a light theme, while doric-mermaid is dark. Below are some screenshots to give you an idea of what to expect.

[ Or just check all the pictures: https://protesilaos.com/emacs/doric-themes-pictures. ]

doric-siren

doric-siren theme sample

doric-siren theme sample

doric-siren theme sample

doric-siren theme sample

doric-mermaid

doric-mermaid theme sample

doric-mermaid theme sample

doric-mermaid theme sample

doric-mermaid theme sample

Coming in doric-themes version 0.5.0

The character of the themes is established and, in principle, I will not change them further. Though I am giving it a few more days of further testing to confirm I did not miss something. Expect these and other improvements to be available in the next stable version of the doric-themes, which I expect to publish before the end of November.

About the Doric themes

The Doric themes use few colours and will appear monochromatic in many contexts. They are my most minimalist themes. Styles involve the careful use of typographic features and subtleties in colour gradients to establish a consistent rhythm. Legibility is still high.

If you want maximalist themes in terms of colour, check my ef-themes package. For something in-between, which I would consider the best “default theme” for a text editor, opt for my modus-themes.

]]>
Emacs: complete examples for Modus themes derivatives I updated the manual of the Modus themes with complete step-by-step instructions and code samples that can be copy-pasted directly. Mon, 10 Nov 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-11-10-emacs-modus-themes-derivatives-more-doc-examples/ https://protesilaos.com/codelog/2025-11-10-emacs-modus-themes-derivatives-more-doc-examples/ I just expanded the manual of the modus-themes with complete step-by-step examples on how to define a derivative theme. Here is the commit:

commit c94938ff794d043447ed4ffe9b55f1031039f667
Author: Protesilaos Stavrou <[email protected]>
Date:   Mon Nov 10 13:02:49 2025 +0200

  Greatly expand the manual with complete examples of creating Modus derivatives

  This covers the basic and more advanced use cases. It also is for both
  private use and making new packages.

 doc/modus-themes.info | 588 +++++++++++++++++++++++++++++++++++++-------------
 doc/modus-themes.org  | 278 +++++++++++++++++++++++-
 2 files changed, 711 insertions(+), 155 deletions(-)

The relevant sections and their structure:

If something is unclear, you are welcome to contact me.

]]>
Emacs: ‘standard-themes’ version 3.0.0 Release notes for the latest version of my 'standard-themes' for GNU Emacs. Sun, 09 Nov 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-11-09-emacs-standard-themes-3-0-0/ https://protesilaos.com/codelog/2025-11-09-emacs-standard-themes-3-0-0/ The standard-themes are a collection of light and dark themes for GNU Emacs. The standard-light and standard-dark emulate the out-of-the-box looks of Emacs (which technically do NOT constitute a theme) while bringing to them thematic consistency, customizability, and extensibility. Other themes are stylistic variations of those.

In practice, the Standard themes take the default style of the font-lock and Org faces, complement it with a wider and harmonious colour palette, address many inconsistencies, and apply established semantic patterns across all interfaces by supporting a large number of packages.

Below are the release notes.


Version 3.0.0 on 2025-11-09

This major version makes Standard build on top of my Modus themes. The latter provides extensive face/package coverage and a wide range of customisation options. As a result, the Standard themes retain their design while giving more control to the user.

These release notes are essentially the same as what I wrote earlier today for my ef-themes package, which is now also built on top of my Modus themes: https://protesilaos.com/codelog/2025-11-09-emacs-ef-themes-2-0-0/.

In short:

  • User options that were provided by the Standard themes are now mere aliases for their Modus counterparts.
  • Commands that were defined by the Standard themes are now reduced to convenience wrappers that build on top of Modus.
  • The new minor mode standard-themes-take-over-modus-themes-mode can be enabled to make all Modus commands that load a theme only consider the Standard themes. This is effectively the opposite of enabling the modus-themes-include-derivatives-mode or using one of the Standard commands to load just a Standard theme (like standard-themes-rotate).
  • The manual of the Modus themes covers everything from the basics to advanced topics on how to use and customise the themes. Evaluate (info "(modus-themes) Top") or visit https://protesilaos.com/emacs/modus-themes.

You are welcome to contact me if something is unclear.

]]>
Emacs: ef-themes version 2.0.0 Information about the latest version of my colourful-yet-legible themes for GNU Emacs. Sun, 09 Nov 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-11-09-emacs-ef-themes-2-0-0/ https://protesilaos.com/codelog/2025-11-09-emacs-ef-themes-2-0-0/ The ef-themes are a collection of light and dark themes for GNU Emacs that provide colourful (“pretty”) yet legible options for users who want something with a bit more flair than the modus-themes (also designed by me).

Below are the release notes.


Version 2.0.0 on 2025-11-09

The Ef themes are now derived from my Modus themes. This means that they inherit the wide face coverage and extensive customisability of Modus, while retaining their stylistic flair.

The Ef themes no longer provide any user options of their own. Each of the options we had before is now an alias for the Modus equivalent. As part of this transition, the Ef themes actually gain new customisation options, which are documented herein.

Furthermore, the Ef themes do not define any commands to load a theme. What we had before is once again an alias for the equivalent Modus command.

The manual of the Ef themes describes these compatibility arrangements. Further documentation and code samples are available in the manual of the Modus themes:

Old user options and hooks are mere aliases for Modus options

Old name Is alias for CURRENT NAME
ef-themes-disable-other-themes modus-themes-disable-other-themes
ef-themes-to-toggle modus-themes-to-toggle
ef-themes-to-rotate modus-themes-to-rotate
ef-themes-italic-constructs modus-themes-italic-constructs
ef-themes-bold-constructs modus-themes-bold-constructs
ef-themes-variable-pitch-ui modus-themes-variable-pitch-ui
ef-themes-mixed-fonts modus-themes-mixed-fonts
ef-themes-headings modus-themes-headings
ef-themes-completions modus-themes-completions
ef-themes-prompts modus-themes-prompts
ef-themes-common-palette-overrides modus-themes-common-palette-overrides
ef-themes-post-load-hook modus-themes-after-load-theme-hook
ef-themes-after-load-theme-hook modus-themes-after-load-theme-hook

Please read their respective documentation strings.

If you use Ef and possibly other Modus derivatives, you may prefer to switch all your user options to the Modus ones. This way you can keep a unified configuration for all your themes.

Fewer bold and italic faces by default, more as an opt-in clause

In the past, the Ef themes did not provide an option to disable the extensive use of a bold font weight and italic font slant. Whereas now those are controlled by the user options modus-themes-bold-constructs and modus-themes-italic-constructs. By default, when they are nil, bold and italics are used only when necessary. Set these user options to t to have bold and italics in more places.

Loading only Ef themes with the convenience wrappers we provide

All the old commands Ef provided for loading one of its themes will still work as before, meaning that they will only ever show and load a theme that belongs to the Ef collection.

Internally, these commands are now using the Modus infrastructure and are then limiting the set of themes to the Ef collection. They are thus convenience wrappers around the equivalent Modus commands.

  • ef-themes-toggle
  • ef-themes-rotate
  • ef-themes-select
  • ef-themes-load-random
  • ef-themes-load-random-dark
  • ef-themes-load-random-light

Additionally, the commands ef-themes-list-colors and ef-themes-list-colors-current use the relevant Modus functionality under the hood while working only with the Ef themes.

Combining core Modus themes with all their derivatives

The minor mode modus-themes-include-derivatives-mode makes all the theme-loading commands that Modus defines consider all core and derivative themes. This means that something like modus-themes-select will offer modus-operandi and ef-summer as two of the many possible candidates.

In this scenario, the Modus and Ef collections become part of a larger family of themes as opposed to only considering one or the other (Loading only Ef themes with the convenience wrappers we provide). Enable modus-themes-include-derivatives-mode and then access them all with the following commands:

  • modus-themes-toggle
  • modus-themes-rotate
  • modus-themes-select
  • modus-themes-load-random
  • modus-themes-load-random-dark
  • modus-themes-load-random-light
  • modus-themes-list-colors
  • modus-themes-list-colors-current

Consult the manual of the Modus themes for further details and/or read the documentation string of each command.

Taking over the Modus commands altogether

The minor mode ef-themes-take-over-modus-themes-mode makes all Modus commands that load a theme consider only Ef themes. This is the opposite of allowing different theme collections to be blended together (Combining core Modus themes with all their derivatives). It effectively is the same as using one of the convenience wrapper commands we already provide (Loading only Ef themes with the convenience wrappers we provide).

This minor mode exists to accommodate the needs of users who install both the Modus and Ef theme packages (and possibly other Modus derivatives). They can maintain a single/shared configuration and then decide when to enable ef-themes-take-over-modus-themes-mode to switch to using just the Ef themes.

For example, in the morning the user only wants to consider the Modus themes, but during the evening they only likee the Ef themes. In this scenario, a key binding to, say, modus-themes-rotate does not need to be updated: it internally reads only Ef themes when ef-themes-take-over-modus-themes-mode is enable. When this minor mode is disabled, that same key binding will revert to doing what it did before (load only a core Modus theme or Modus plus derivatives if modus-themes-include-derivatives-mode is enabled).

More semantic palette mappings

Modus has always had a more comprehensive palette than Ef. Now they are on par. Concretely, this means that users can customise more of the theme’s style to their liking. Use the commands that list/preview a palette to learn about all the available options.

The manual of the Modus themes covers the palette and user-defined overrides at great length. It also includes code samples that you can use as a starting point. And if something is unclear, you are welcome to contact me.

Many more faces are covered

The wide face/package coverage of Modus is now inherited by the Ef themes. If some interface you are using does not look right, then the underlying faces are probably not supported yet. Contact me and I will take care of it right away.

]]>
Emacs: modus-themes version 5.1.0 Information about the latest version of my highly accessible themes for GNU Emacs. Fri, 07 Nov 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-11-07-emacs-modus-themes-5-1-0/ https://protesilaos.com/codelog/2025-11-07-emacs-modus-themes-5-1-0/ I just published the latest stable release of the Modus themes. The change log entry is reproduced further below. For any questions, you are welcome to contact me. I will now work to apply these same changes to emacs.git, so please wait a little longer for the updates to trickle down to you.


5.1.0 on 2025-11-07

This version fixes a critical bug in the modus-themes-with-colors macro. In short, it was not working as before or was not working at all. Now it should do the right thing.

Thanks to Alexandr Semenov for reporting a relevant bug in issue 170 and for helping me test the results: https://github.com/protesilaos/modus-themes/issues/170.

Thanks to Stéphane Marks for testing some configurations with the latest stable Emacs version as well as with builds from emacs.git. This was done via a private channel and I am sharing this information with permission.

Also thanks to Stefan Monnier for monitoring my commits as I was trying to refactor the modus-themes-with-colors macro. Some comments were posted on the emacs-devel mailing list, as well as a patch that I ended up applying and then reverting (check the commit log for the technicalities): https://lists.gnu.org/archive/html/emacs-devel/2025-11/msg00114.html.

Apologies to everyone for the inconvenience! This was a tricky bug. The good thing is that it compelled me to improve several parts of the code.

This version also includes a clarification in the manual about building a theme on top of Modus:

In short, it mentions that a theme exists in an appropriately named file that is part of the custom-theme-load-path. Thanks to Ashton Wiersdorf for asking a related question in issue 171: https://github.com/protesilaos/modus-themes/issues/171.

]]>
Emacs: modus-themes version 5.0.0 Information about the latest version of my highly accessible themes for GNU Emacs. Sat, 01 Nov 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-11-01-emacs-modus-themes-5-0-0/ https://protesilaos.com/codelog/2025-11-01-emacs-modus-themes-5-0-0/ I just published the latest stable release of the Modus themes. The change log entry is reproduced further below. For any questions, you are welcome to contact me. I will now work to apply these same changes to emacs.git, so please wait a little longer for the updates to trickle down to you.


5.0.0 on 2025-11-01

This is a major release. There are some small breaking changes. The big new feature is that Modus can be used as the basis for other theme projects. Two of my other theme packages, the ef-themes and the standard-themes are already done in this way: their next major versions will formalise what I have been developing for a while now (though the doric-themes will remain their own thing for the time being).

Build on top of Modus

This is of immediate interest to package developers or advanced users. It changes nothing for existing users of the Modus themes. Please refer to the manual on the matter and feel welcome to contact me if you have any questions—I am happy to help.

Evaluate:

(info "(modus-themes) Build on top of the Modus themes")

Or visit: https://protesilaos.com/emacs/modus-themes#h:86eb375b-9be4-43ce-879a-0686a524a63b.

Why build on top of Modus? To benefit from (i) the wide face coverage and extensive detail-oriented testing, (ii) the use of palette mappings, (iii) the palette preview done with modus-themes-list-colors or related, (iv) the inclusion of the derivative theme in the workings of all Modus commands that load a theme, like modus-themes-rotate and modus-themes-select (see the new minor mode modus-themes-include-derivatives-mode).

Derivative themes can be as simple as a few extra colours on top of, say, modus-operandi. They can also be more involved, with new palette mappings and custom faces that use them. Such themes can define commands which load only their own themes (see modus-themes-define-derivative-command) and they can even take over the Modus themes completely, in terms of becoming the only ones that are exposed to the commands that load a theme, like modus-themes-rotate and modus-themes-select.

Thanks to Suleyman Boyar for fixing an intermediate omission with an earlier version of the code that derives a theme. I did eventually change the whole approach to use a function instead of a macro, but Suleyman’s contribution was still useful at the time. This was done in pull request 156: https://github.com/protesilaos/modus-themes/pull/156. The change is small, meaning that Suleyman does not need to assign copyright to the Free Software Foundation.

Colours can be copied from the palette preview buffer

The commands modus-themes-list-colors and modus-themes-list-colors-current display the given theme’s palette in a tabulated listing. Each line visualises the colour it references. From that buffer it is now possible to call the following commands (bound to the modus-themes-preview-mode-map):

Default key binding Name of the command
w modus-themes-preview-mode-copy-color
W modus-themes-preview-mode-copy-entry
m modus-themes-preview-mode-mark
M modus-themes-preview-mode-mark-all
u modus-themes-preview-mode-unmark
U modus-themes-preview-mode-unmark-all

The modus-themes-preview-mode-copy-color and its modus-themes-preview-mode-copy-entry counterpart work on the line at point or those that are marked. The first copies the resolved colour value, as a string (“resolved” here means that it will find what a palette mapping actually stands for). The second gets the complete palette entry, as it appears in the underlying definition. This is a starting point for writing palette overrides.

Thanks to shimeike for reporting a problem with a regression I introduced by mistake in one of the development versions of the function that handles the creation of the tabulated list. This was done in issue 163: https://github.com/protesilaos/modus-themes/issues/163.

New semantic palette mappings for programming contexts

The fnname-call and variable-use are now available. They are applied to faces that are used by major modes which build on top of tree-sitter program as well as the Emacs Lisp semantic highlighting feature of Emacs 31.

By default, these colours are more subtle than their fnname and variable counterparts. The reason is that I want to avoid exaggerations with the wanton application of colour (“avoiding exaggerations” is one of the design principles of the Modus themes).

Because of the commitment to the highest legibility standard for colour contrast, we are using colours that stand out in their context, yet are still harmonious with each other. This is due to (i) careful consideration of colour harmonies, (ii) enforced uniformity of styles where necessary to avoid emphasising the emphasis or stating the obvious, and (ii) the fact that not too many intense colours appear in close proximity to each other in most Emacs major modes. If a major mode or other feature adds colours virtually everywhere, then the Modus themes are no longer true to their character and become borderline unusable.

The more subtle colours for fnname-call and variable-use do not prevent exaggerations, though they do make them less egregious.

[ Note that themes do not control which face is applied where. That is the job of a major mode or specialised minor modes. When in doubt, work with the rule that fewer colours are better than many. ]

Support for Emacs Lisp semantic highlighting

This is built into Emacs version 31. What it does is make different parts of the Elisp syntax stand out visually. It also augments them with a mouse tooltip (technically a help-echo) that provides valuable insights about what the thing is.

Thanks to Eshel Yaron, the author of this feature, for (i) asking me to review the relevant faces, (ii) helping me understand what “semantic highlighting” is intended for, and (iii) explaining to me how some faces are meant to be used. This was done in the context of Emacs bug 79677 and in an aside about a change to my minimalist doric-themes package:

I wrote to Eshel that I do not want many colours clustered together. This design is more suitable to themes with low intensity. All my themes exacerbate the effect of dense colouration due to their primary design goal: legibility.

Currently the added colouration of semantic highlighting is noticeable far more than I like. This is a compromise on my end. Future versions of the themes might set more semantic faces to nil (or anyhow make them subtle), subject to further review and user feedback.

This is not a position against semantic highlighting, but a comment on inconsiderate themes.

More elements are optionally bold or italic

I have revised all supported faces to make them more conservative about when they apply typographic qualities that deviate from the default font. Many faces that were unconditionally rendered with a bold weight or an italic slant are now subject to the user options modus-themes-bold-constructs and modus-themes-italic-constructs.

This means that they are like the default font family by default and will become bold/italic if the relevant user option is set to a non-nil value.

Faces that are semantically bold or italic and/or which genuinely benefit from such typographic attributes out-of-the-box are exempt from this.

Headings are also exempt because they are anyway subject to the user option modus-themes-headings which covers the height and weight of each heading level’s text.

Thanks to chainedghost for reporting a regression in one of the commits I made. This was done in issue 167: https://github.com/protesilaos/modus-themes/issues/167

Support for lsp-mode and lsp-ui packages

Thanks to Jimmy Yuen Ho Wong for the initial contribution in pull request 142: https://github.com/protesilaos/modus-themes/pull/142. I made some changes on top to use semantic palette mappings, where applicable, and other such tweaks.

The minibuffer-nonselected face is supported

This is coming in Emacs version 31: it highlights the active minibuffer when the cursor is in another window. The face is designed to be as noticeable as possible because this kind of scenario usually leads to mistakes or confusion.

Refinements to supported packages or face groups

  • The markdown-code-face uses the same semantic palette mapping as org-block. This was always the intent. Thanks to Frédéric Giquel for the fix in pull request 160: https://github.com/protesilaos/modus-themes/pull/160. The change is small and thus does not require copyright assignment to the Free Software Foundation.

  • Fixed a word in the symbol of the flymake-warning-echo-at-eol. Thanks to Eric Ottosson for the patch in pull request 145: https://github.com/protesilaos/modus-themes/pull/145. No copyright assignment is required.

  • The two new Emacs 31 faces for packages that are marked for installation or deletion in the M-x list-packages buffer are now included. Thanks to Gautier Ponsinet for sending me the patch. Gautier has assigned copyright to the Free Software Foundation.

  • The hs-ellipsis in Emacs 31 from the built-in hideshow package is also covered. It is made to conform with established patterns across conceptually equivalent faces (e.g. Org folded headings) rather than do its own thing.

  • The widget-field uses an underline to be easier to spot. On supported Emacs displays (generally graphical Emacs) the underline is at the descent line, meaning that it does not cross through characters with descenders like g.

  • The git-commit and log-edit faces for writing commit messages in Magit and VC are tweaked to avoid exaggerations.

  • The Magit section headings have a slightly modified foreground value.

  • The org-list-dt face for list definition terms has a slightly modified foreground value to (i) be easier to spot while (ii) being less intense overall.

  • The calendar-today in the M-x calendar interface now has a box around it on supported displays (graphical Emacs) to better stand out from its context. On unsupported displays, the face still gets an appropriate background value.

  • The org-date-selected and calendar-today should look the same, contrary to how they did before. This is done in the interest of theme-wide consistency (i.e. the kind of detail you appreciate once it is no longer there).

  • The mode lines use an underline on displays that cannot render a box. This way, the faces remain distinct from their context.

  • All interface buttons, like those that appear in the Custom buffers, will be rendered with an underline on displays that cannot handle boxes.

  • The notmuch-message-summary-face, which is used in threaded message views, now has an overline on supported displays (graphical Emacs). Individual messages in the thread should thus be more discernible.

  • The tab-bar-tab-highlight is directly covered to make sure all mouse hover effects are consistent across similar interfaces.

  • Some faces that had specific colour values (e.g. cyan-cooler) are revised to use semantic palette mappings instead. This ensures thematic consistency. The most obvious beneficiaries are users of the deuteranopia- and tritanopia- optimised themes (deuteranopia-friendly themes cannot work with red and green while tritanopia-friendly themes must not rely on yellow and blue).

The modus-themes-custom-auto-reload is obsolete

Plus all our user options no longer specify a :set function. This means that the theme will never be reloaded automatically when using the Custom interface or setopt to configure one of the theme’s user options. Reloading the theme is what applies the new styles. The idea of this feature is good, but the implementation was problematic. Maybe I will reinstate it in the future, though I cannot let it block this major release.

Several modus-themes-* faces are obsolete

In previous versions I was defining faces that were used to apply uniform styles across many packages. This was the old way of doing things before version 4.0.0 of the themes that introduced palettes with semantic mappings and, optionally, user-defined overrides to them.

I have deprecated all of the following and made all the necessary changes (i.e. several thousands of them), to make palette mappings the norm everywhere. In general, I encourage you not to rely on any faces defined by Modus: they are really intended for internal use.

  • modus-themes-fg-blue
  • modus-themes-fg-blue-cooler
  • modus-themes-fg-blue-faint
  • modus-themes-fg-blue-intense
  • modus-themes-fg-blue-warmer
  • modus-themes-fg-cyan
  • modus-themes-fg-cyan-cooler
  • modus-themes-fg-cyan-faint
  • modus-themes-fg-cyan-intense
  • modus-themes-fg-cyan-warmer
  • modus-themes-fg-green
  • modus-themes-fg-green-cooler
  • modus-themes-fg-green-faint
  • modus-themes-fg-green-intense
  • modus-themes-fg-green-warmer
  • modus-themes-fg-magenta
  • modus-themes-fg-magenta-cooler
  • modus-themes-fg-magenta-faint
  • modus-themes-fg-magenta-intense
  • modus-themes-fg-magenta-warmer
  • modus-themes-fg-red
  • modus-themes-fg-red-cooler
  • modus-themes-fg-red-faint
  • modus-themes-fg-red-intense
  • modus-themes-fg-red-warmer
  • modus-themes-fg-yellow
  • modus-themes-fg-yellow-cooler
  • modus-themes-fg-yellow-faint
  • modus-themes-fg-yellow-intense
  • modus-themes-fg-yellow-warmer
  • modus-themes-intense-blue
  • modus-themes-intense-cyan
  • modus-themes-intense-green
  • modus-themes-intense-magenta
  • modus-themes-intense-red
  • modus-themes-intense-yellow
  • modus-themes-key-binding
  • modus-themes-lang-error
  • modus-themes-lang-note
  • modus-themes-lang-warning
  • modus-themes-mark-alt
  • modus-themes-mark-del
  • modus-themes-mark-sel
  • modus-themes-nuanced-blue
  • modus-themes-nuanced-cyan
  • modus-themes-nuanced-green
  • modus-themes-nuanced-magenta
  • modus-themes-nuanced-red
  • modus-themes-nuanced-yellow
  • modus-themes-prominent-error
  • modus-themes-prominent-note
  • modus-themes-prominent-warning
  • modus-themes-prose-code
  • modus-themes-prose-macro
  • modus-themes-prose-verbatim
  • modus-themes-search-current
  • modus-themes-search-lazy
  • modus-themes-search-replace
  • modus-themes-search-rx-group-0
  • modus-themes-search-rx-group-1
  • modus-themes-search-rx-group-2
  • modus-themes-search-rx-group-3
  • modus-themes-search-static
  • modus-themes-subtle-blue
  • modus-themes-subtle-cyan
  • modus-themes-subtle-green
  • modus-themes-subtle-magenta
  • modus-themes-subtle-red
  • modus-themes-subtle-yellow

Thanks to Kevin Fleming and Jimmy Yuen Ho Wong for fixing two cases of unbalanced/faulty parentheses caused by the aforementioned. These were done as pull requests 166 and 168, respectively:

Both changes are small: no copyright assignment to the Free Software Foundation is needed (and I think both authors are covered, anyway).

All :inherit face attributes are reviewed and kept to a minimum

The themes now use the :inherit attribute much more cautiously than before. This is because of the reliance on semantic palette mappings: those give us more control and usually are explicit about the desired result.

Face inheritance can become circular in some cases. Newer Emacs versions throw an error accordingly. This was discussed in Emacs bug 79672, with participation from Eli Zaretskii, JD Smith, Manuel Giraud, Stephane Marks, and Steven Allen: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=79672.

Thanks to everybody involved!

]]>
Emacs: Denote version 4.1.0 Information about the latest version of my Denote package for GNU Emacs. Fri, 17 Oct 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-10-17-emacs-denote-4-1-0/ https://protesilaos.com/codelog/2025-10-17-emacs-denote-4-1-0/ Denote aims to be a simple-to-use, focused-in-scope, and effective note-taking and file-naming tool for Emacs.

Denote is based on the idea that files should follow a predictable and descriptive file-naming scheme. The file name must offer a clear indication of what the contents are about, without reference to any other metadata. Denote basically streamlines the creation of such files or file names while providing facilities to link between them (where those files are editable).

Denote’s file-naming scheme is not limited to “notes”. It can be used for all types of file, including those that are not editable in Emacs, such as videos. Naming files in a constistent way makes their filtering and retrieval considerably easier. Denote provides relevant facilities to rename files, regardless of file type.

Below are the release notes.


Version 4.1.0 on 2025-10-17

The overarching theme of version 4.1.0 is that of continuing to deliver on the highly hackable/flexible/powerful potential of Denote. All the core functionality is the same as before and you still only need a tiny configuration to use Denote productively. We are adding more refinements and subtle improvements under the hood, while making it even easier for advanced users/developers to piece together a workflow that matches their particular needs.

Since version 4.0.0, we have moved the “Denote extras” files into their own packages. I cover their changes further down after I elaborate on all the changes to the core Denote package:

Note that I write all the release notes by hand. The reason is that I consider this process an essential part of my role as a maintainer. Taking the time to review and document everything ensures that (i) I am well informed about the state of the package, (ii) I did not forget anything about this development cycle, and (iii) I take another look at the changes we made to ensure everything is in order.

Overview of the new features for core Denote

  • The user option denote-directory can be assigned to a list of directories. The original string value is also acceptable and remains the default.

  • Advanced users can define a completely custom scheme for identifiers. This can be as simple as automatically assigned ordinal numbers to increasingly complex patterns that may also involve user input.

  • The command denote-find-backlink-with-location is like denote-find-backlink except it also moves to the exact location of the link in the corresponding file.

  • All Denote buffer names share a common prefix, which is subject to the user option denote-buffer-name-prefix. This makes it easier to spot them in the buffer list.

  • The command denote-dired (alias denote-sort-dired) can sort files by random and last-modified in addition to the methods that involve Denote file name components.

  • The user option denote-query-sorting controls how files in all query buffers are sorted by default. This covers backlinks, query links for file contents, and any buffer produced by the denote-grep command. It benefits from the internal “Denote sort” mechanism, which is also used by denote-dired and the Org dynamic blocks of the denote-org package.

Remember that the release notes are true only at the time of publication. The single source of truth always is the official manual.

Set denote-directory to a list of directories

The user option denote-directory can optionally be bound to a list of file system paths, each of which represents a directory root, such as '("/home/prot/Documents/work/" "=/home/prot/Git/hut/") (Denote has always supported subdirectories, even for a singular denote-directory).

When creating new files, such as with the denote command, the first directory on the list will be selected. This can be changed by modifying the denote-prompts user option so that it asks for a directory or subdirectory thereof. Or by writing small wrapper commands that put files in a predefined directory, like this:

(defun my-denote-for-work ()
  "Like `denote' but always use the ~/Documents/work/ directory."
  (interactive)
  (let ((denote-use-directory "~/Documents/work/"))
    (call-interactively 'denote)))

Why have many directories as part of the denote-directory? Some users want to maintain separate directories with Denote files, while retaining the option of establishing links between (unlike the concept of “silos” we support, where the directories are self-contained). Those two directories can be their own Git repositories, for example, and have different syncing policies for access across multiple devices.

Thanks to Jean-Philippe Gagné Guay for providing the core functionality in pull request 609: https://github.com/protesilaos/denote/pull/609.

Jean-Philippe is a long-time contributor who has assigned copyright to the Free Software Foundation. I made several changes on top, such as to allow denote-dired (alias denote-sort-dired) to work with many directories, by finding their common root (which would ultimately be /).

Define completely custom Denote identifiers

The default Denote identifier should work for most people in most cases. I have considered the Denote file-naming scheme carefully and know it is reliable. Advanced users who have a clear use-case of something out-of-the-ordinary can now get “Denoted” file names with arbitrary identifiers. Since this is an advanced feature, I will not elaborate here on the technicalities. Though I have taken the time to write at length in the manual about it, with concrete examples ranging from simple to more complex scenaria. Start with this introduction: https://protesilaos.com/emacs/denote#h:3048f558-7d84-45d6-9ef2-53055483e801.

This feature has been discussed and requested for a long time, across several related issues:

Thanks, in no particular order, to mentalisttraceur, juh2, Christian Tietze, and Jean-Philippe Gagné Guay for sharing their thoughts. Also thanks to Jean-Philippe Gagné Guay for contributing the patches that made this possible, the last of which is in pull request 586: https://github.com/protesilaos/denote/issues/586.

Find a backlink at its exact location in the file

Denote has two ways of working with backlinks: (i) to display them in a dedicated buffer and (ii) to use a minibuffer prompt that supports completion in order to pick one file out of the list. The new command denote-find-backlink-with-location is of the latter kind. Like its more generic denote-find-backlink counterpart, it uses the minibuffer to pick a file that links to the current one. Then, it also moves the cursor to where the link is.

I did this is in response to issue 471 as reported by johkneisl: https://github.com/protesilaos/denote/issues/471.

Denote buffer names use the denote-buffer-name-prefix

This is a new user option that takes an arbitrary string. Its value is "[D]" by default. It consolidates how we name all of our buffers. Out-of-the-box, this applies to special buffers, like those produced by the commands denote-backlinks and denote-dired. When the optional minor mode denote-rename-buffer-mode is enabled, all buffers whose file naming scheme is that of Denote will get the denote-buffer-name-prefix in addition to their own denote-rename-buffer-format.

This is related to pull request 597 by James Kalyan: https://github.com/protesilaos/denote/pull/597. James has assigned copyright to the Free Software Foundation.

The Denote sort mechanism can sort by random and last-modified

In core Denote, this is used internally by the denote-dired command (alias denote-sort-dired) and the query buffers (more in the next section). By default, denote-dired prompts for the sort method and whether to reverse the order. Though there are user options to tweak its behaviour (consult the manual). The Org dynamic blocks of the denote-org package also rely on this mechanism (denote-org version 0.2.0).

Control the default sort of files in query buffers

Query buffers are those of denote-backlinks, denote-grep, and denote-query-contents-link (in the latter case, the query buffer is produced when you click on the link). Users can now modify how they sort matching files via the option denote-query-sorting. The sorting methods are by any of the Denote file names components (per denote-sort-components), random order, last modified, or an arbitrary function.

Thanks to Lucas Quintana for the contribution in pull request 594: https://github.com/protesilaos/denote/pull/594. Lucas has assigned copyright to the Free Software Foundation.

Miscellaneous for core Denote

  • The denote-dired command (alias denote-sort-dired) sets up its revert-buffer-function in a more robust way, such that it does not affect the window layout under certain conditions.

  • Fixed a bug with the menu entry of Denote that broke context-menu-mode. It addresses issue 592, as reported by artelse: https://github.com/protesilaos/denote/issues/592. Thanks to Lucas Quintana for the patch. Lucas has assigned copyright to the Free Software Foundation.

  • Thanks to ryota for refining the documentation of the variable denote-use-template and its potential interference with denote-org-capture-identifiers in custom user code. We discussed this in issue 545 and the patch was sent as pull request 598:
  • An internal check to determine if a file has backlinks is now faster than before: it exits with a non-nil value as soon as it finds one match, instead of trying to collect all the backlinks. Thanks to Yann Dutrieux for addressing an omission of mine in the original implementation and then for discussing with me some further refinements. Yann’s contribution was sent as pull request 637: https://github.com/protesilaos/denote/pull/637.

  • Thanks to Alan Schmitt and Ashish Panigrahi for fixing a couple of typos, in pull requests 623 and 626, respectively:

Git commits for core Denote

~/Git/Projects/denote $ git shortlog 4.0.0..4.1.0  --summary --numbered
   156	Protesilaos Stavrou
    29	Jean-Philippe Gagné Guay
     4	Lucas Quintana
     2	James Kalyan
     1	Alan Schmitt
     1	Ashish Panigrahi
     1	Hanwen Guo
     1	Ryota
     1	Yann Dutrieux

Changes to the extensions of Denote I maintain

This concerns all the former “Denote extras” that were shipped with core Denote as well as consult-denote.

consult-denote version 0.4.0

  • The commands consult-denote-grep and consult-denote-find also work when denote-directory is set to a list value, as explained further above (Set denote-directory to a list of directories).

  • There is a Consult-powered counterpart to the denote-sequence-file-prompt. It is for users of the denote-sequence package and comes into effect when the consult-denote-mode is enabled (that mode “Consults” all relevant minibuffer prompts Denote uses so they get the familiar preview functionality). The denote-sequence-file-prompt is used by commands such as denote-sequence, denote-sequence-find, and denote-sequence-link, among others (denote-sequence version 0.2.0).

  • The command consult-denote-find sorts its files by default. We discussed this with Gianluca Della Vedova and Gianluca implemented the tweak in pull request 18: https://github.com/protesilaos/consult-denote/pull/18. The change is small, meaning that Gianluca does not need to assign copyright to the Free Software Foundation.

denote-journal version 0.2.0

  • It is now possible to specify the desired interval used by the command denote-journal-new-or-existing-entry to determine what “new” and “existing” mean. Users may want to, for example, maintain one file per month, with daily entries as headings or as free-form text. The user option denote-journal-interval specifies the interval as a symbol among daily, weekly, monthly, and yearly. Thanks to Ning Xu for floating the idea of non-daily journaling in issue 18: https://github.com/protesilaos/denote-journal/issues/18.
  • The new user option denote-journal-signature specifies a signature that will be applied to all new journal entries. It is the counterpart of denote-journal-keyword. Possible values are nil, for no predefined signature, a string for a constant signature, and a function that returns a string which is then used as-is. Thanks to Halogen3576 for suggesting an option for a signature in issue 13: https://github.com/protesilaos/denote-journal/issues/13.

    In the case of a function value, users may wish to integrate the denote-journal package with the denote-sequence package (denote-sequence version 0.2.0). For example, each new journal entry should be defined as a new parent sequence. Thus:

    (setq denote-journal-signature
          (lambda ()
            (denote-sequence-get-new 'parent)))
    
  • The user option denote-journal-keyword is extended to support a function value which should return a string or list of strings.

  • The integration with M-x calendar (when the minor mode denote-journal-calendar-mode is enabled) is more robust when highlighting dates that have a Denote journal entry. Thanks to Alan Schmitt for the patch that improves the check for visible dates only. This was done in pull request 12: https://github.com/protesilaos/denote-journal/pull/12.

  • The denote-journal-calendar face is extended to also work when Emacs is ran in a TTY. Thanks to Ettore Berardi for the original contribution and for discussing this with me. It was done in pull request 14: https://github.com/protesilaos/denote-journal/pull/14. The contribution is less than 15 lines of code, meaning that Ettore does not need to assign copyright to the Free Software Foundation.

  • The function denote-journal-path-to-new-or-existing-entry is tweaked to not kill the buffer of the new file it might generate. Thanks to jbwfu for the change in pull request 17: https://github.com/protesilaos/denote-journal/pull/17. The change is small, meaning that the author does not need to assign copyright to the Free Software Foundation.

  • Dates with a single digit in the title of a new journal entry no longer have a space where the second digit normally is. So something like October 1 instead of October 1. Thanks to Josh Kingsley for the patch. The change is small, meaning that Josh does not need to assign copyright to the Free Software Foundation. It was done in pull request 24: https://github.com/protesilaos/denote-journal/pull/24.

  • Thanks to gk2803 for renaming a couple of old symbols to their current names in the commentary of the package. This was done in pull request 10: https://github.com/protesilaos/denote-journal/pull/10.

    ~/Git/Projects/denote-journal $ git shortlog 0.1.0..0.2.0  --summary --numbered
        35	Protesilaos Stavrou
         3	Alan Schmitt
         2	Ettore Berardi
         1	Abdelhak Bougouffa
         1	Josh Kingsley
         1	gk2803
         1	jbwfu
    

denote-org version 0.2.0

  • A new Org dynamic block integrates with the denote-sequence package (denote-sequence version 0.2.0). The block is called denote-sequence and can be inserted at point with the command denote-org-dblock-insert-sequence. What this block does is list the descendants of a given sequence up to a maximum depth. The presentation is a typographic list of lists to visualise the hierarchy of the complete sequence, with each set of children nested under its parent. Thanks to Peter Prevos for the original implementation in pull request 9 and for subsequent tweaks in pull request 13. Other changes by me are done to ensure tighter integration with the denote-sequence package.
  • All Org dynamic blocks that have a :sort-by-component parameter can now sort by random and last-modified. This is made possible by the aforementioned improvements to the core Denote sort mechanism (The Denote sort mechanism can sort by random and last-modified).

  • The denote-missing-links Org dynamic block, which can be inserted at point with the command denote-org-dblock-insert-missing-links takes an optional :not-regexp parameter. This is a regular expression of files to omit from the results. Same for the denote-backlinks block, which can be inserted at point with the command denote-org-dblock-insert-backlinks.

  • The denote-files-as-headings Org dynamic block, which can be inserted at point with the command denote-org-dblock-insert-files-as-headings now also accepts an optional :exclude-tags parameter. It is either nil or non-nil and determines whether the heading will have the file’s #+filetags as its own tags. Thanks to Matt Nolan for suggesting this idea in issue 14: https://github.com/protesilaos/denote-org/issues/14.

    ~/Git/Projects/denote-org $ git shortlog 0.1.0..0.2.0  --summary --numbered
        42	Protesilaos Stavrou
         8	Peter Prevos
    

denote-sequence version 0.2.0

  • The new commands denote-sequence-find-next-sibling and denote-sequence-find-previous-sibling move to the next or previous sibling in the given sequence. When called interactively, they work relative to the current file. When called from Lisp, they expect a SEQUENCE argument and its corresponding RELATIVES.

  • The denote-sequence-dired command is updated to (i) work with a list value for denote-directory (Set denote-directory to a list of directories), as noted further above and (ii) benefit from the refinements done to denote-dired with regard to its revert-buffer-function.

  • The new command denote-sequence-rename-as-parent makes it easier to apply the Denote file-naming scheme to an existing file and make it a new parent sequence. Thanks to Alex Carney for requesting something along those lines in issue 4: https://github.com/protesilaos/denote-sequence/issues/4.

    [ Remember that Denote is highly adaptable/hackable, meaning that many of these convenience commands build on top of the core with small extensions to it. The body of denote-sequence-rename-as-parent is only 4 lines long, two of which are for an error check. This is typical of much of what we provide and is how users can always extend Denote to do something slightly different than what we support out-of-the-box. ]

  • Made several other refinements under the hood, including the addition of more tests. In this regard, thanks to Rory Molinari, Peter Prevos, and Ashton Wiersdorf for fixing three bugs in pull requests 5, 8, and 11, respectively:

    ~/Git/Projects/denote-sequence $ git shortlog 0.1.0..0.2.0  --summary --numbered
        61	Protesilaos Stavrou
         1	Ashton Wiersdorf
         1	Peter Prevos
         1	Rory Molinari
    

Changes to denote-markdown

Nothing of substance.

Changes to denote-silo

Nothing of substance.

]]>
Emacs: tmr version 1.2.0 Information about the latest version of my TMR package for GNU Emacs. Mon, 06 Oct 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-10-06-emacs-tmr-1-2-0/ https://protesilaos.com/codelog/2025-10-06-emacs-tmr-1-2-0/ TMR provides facilities for setting timers using a convenient notation. Lots of commands are available to operate on timers, while there also exists a tabulated view to display all timers in a nice grid.

Below are the release notes.


Version 1.2.0 on 2025-10-06

This release introduces several quality-of-life refinements to an already stable and featureful package.

Timers can now appear on the modeline

The new minor mode tmr-mode-line-mode controls whether running timers are displayed on the mode line. More specifically, they are displayed in the global-mode-string, which can also be set in the tab-bar-mode (this way the information appears in one place instead of all the mode lines, assuming default settings).

The exact format of a timer on display is controlled by the user option tmr-mode-line-format. The number of timers is set with the option tmr-mode-line-max-timers. The separator between multiple timers is tmr-mode-line-separator. The length of each timer’s optional description is subject to tmr-mode-line-max-desc-length. While the entire indicator can have a prefix, per tmr-mode-line-prefix.

Thanks to Steven Allen for contributing the original version of this feature in pull request 2: https://github.com/protesilaos/tmr/pull/2. Steven has assigned copyright to the Free Software Foundation. Further changes by me, such as to make the timers on the mode line clickable (which produces a tabulated view, per tmr-tabulated-view).

Notifications for more operating systems

Timers can optionally trigger a system notification, via the abnormal hook tmr-timer-finished-functions. The relevant function is tmr-notification-notify. It used to only support Linux. Now it is extended to handle Android, Windows, and Haiku.

Thanks to Lucas Quintana for the contribution in pull request 10: https://github.com/protesilaos/tmr/pull/10. Lucas has assigned copyright to the Free Software Foundation.

The tabulated timers have a “duration” column

The tmr-tabulated-view command (alias tmr-list-timers) now includes a “duration” column, in addition to all the other informative data on display.

[ Remember that the tabulated view can be used to create, duplicate, edit, etc. the timers. ]

Thanks to jpg for suggesting this in issue 11: https://github.com/protesilaos/tmr/issues/11.

Miscellaneous

  • System notifications specify the :app-icon of Emacs. It will be displayed, if the underlying software supports it (I see it on Linux, anyway).

  • The option to play the tmr-sound-file via the abnormal hook tmr-timer-finished-functions is redone to not rely on the system shell (implicitly bash). This way, users who use exotic shell alternatives will not run into any trouble. This is done in response to a relevant problem that g-gundam was facing with the nushell: https://github.com/protesilaos/tmr/pull/7.

  • The function tmr-notification-notify is better at informing the user that it has produced the warning about the lack of DBUS support. Before, the notification did not identity itself as belonging to the tmr package.

  • The function tmr-running-timers-p is now available as a standalone function to do what was done before inside other functions. This is useful for anyone writing custom code on top of tmr. Thanks to Eugene Mikhaylov for suggesting the idea in issue 9: https://github.com/protesilaos/tmr/issues/9.

  • The manual is updated to include whatever necessary from the aforementioned.

]]>
Emacs: the ‘standard-themes’ are also built on top of the ‘modus-themes’ My 'standard-themes' for Emacs are refactored to work on top of my 'modus-themes', thus inheriting their extensive face coverage and customisability. Fri, 03 Oct 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-10-03-emacs-standard-themes-on-top-modus/ https://protesilaos.com/codelog/2025-10-03-emacs-standard-themes-on-top-modus/ In previous entries I explained how I have reworked the modus-themes to optionally work as the basis for other theme packages. The official documentation is in the manual of the Modus themes (my manuals are the only source of truth; blog posts—including this one—become outdated): https://protesilaos.com/emacs/modus-themes#h:86eb375b-9be4-43ce-879a-0686a524a63b.

I already mentioned how version 2.0.0 of the ef-themes will be done this way. I am happy to announce that as of this morning the same is true for my standard-themes. Specifically, version 3.0.0 of the Standard themes will be built on top of the modus-themes.

Users are now expected to customise the themes via the user options provided by Modus and to load the themes with the relevant Modus commands. Here is a sample configuration:

(use-package standard-themes
  :ensure t
  :init
  ;; This makes the Modus commands listed below consider only the
  ;; Standard themes.  For an alternative that includes Modus and all
  ;; derivative themes (like Standard), enable the
  ;; `modus-themes-include-derivatives-mode' instead.
  (standard-themes-take-over-modus-themes-mode 1)
  :bind
  (("<f5>" . modus-themes-rotate)
   ("C-<f5>" . modus-themes-select)
   ("M-<f5>" . modus-themes-load-random))
  :config
  ;; All customisations here.
  (setq modus-themes-mixed-fonts t)
  (setq modus-themes-italic-constructs t)

  ;; Finally, load your theme of choice (or a random one with
  ;; `modus-themes-load-random', `modus-themes-load-random-dark',
  ;; `modus-themes-load-random-light').
  (modus-themes-load-theme 'standard-light-tinted))

The modus-themes-theme macro is flexible

This morning, I extended the modus-themes-theme macro to optionally accept custom faces and user options that complement or override those provided by core Modus (the modus-themes-theme macro is documented at length with concrete examples in the aforementioned link to the manual). For the standard-themes, this means that we can inherit all the goodies from Modus but still deviate stylistically in important ways wherever necessary. One case where this is evident is the design of the active mode line: Modus has a flat appearance, while Standard uses a 3D effect.

Standard does not need to deviate substantively from Modus, though there is no technical constraint in this regard. A derivative theme can implement all the requisite deviations to achieve the exact design it aims for, all while reusing Modus.

My plan is to release all new theme versions in the coming days, depending on my availability. Please let me know if you have any questions or want some things to change.

]]>
Emacs: ‘modus-themes’ as a basis for other themes; ‘ef-themes’ is first Update on changes I making to allow the modus-themes to be used as a basis for other other projects. My ef-themes is the first of that kind. Wed, 01 Oct 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-10-01-emacs-modus-framework-ef-built-on-top/ https://protesilaos.com/codelog/2025-10-01-emacs-modus-framework-ef-built-on-top/ [ This is a development note. Things might change before the release of modus-themes version 5.0.0 and ef-themes version 2.0.0. ]

In previous entries, I outlined how my ef-themes will be built on top of my modus-themes and then how the modus-themes are partly redesigned to enable such an arrangement:

I have now finalised the details and merged the changes in the respective main branch of each Git repository. If you are building the packages from their latest commit, you might need to delete and then re-install the package. Otherwise, I expect things to work as expected. The modus-themes, in particular, should have no obvious change to its users.

The ef-themes have undergone substantial changes. All of their user options are deprecated and will no longer have any effect. User options from the Modus themes now take their place. Furthermore, all the Ef commands to load a theme are discontinued. The plan is to re-use the infrastructure of the Modus themes throughout. Concretely, users must change their configuration to at least this minimal setup:

(use-package ef-themes
  :init
  ;; This is essential to let the Ef themes take over the Modus themes commands.
  (ef-themes-take-over-modus-themes-mode 1))

Or this sort, if they want some key bindings and customisations:

(use-package ef-themes
  :init
  (ef-themes-take-over-modus-themes-mode 1)
  :bind
  (("<f5>" . modus-themes-rotate)
   ("C-<f5>" . modus-themes-select)
   ("M-<f5>" . modus-themes-load-random))
  :config
  ;; All customisations here.
  (setq modus-themes-mixed-fonts t))

Load a theme

The commands modus-themes-rotate, modus-themes-select, modus-themes-toggle, and modus-themes-load-random will also load a theme interactively.

Loading a specific theme from Lisp works as expected:

(load-theme 'ef-cyprus :no-confirm)

To do the same while also triggering the modus-themes-after-load-theme-hook as well as the modus-themes-disable-other-themes:

(modus-themes-load-theme 'ef-summer)

To load a theme at random, do this:

(modus-themes-load-random)
(modus-themes-load-random 'dark) ; dark only (alternative `modus-themes-load-dark')
(modus-themes-load-random 'light) ; light only (alternative `modus-themes-load-light')

Use both Ef and Modus themes

To not take over the Modus themes completely and to instead allow the Modus commands to act on both Modus and Ef themes, enable this minor mode instead:

(modus-themes-include-derivatives-mode 1)

And make sure you disable ef-themes-take-over-modus-themes-mode in this case.

More customisation for the Ef themes

All the user options of the Modus themes are now available. For example, there was no option in the past to disable bold and italic styles from the Ef themes. They are now disabled by default, unless the user sets modus-themes-bold-constructs and modus-themes-italic-constructs to non-nil values.

Additionally, the Ef themes now enjoy wider face/package support.

Everything else should be as expected

Advanced users who were relying on the ef-themes-with-colors or any other Ef functionality will have to do the same with the Modus framework. Everything is possible, plus I am happy to help with the transition if you have any questions.

The Modus themes benefit from this redesign because their code is made to be more generic and to not hardcode certain assumptions. It also makes sense for them to be useful as a dependency for other themes, as they are part of core Emacs, which is convenient.

Remember that everything is still in development. I will expand the manuals and make sure everything is in order for the next major version of each of these two projects.

If everything goes well, expect my standard-themes to be redone on top of the modus-themes. But not for the doric-themes: those are quite different in style and overall design.

]]>
Emacs: building on top of the Modus themes A big picture view of how the Modus themes can be used by other theme packages. Tue, 30 Sep 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-09-30-emacs-building-on-top-modus-themes/ https://protesilaos.com/codelog/2025-09-30-emacs-building-on-top-modus-themes/ I have been doing a lot of work these days on my themes. The immediate goal is two-fold: (i) make the modus-themes more flexible so they can be used as a the basis for other theme packages and (ii) make the ef-themes the first project to benefit from this development. Having the Modus themes as a foundation gives us all of their customisability and extensive face coverage for little extra work. The themes are well tested and are also shipped with core Emacs. It all fits together.

In this article, I give you the big picture view of how this is supposed to work. Remember that the only source of truth for my packages is their corresponding manual. Any blog post is useful the time it is written but will eventually go out of date.

Symbol properties for themes

When we define a theme, we essentially add properties to a symbol. In its simplest form, this is how:

(put 'my-test-symbol 'my-test-proerty "Hello world test value")

Evaluate the above and then try the following:

(get 'my-test-symbol 'my-test-proerty)
;; => "Hello world test value"

The function custom-declare-theme does the heavy lifting, while the deftheme macro streamlines most of that work. Still, the point is that we have symbols whose properties we can access and, thus, we can filter by any given property. To make things even better, we can add arbitrary properties to a theme. Here is a real scenario of _in-development code that might change:

(get 'modus-operandi 'theme-properties)
;; => (:kind color-scheme :background-mode light :family modus-themes :modus-core-palette modus-themes-operandi-palette :modus-user-palette modus-operandi-palette-user :modus-overrides-palette modus-operandi-palette-overrides)

The theme-properties has as a plist value. Its Modus-specific properties are references to variables that we can use to do our work, such as to put together a theme palette that combines the relevant overrides with the core entries.

Getting a list of themes based on their properties

When we declare a theme with custom-declare-theme, we make it known to Emacs by adding it to the custom-known-themes. When we eventually load a theme, its symbol gets stored in the custom-enabled-themes. Knowing that themes have properties, we can filter those lists accordingly. With my current development code, I can do this, for example:

(defun my-demo-is-modus-p (theme)
  "Return non-nil if THEME has `modus-themes' :family property."
  (when-let* ((properties (get theme 'theme-properties))
              (family (plist-get properties :family)))
    (eq family 'modus-themes)))

(seq-filter #'my-demo-is-modus-p custom-known-themes)
;; => (modus-vivendi-tritanopia modus-vivendi-tinted modus-vivendi modus-vivendi-deuteranopia modus-operandi-tritanopia modus-operandi-tinted modus-operandi modus-operandi-deuteranopia)

The next step from here is to make all the Modus infrastructure rely on generic functions and methods for working with themes. Then any package can provides its own method for returning a list of desired themes.

Generic function and methods for getting a list of themes

Emacs Lisp has a concept of generic functions, which it borrows from Common Lisp. The general idea is to have a single symbol, like modus-themes-get-themes whose implementation details are instantiated via specialised methods. For example, when a minor mode is active, a given method takes effect, thus changing what modus-themes-get-themes actually does.

The default implementation is this:

(cl-defgeneric modus-themes-get-themes ()
  "Return a list of all themes with `modus-themes' :family property."
  (modus-themes-get-all-known-themes 'modus-themes))

The function modus-themes-get-all-known-themes has a filter like the one I demonstrated in the code block further above. By default, this is what I get when I run the aforementioned generic function:

(modus-themes-get-themes)
;; => (modus-operandi modus-operandi-tinted modus-operandi-deuteranopia modus-operandi-tritanopia modus-vivendi modus-vivendi-tinted modus-vivendi-deuteranopia modus-vivendi-tritanopia)

The beauty of this design is that another package can define a method to make the same code return something else. This is how I do it in the current development target of the ef-themes (again, the actual code might change):

(cl-defmethod modus-themes-get-themes (&context (ef-themes-take-over-modus-themes-mode (eql t)))
  (modus-themes-get-all-known-themes 'ef-themes))

Notice that this method has a &context, which is the scenario in which it is relevant. In this case, we have a minor mode that activates the method when it is enabled:

(define-minor-mode ef-themes-take-over-modus-themes-mode
  "When enabled, all Modus themes commands consider only Ef themes."
  :global t
  :init-value nil)

This minor mode does not have anything in its body. It does not need to, because the define-minor-mode macro already instantiates the parts we care about. Namely, when we call the function defined by the minor mode (i.e. ef-themes-take-over-modus-themes-mode), it toggles the value of the variable ef-themes-take-over-modus-themes-mode (functions and variables have separate namespaces in Emacs Lisp and thus the same symbol can be in both places). Our method then becomes relevant when the user enables the minor mode:

(ef-themes-take-over-modus-themes-mode 1)

And now the generic function modus-themes-get-themes does something else:

(modus-themes-get-themes)
;; => (ef-winter ef-tritanopia-light ef-tritanopia-dark ef-trio-light ef-trio-dark ef-symbiosis ef-summer ef-spring ef-rosa ef-reverie ef-owl ef-night ef-melissa-light ef-melissa-dark ef-maris-light ef-maris-dark ef-light ef-kassio ef-frost ef-elea-light ef-elea-dark ef-eagle ef-duo-light ef-duo-dark ef-dream ef-deuteranopia-light ef-deuteranopia-dark ef-day ef-dark ef-cyprus ef-cherie ef-bio ef-autumn ef-arbutus)

Since all the Modus functions are redesigned to work with this generic function, we can now use commands like modus-themes-select or even modus-themes-list-colors for any of those themes.

As a bonus, we can now seamlessly blend Modus themes with their derivatives. Imagine a user who wants to invoke the command modus-themes-load-random (or its variants for light and dark themes) and have it consider the likes of modus-operandi and ef-dream. Users can opt in to this feature via the minor mode that the Modus themes provide called modus-themes-include-derivatives-mode. It is the same ideas as the minor mode for the Ef themes, mentioned above:

(define-minor-mode modus-themes-include-derivatives-mode
  "When enabled, all Modus themes commands cover derivatives as well.
Otherwise, they only consider the `modus-themes-items'.

Derivative theme projects can implement the equivalent of this minor
mode plus a method for `modus-themes-get-themes' to filter themes
accordingly."
  :global t
  :init-value nil)

(cl-defmethod modus-themes-get-themes (&context (modus-themes-include-derivatives-mode (eql t)))
  (modus-themes-get-all-known-themes nil))

This is what happens when I load both the modus-themes and the ef-themes and enable this “all good ones fit” minor mode:

(modus-themes-include-derivatives-mode 1)

(modus-themes-get-themes)
;; => (modus-operandi modus-operandi-tinted modus-operandi-deuteranopia modus-operandi-tritanopia modus-vivendi modus-vivendi-tinted modus-vivendi-deuteranopia modus-vivendi-tritanopia ef-winter ef-tritanopia-light ef-tritanopia-dark ef-trio-light ef-trio-dark ef-symbiosis ef-summer ef-spring ef-rosa ef-reverie ef-owl ef-night ef-melissa-light ef-melissa-dark ef-maris-light ef-maris-dark ef-light ef-kassio ef-frost ef-elea-light ef-elea-dark ef-eagle ef-duo-light ef-duo-dark ef-dream ef-deuteranopia-light ef-deuteranopia-dark ef-day ef-dark ef-cyprus ef-cherie ef-bio ef-autumn ef-arbutus)

And when I no longer want to include everything, I just disable the minor mode:

(modus-themes-include-derivatives-mode -1)

(modus-themes-get-themes)
;; => (modus-operandi modus-operandi-tinted modus-operandi-deuteranopia modus-operandi-tritanopia modus-vivendi modus-vivendi-tinted modus-vivendi-deuteranopia modus-vivendi-tritanopia)

It is a thing of beauty!

Finalising the implementation details

I am still experimenting with some of the technicalities involved. In principle, derivative themes will (i) depend on the modus-themes, (ii) define each of their themes using the modus-themes-theme macro, and (iii) specify how/when they affect the behaviour of the generic function modus-themes-get-themes.

The code I am working on will soon be available in the respective main branch of modus-themes.git and ef-themes.git. I think this gives us the tools to realise the full potential of the Modus themes.

Finally, it is not just package authors that can benefit from this development. Users may also curate their themes with something as basic as this:

(cl-defmethod modus-themes-get-themes ()
  '(modus-operandi ef-eagle modus-vivendi-tinted ef-melissa-dark))

(modus-themes-get-themes)
;; => (modus-operandi ef-eagle modus-vivendi-tinted ef-melissa-dark)

In this method, there is no function involved for returning a list of themes nor an opt-in clause. It simply hardcodes a list of themes. The point is that it works! The approach with the minor mode will usually be better and is easy enough. It is all a matter of empowering personal preference, which is the Emacs-y outlook, after all. I expect users to define their own collections, as they see fit.

Have fun!

About the Modus themes

Highly accessible themes, conforming with the highest standard for colour contrast between background and foreground values (WCAG AAA). They also are optimised for users with red-green or blue-yellow colour deficiency.

The themes are very customisable and provide support for a wide range of packages. Their manual is detailed so that new users can get started, while it also provides custom code for all sorts of more advanced customisations.

Since August 2020, the original Modus themes (modus-operandi, modus-vivendi) are built into Emacs version 28 or higher. Emacs 28 ships with modus-themes version 1.6.0. Emacs 29 includes version 3.0.0. Emacs 30 provides version 4.4.0. Version 4 is a major refactoring of how the themes are implemented and customised. Such major versions are not backward-compatible due to the limited resources at my disposal to support multiple versions of Emacs and of the themes across the years.

About the Ef themes

The ef-themes are a collection of light and dark themes for GNU Emacs that provide colourful (“pretty”) yet legible options for users who want something with a bit more flair than the modus-themes (also designed by me).

]]>
Emacs: the next ‘ef-themes’ will build on top of the ‘modus-themes’ Announcement about the changes coming to the next major version of the Ef themes. Sat, 27 Sep 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-09-27-emacs-next-ef-themes-built-on-modus/ https://protesilaos.com/codelog/2025-09-27-emacs-next-ef-themes-built-on-modus/ Since version 4.0.0 of my modus-themes, users can override the palette of one or all the themes. They can change the applicable colours and how those are mapped to semantic elements. For example, “heading level 1” will apply to Org, Markdown, Info, and anything else that defines a relevant face. In principle, Modus can derive any theme. The advantage is that we get battle tested support for a wide range of packages, theme-wide consistency and attention to detail, and all the familiar flexibility of customisation, while only defining new colour values and/or their mappings. Plus, the Modus themes are built into Emacs.

When I first designed the ef-themes, Modus did not have the aforementioned capabilities. As such, Ef had to be implemented from scratch. Over time, the two projects have converged in terms of overall approach. There still are some notable differences, namely, Ef is less customisable and extensive than Modus. This is about to change.

I am working on a thoroughgoing redesign of the Ef themes to make them essentially load either modus-operandi (main light theme) or modus-vivendi (main dark theme) with the relevant palette overrides. All the Ef themes will look the same as they do now, but under the hood things will become much simpler. What is currently a standalone “theme” object will be reduced to a palette definition, essentially an alist.

In a future publication, I will document all the breaking changes. In short, all customisation shall be done via the Modus user options. Ef will only implement its palettes. As for my doric-themes and standard-themes those will remain unchanged for the time being. Standard might go the way of Ef, but Doric will probably continue to be its own thing. At any rate, these issues will be examined when their time is right.

Stay tuned for more. In the meantime, enjoy version 1.11.0 of the Ef themes that I released earlier this week!

About the Ef themes

The ef-themes are a collection of light and dark themes for GNU Emacs that provide colourful (“pretty”) yet legible options for users who want something with a bit more flair than the modus-themes (also designed by me).

About the Modus themes

Highly accessible themes, conforming with the highest standard for colour contrast between background and foreground values (WCAG AAA). They also are optimised for users with red-green or blue-yellow colour deficiency.

The themes are very customisable and provide support for a wide range of packages. Their manual is detailed so that new users can get started, while it also provides custom code for all sorts of more advanced customisations.

Since August 2020, the original Modus themes (modus-operandi, modus-vivendi) are built into Emacs version 28 or higher. Emacs 28 ships with modus-themes version 1.6.0. Emacs 29 includes version 3.0.0. Emacs 30 provides version 4.4.0. Version 4 is a major refactoring of how the themes are implemented and customised. Such major versions are not backward-compatible due to the limited resources at my disposal to support multiple versions of Emacs and of the themes across the years.

]]>
Emacs: ef-themes version 1.11.0 Information about the latest version of my colourful-yet-legible themes for GNU Emacs. Thu, 25 Sep 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-09-25-emacs-ef-themes-1-11-0/ https://protesilaos.com/codelog/2025-09-25-emacs-ef-themes-1-11-0/ The ef-themes are a collection of light and dark themes for GNU Emacs that provide colourful (“pretty”) yet legible options for users who want something with a bit more flair than the modus-themes (also designed by me).

Below are the release notes.


Version 1.11.0 on 2025-09-25

This version introduces minor refinements to a stable package.

Support for faces added to Emacs 31

Emacs 31 is the current development target of Emacs. The new faces are header-line-inactive, package-mark-delete-face, package-mark-install-face, minibuffer-nonselected.

Mode lines are a bit easier to spot

The active and inactive mode lines now have a subtle box/border around them on graphical Emacs. In non-graphical sessions, an underline is applied instead. This makes mode lines easier to stand out even when the buffer is showing a background that is of a similar colour to their own background.

The Custom interface buttons are more refined

These are the buttons that appear in the Custom buffers that we reach through various means such as M-x customize. Like with the mode lines, they use a box/border around where possible, else fall back to an underline.

The current date in the M-x calendar always looks the same

Before, it would look different if the Calendar was produced via M-x calendar as opposed to the Org date selection interface. This is because they apply different faces to the current date. Those are now reworked to look the same.

Notmuch message summary headers have clear dividers

In the Notmuch email client, the messages in a thread can be collapsed/minimised to just a heading. Those used to have only a subtle background, which would be enough to differentiate them from the body of the email but not from each other when all were collapsed. Now the themes add an overline to each heading, if supported by the underlying display engine (i.e. graphical Emacs), which should make it easier to spot them.

Links in the header line of Info buffers do not have an underline

This is because the header line has a distinct background already, so we want to avoid exaggerations.

The commands ef-themes-rotate and ef-themes-load-random can be silent

They now accept an optional SILENT parameter that inhibits the message they otherwise print. Thanks to Sean Devlin for the contribution in pull request 59: https://github.com/protesilaos/ef-themes/pull/59.

Note that any function can be silenced with something like this:

(defun my-wrapper-of-some-function ()
  (let ((inhibit-message t))
    (some-function)))
]]>
Emacs: example of a custom Denote identifier to include day of week data I explain how Denote can use custom identifiers and discuss the technicalities of the code. Wed, 24 Sep 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-09-24-emacs-example-denote-custom-identifier/ https://protesilaos.com/codelog/2025-09-24-emacs-example-denote-custom-identifier/ As I wrote in a recent entry, the forthcoming version 4.1.0 of Denote will provide the option to define custom identifier schemes. Here I explain one of the examples I have included in the manual, specifically, the idea of recording the day of the week as part of the date+time stamp. Monday is A, Tuesday is B, and so on.

The default Denote identifier is a compact representation of the date and time, with the letter T in between. For example:

20250924T190920

The letter T does not have any special meaning. It simply delimits the two constituents of the identifier. Users who want to record the day of the week can ultimately derive identifiers that look like these:

20250922A082941
20250923B140652
20250924C191038

And with some spaces for didactic purposes:

2025 09 22   A   08 29 41
2025 09 23   B   14 06 52
2025 09 24   C   19 10 38

[ Actually, users can produce identifiers with such spaces, but I will leave this as an exercise for interested parties. ]

Get the day of the week as a capital letter

To get the day of the week as a string that holds a number, we use the %u format specifier of the function format-time-string. Today is Wednesday, thus:

(format-time-string "%u")
;; => "3"

Based on this, we know that we need a function that takes such a string and returns the corresponding capital letter. Here is one way of achieving as much:

(defun my-denote-get-day-of-week-as-alpha (day)
  "Return the corresponding capital letter for DAY.
DAY is a string holding a number, as the return value of the %u
specifier in `format-time-string'.

If DAY is a number, convert it to a string and then return its
corresponding letter."
  (pcase (if (numberp day) (number-to-string day) day)
    ("1" "A")
    ("2" "B")
    ("3" "C")
    ("4" "D")
    ("5" "E")
    ("6" "F")
    ("7" "G")
    (_ (error "The day `%S' is not among 1-7" day))))

The pcase macro does the heavy lifting here. We basically test for string equality and return a new string or throw an error. Testing the code, I get these results:

(my-denote-get-day-of-week-as-alpha "3")
;; => "C"

(my-denote-get-day-of-week-as-alpha 3)
;; => "C"

(my-denote-get-day-of-week-as-alpha "10")
;; => ERROR

(my-denote-get-day-of-week-as-alpha 10)
;; => ERROR

Tweak the Denote identifier format to pass the %u specifier

Denote stores the format-time-string specifiers for its default identifier in the variable denote-date-identifier-format. The value is "%Y%m%dT%H%M%S", which is what derives the aforementioned standard identifier.

We already noted that we do not want that literal T over there. So let us make our format the same as the original one except that we include %u in place of T. A function call that would yield the desired result is this:

(replace-regexp-in-string "T" " %u " denote-date-identifier-format t)
;; => "%Y%m%d %u %H%M%S"

Notice that I add a space before and after the %u. These are delimiters that we will use to split the string more easily into its DATE, DAY, TIME components. But one step at a time. We first need to define this as a variable:

[ Technically, this is not a normal variable because of defconst instead of the more common defvar, but we do not need to consider such details. ]

(defconst my-denote-date-identifier-format
  (replace-regexp-in-string "T" " %u " denote-date-identifier-format t))

Format a date using the new identifier scheme

Our next task is to write a small function that takes a date argument and returns a string whose pattern follows what we did in the previous section. For example, if the current date is 2025-09-24, the day is Wednesday, and the time is 19:30:00, we expect an identifier like 20250924C193000.

To keep things simple, we will not go into how Emacs represents dates internally. It does not matter, anyway, because Denote handles that part internally. All we need to test our function is to use the return value of the function current-time. Actually, even that is optional because format-time-string defaults to that if it is not given an explicit date as an argument.

As such, here is how we get the string "DATE DAY TIME", based on what we have:

(format-time-string my-denote-date-identifier-format)
;; => "20250924 3 193347"

Remember those spaces from earlier? We need them now to split this string into a list of three strings, so that we can isolate the day in the middle. Once we have just the day, we can pass it to the function we wrote earlier that gives us the corresponding capital letter.

To split a string at the spaces, we do this (read the split-string doc string for further details):

(split-string STRING)

Which means:

(split-string (format-time-string my-denote-date-identifier-format))
;; => ("20250924" "3" "193626")

We get back a list of strings, so the day is retrieved thus:

(nth 1 '("20250924" "3" "193626"))
;; => "3"

Use (nth 0 ...) for the date and (nth 2 ...) for the time.

Now that we know all this, we can piece it together into a single function. Here is what we will do, which I shall explain in further detail below:

(defun my-denote-format-date (date)
  "Format DATE using `my-denote-date-identifier-format'.
Represent the day of the week with `my-denote-get-day-of-week-as-alpha'."
  (pcase-let* ((identifier-string (format-time-string my-denote-date-identifier-format date))
               (`(,date ,day ,time) (split-string identifier-string))
               (day-as-letter (my-denote-get-day-of-week-as-alpha day)))
    (concat date day-as-letter time)))

The pcase-let* macro uses “destructuring” to pattern match the return value and bind it to the variables we name (also see my free (gratis and libre) book: Emacs Lisp Elements). This is the short way of doing the following:

(defun my-denote-format-date (date)
  "Format DATE using `my-denote-date-identifier-format'."
  (let* ((identifier-string (format-time-string my-denote-date-identifier-format date))
         (strings (split-string identifier-string))
         (date (nth 0 strings))
         (day (nth 1 strings))
         (time (nth 2 strings))
         (day-as-letter (my-denote-get-day-of-week-as-alpha day)))
    (concat date day-as-letter time)))

Use whichever style you prefer.

The point is that we (i) take the return value of format-time-string with the spaces, as I showed above, (ii) split it at the spaces into three strings, (iii) assign each of those strings to a variable local to this function, (iv) convert the day from a number to a capital letter, and (v) put it all back together without those spaces. The result is this:

(my-denote-format-date (current-time))
;; => "20250924C194219"

Write and then use the custom denote-get-identifier-function

The variable denote-get-identifier-function has the symbol of a function as its value. Its documentation describes the technicalities. Though, again, we do not need to understand the finer points to achieve our goal. Since our custom identifier is almost the same as the default, we can copy the original function that Denote relies on and make a small change to it so that it uses the my-denote-format-date we just wrote. Behold:

(defun my-denote-generate-identifier-as-date (initial-identifier date)
  "Generate an identifier based on DATE.

If INITIAL-IDENTIFIER is not already used, return it.  Else, if it is
possible to derive an identifier from it, return this identifier.

Else, use the DATE.  If it is nil, use `current-time'.

Slightly modified version of `denote-generate-identifier-as-date'."
  (let ((denote-used-identifiers (or denote-used-identifiers (denote--get-all-used-ids))))
    (cond ((and initial-identifier
                (not (gethash initial-identifier denote-used-identifiers)))
           initial-identifier)
          ((and initial-identifier
                (string-match-p denote-date-identifier-regexp initial-identifier)
                (date-to-time initial-identifier))
           (denote--find-first-unused-id-as-date initial-identifier))
          (t
           (denote--find-first-unused-id-as-date
            (my-denote-format-date (or date (current-time))))))))

The internal workings do not matter right now, though I am happy to explain them elsewhere. Our priority is to find where my-denote-format-date is used. The only difference between what we have here and the original is that our final line uses my-denote-format-date, while the original does a format-time-string with the denote-date-identifier-format (which we saw further above when we replaced T with %u).

Finally, bind denote-get-identifier-function to the symbol of the custom function to start using it:

(setq denote-get-identifier-function #'my-denote-generate-identifier-as-date)

All Denote files will henceforth look like this:

@@20250924C190301--this-is-a-test__denote_testing.txt

Remember that the @@ exists for custom identifiers and that all the components of the file name can be reordered.

This covers it! The manual has more examples and I always am eager to help anyone who needs to do something a little bit differently.

About Denote

Denote is a simple note-taking tool for Emacs. It is based on the idea that notes should follow a predictable and descriptive file-naming scheme. The file name must offer a clear indication of what the note is about, without reference to any other metadata. Denote basically streamlines the creation of such files while providing facilities to link between them.

Denote’s file-naming scheme is not limited to “notes”. It can be used for all types of file, including those that are not editable in Emacs, such as videos. Naming files in a consistent way makes their filtering and retrieval considerably easier. Denote provides relevant facilities to rename files, regardless of file type.

[ I have a page with all my Emacs packages, which includes all the Denote extensions I maintain: https://protesilaos.com/emacs. ]

]]>
Emacs: the next version of Denote will support custom identifiers Information about the upcoming release of Denote that will allow advanced users or developers to use custom identifiers. Sat, 20 Sep 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-09-20-emacs-denote-custom-identifiers/ https://protesilaos.com/codelog/2025-09-20-emacs-denote-custom-identifiers/ There are a lot of developments happening in denote and the various other extensions for it that I maintain. I will share more details in the release notes, hopefully before the end of this month. Just to give you a forewarning about a potentially massive boost for advanced users or developers: the ability to specify a completely custom identifier scheme for Denote file names.

By default, Denote constructs a file name to have, at minimum, an identifier as a compact representation of the date and time. It looks like this: 20250920T120924. The default file will also have a title and keywords, based on user input at the relevant minibuffer prompts, so it will look like this:

20250920T120924--denote-custom-identifiers__emacs_programming.txt

Instead of hardcoding the scheme of an identifier as a compact representation of a date and time, we provide the variable denote-get-identifier-function. Its value is the symbol of a function, which is called to yield an identifier, as a string.

I have written a few examples of this in the Denote manual, grouped under this section: https://protesilaos.com/emacs/denote#h:3048f558-7d84-45d6-9ef2-53055483e801. Read the documentation of denote-get-identifier-function for the remaining technicalities.

The identifier can be anything from an automatic incremental numbering scheme to something that always asks for user input to produce a more information-dense result. To illustrate the potential of the latter concept, the manual elaborates on the use-case of recording data about academic publications, such as the editor, authors, and publisher, through a series of minibuffer prompts. The end result is a unique identifier with the help of some extra helper functions.

Custom identifiers are prefixed with the @@ file name component separator. This way they are unambiguous and can be retrieved with certainty. More so since the Denote file name components can be presented in any order, per the user option denote-file-name-components-order.

Custom identifiers are the culmination of many changes over the years to make the Denote file-naming scheme as flexible as possible. It is super effective out-of-the-box and can then be particularised to specific workflows with ease. These are not mutually exclusive, as users can still rely on the regular Denote functionality for most cases and only deviate from it with bespoke functions where necessary. For instance, to have a special variant of denote-rename-file that applies a custom identifier scheme instead of the default, users can write a wrapper command like this:

(defun my-denote-rename-file-with-my-custom-identifier ()
  "Like `denote-rename-file' but use `my-denote-get-custom-identifier' instead."
  (interactive)
  (let ((denote-get-identifier-function #'my-denote-get-custom-identifier))
    (call-interactively 'denote-rename-file)))

Imagine doing this for files in a specific folder where the standard identifier provided by Denote does not add much value (beside being a unique match for the linking mechanism, that is).

The Denote manual is full of examples like the above. These sort of small and elegant extensions are possible owning to the design of the code into easily adaptable functions.

We keep going from strength to strength and I am delighted with the results. I hope you make good use of the tools on offer. Let me know if there is anything more you need: I am confident we can make it happen.

Much of the thought and work that went is to this project is thanks to user mentalisttraceur and long-time contributor Jean-Philippe Gagné Guay.

About Denote

Denote is a simple note-taking tool for Emacs. It is based on the idea that notes should follow a predictable and descriptive file-naming scheme. The file name must offer a clear indication of what the note is about, without reference to any other metadata. Denote basically streamlines the creation of such files while providing facilities to link between them.

Denote’s file-naming scheme is not limited to “notes”. It can be used for all types of file, including those that are not editable in Emacs, such as videos. Naming files in a consistent way makes their filtering and retrieval considerably easier. Denote provides relevant facilities to rename files, regardless of file type.

[ I have a page with all my Emacs packages, which includes all the Denote extensions I maintain: https://protesilaos.com/emacs. ]

]]>
Emacs: show-font version 1.0.0 Information about the latest version of my show-font package for GNU Emacs. Sun, 07 Sep 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-09-07-emacs-show-font-1-0-0/ https://protesilaos.com/codelog/2025-09-07-emacs-show-font-1-0-0/ This package lets you preview a font inside of Emacs. It does so in three ways:

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

Sources:

Below are the release notes.


Version 1.0.0 on 2025-09-07

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

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

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

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

Checking for language support among known families

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

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

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

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

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

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

Support for music notation, mathematics, and other symbols

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

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

Problematic fonts are hidden from the list view

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

Show a full preview from the list view

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

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

Quickly copy the name of the font in the list view

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

]]>
Emacs: doric-themes version 0.4.0 Minimalist themes for GNU Emacs to complement my ef-themes (maximalist) and modus-themes (moderate). Mon, 01 Sep 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-09-01-emacs-doric-themes-0-4-0/ https://protesilaos.com/codelog/2025-09-01-emacs-doric-themes-0-4-0/ These are my minimalist themes. They use few colours and will appear mostly monochromatic in many contexts. Styles involve the careful use of typography, such as italics and bold italics.

If you want maximalist themes in terms of colour, check my ef-themes package. For something in-between, which I would consider the best “default theme” for a text editor, opt for my modus-themes.

Below are the release notes.


Update to doric-themes version 0.4.0

This version brings several refinements to the package, as well as two new themes.

Enjoy doric-beach and doric-valley

Most of the Doric themes feel monochromatic. By contrast, the doric-beach (light) and doric-valley (dark) are dichromatic: they combine warm hues, such as orange, with cold hues like teal. They still are minimalistic, like the rest of the family, but appear a bit more playful than their more austere counterparts.

[ The doric-oak and doric-pine are similar in this regard. ]

Refashioned diffs

All diff interfaces, including Magit, diff-mode, and Ediff now rely on a comprehensive new subset of colours. They use colour-coded backgrounds throughout, whereas before they had just colour-coded text. The problem with highlighting only text is that it is harder to (i) discern the colour and thus (ii) quickly estimate the boundaries of a change.

For Magit in particular, there are distinct styles for the highlighted/current diff hunk, all other diff hunks, as well as the common word-wise (“refined”) diffs that all interfaces share.

Org agenda and dates are more consistent

The changes here are subtle but should contribute to a more pleasant experience, owning to the more careful emphasis of information. “Scheduled” entries are easier to notice, as they are distinct from other events. Date headings also have a more clear distinction from the tasks they contain.

For the M-x calendar, in particular, month and date headings are revised to be consistent with the Org agenda, while the diary and holiday faces are redone to look harmonious in context. Thanks to Amin Bandali for checking those and suggesting some tweaks.

Certain header-like faces stand out more

In various contexts, such as in git-mode commit message comments or Dired buffers, there are pieces of text that conceptually are headings. Those are rendered in a distinct style than other generic “bold” faces, to better perform their function.

Flymake fringe indicators are easier to spot

Those now have a fine background colour, coded to the type of warning.

Support for the lin and pulsar packages

Those define faces that affect the background of a line. These packages now feel right when used in tandem with the doric-themes.

]]>
Emacs: show-font version 0.4.0 Information about the latest version of my show-font package for GNU Emacs. Tue, 26 Aug 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-08-26-emacs-show-font-0-4-0/ https://protesilaos.com/codelog/2025-08-26-emacs-show-font-0-4-0/ This package lets you preview a font inside of Emacs. It does so in three ways:

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

Sources:

Below are the release notes.


Version 0.4.0 on 2025-08-26

This version expands the capabilities of the font preview mechanism to handle emoji and icon fonts (i.e. those with codepoints in the Unicode Private Use Area).

Both the show-font-select-preview and show-font-tabulated commands now handle these types of font.

Previews for emoji or icon fonts are done using the string of characters set to the variable show-font-emoji-sample or show-font-icon-sample. These symbols are user options.

]]>
Emacs: in-development ‘doric-beach’ and ‘doric-valley’ themes I am developing two new themes for my minimalistic 'doric-themes' package for Emacs. These combine gold with teal hues. Sun, 17 Aug 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-08-17-emacs-doric-beach-and-doric-valley-themes/ https://protesilaos.com/codelog/2025-08-17-emacs-doric-beach-and-doric-valley-themes/ I am developing two new themes for my minimalistic doric-themes package for Emacs. These combine gold with teal hues. doric-beach is the light theme and doric-valley is its dark counterpart. Here are the screenshots:

doric-beach theme sample

doric-valley theme sample

Coming in version 0.4.0

The character of the themes is well-defined, though I may still make some small tweaks. Expect these and other improvements to be available in the next stable version of the doric-themes, which I expect to publish some time before the end of August.

About the Doric themes

The Doric themes use few colours and will appear monochromatic in many contexts. They are my most minimalist themes. Styles involve the careful use of typographic features and subtleties in colour gradients to establish a consistent rhythm.

If you want maximalist themes in terms of colour, check my ef-themes package. For something in-between, which I would consider the best “default theme” for a text editor, opt for my modus-themes.

]]>
Emacs: sxhkdrc-mode version 1.2.0 Information about the latest version of my Emacs major mode for editing the Simple X Hot Key Daemon files. Thu, 14 Aug 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-08-14-emacs-sxhkdrc-mode-1-2-0/ https://protesilaos.com/codelog/2025-08-14-emacs-sxhkdrc-mode-1-2-0/ This is a major mode for editing sxhkdrc files. SXHKD is the Simple X Hot Key Daemon which is commonly used in minimalist desktop sessions on Xorg (I use it with bspwm, herbstluftwm, and i3wm). The sxhkdrc file configures key chords, binding them to commands. For the technicalities, read the man page sxhkd(1).


1.2.0 on 2025-08-14

The package is stable and gets the job done. This version introduces a small new feature to restart the daemon from inside Emacs. Thanks to Jonathan Neidel for making the suggestion in issue 1: https://github.com/protesilaos/sxhkdrc-mode/issues/1.

Reload the SXHKD daemon on demand

The command sxhkdrc-mode-restart sends a signal to the sxhkd process which causes it to restart, thus reloading its configuration file. Use this after modifying the sxhkdrc to make the new changes available.

Automatically reload the daemon on file save

The function sxhkdrc-mode-auto-restart can be assigned to the sxhkdrc-mode-hook to automatically reload the daemon after the sxhkdrc file is saved (well, technically, after the file which is using the sxhkdrc-mode is saved).

Sample configuration with use-package

The project’s README.md includes this sample configuration:

(use-package sxhkdrc-mode
  :ensure t
  :mode "sxhkdrc.*" ; if you want more than just "sxhkdrc"
  :commands (sxhkdrc-mode-restart)
  :hook (sxhkdrc-mode . sxhkdrc-mode-auto-restart))
]]>
Emacs: doric-themes version 0.3.0 Minimalist themes for GNU Emacs to complement my ef-themes (maximalist) and modus-themes (moderate). Mon, 11 Aug 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-08-11-emacs-doric-themes-0-3-0/ https://protesilaos.com/codelog/2025-08-11-emacs-doric-themes-0-3-0/ These are my minimalist themes. They use few colours and will appear mostly monochromatic in many contexts. Styles involve the careful use of typography, such as italics and bold italics.

If you want maximalist themes in terms of colour, check my ef-themes package. For something in-between, which I would consider the best “default theme” for a text editor, opt for my modus-themes.

Below are the release notes.


The new oak and pine themes

These explore the woody+earthly style:

  • doric-oak has dark text against an ochre background, with accents of green.

  • doric-pine uses light text against a dark green background, with accents of brown.

Background colours for diffs

All diff-related interfaces, including Magit, diff-mode, and Ediff, now use colour-coded background values where appropriate. This is done to improve usability, as it otherwise can be hard to discern the boundaries of individual diff hunks.

Alternating foreground values for message/email quotes

In message-mode, Gnus, and related interfaces all quoted/cited message level now conforming with an odd VS even colouring scheme. The style is still subtle, but now the individual levels of depths are easier to spot.

]]>
I got the Emacs Writing Studio (EWS) book I have the Emacs Writing Studio paperback version of the book. It is nice and shows that we can use Emacs for publishing. Wed, 06 Aug 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-08-06-emacs-writing-studio-book/ https://protesilaos.com/codelog/2025-08-06-emacs-writing-studio-book/ The Emacs Writing Studio (EWS) by Peter Prevos is a configuration for Emacs designed for writers, researchers, and scientists. It provides an integrated environment to express one’s thoughts and publish them in multiple formats. The book, which is produced using EWS, documents the setup, describes relevant methods or workflows, and explains how everything is pieced together. I contributed the foreword.

This morning, I got the paperback version of the book. It is a thing of beauty!

EWS front cover

EWS dedication

Thanks to Peter for working on this and for showing how Emacs can also be used as a professional publishing tool.

Emacs Writing Studio sources

Buy the book, check the source code, and watch the videos:

Also read the Why Use Emacs essay on Peter’s website: https://lucidmanager.org/productivity/why-use-emacs/.

]]>
Emacs: new ‘oak’ and ‘pine’ doric-themes These are two new themes for my minimalist doric-themes package for Emacs. Mon, 04 Aug 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-08-04-emacs-doric-oak-pine-themes/ https://protesilaos.com/codelog/2025-08-04-emacs-doric-oak-pine-themes/ I am working on two new themes for my minimalist doric-themes collection. Both explore the woody, earthly, chthonic motif. Here they are:

doric-oak theme sample

doric-pine theme sample

I may still make further refinements, though the character of the themes is set. Once I am done, I will publish them as part of version 0.3.0 of the package.

About the Doric themes

The Doric themes use few colours and will appear monochromatic in many contexts. They are my most minimalist themes. Styles involve the careful use of typographic features and subtleties in colour gradients to establish a consistent rhythm.

If you want maximalist themes in terms of colour, check my ef-themes package. For something in-between, which I would consider the best “default theme” for a text editor, opt for my modus-themes.

]]>
Deep dive with @linkarzu about Emacs, NeoVim, Linux, keyboards, and philosophy A discussion for more than 2 hours with Christian in which we discuss Emacs and many other interesting topics. Fri, 01 Aug 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-08-01-linkarzu-chat-emacs-neovim-philosophy/ https://protesilaos.com/codelog/2025-08-01-linkarzu-chat-emacs-neovim-philosophy/ Raw link: https://www.youtube.com/watch?v=b4nV0jCHwGQ

I had a ~2-hour-and-30-minute discussion with Christian from the @linkarzu YouTube channel: https://www.youtube.com/@linkarzu.

We talked about Emacs, the underlying idea of an integrated computing environment, how NeoVim effectively took the source of Vim and infused with the spirit of Emacs, thinking in terms of extensibility and cohesion, why purists cannot impose an arbitrary limit to extensibility, and more.

We also discuss other interesting topics, such as Debian and Arch Linux, how free software emphasises freedom, why it is okay to earn an income while contributing to free software, custom keyboards and ergonomics, my journey into computing, alcohol and substance abuse, and other issues of everyday life.

Thanks to Christian for inviting me to this chat! I had a good time and wish all the best with the @linkarzu channel!

]]>
All my videos are mirrored on the Internet Archive (thanks to Amin Bandali) All my videos are now available on a hosting platform that respects user freedom. Tue, 29 Jul 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-07-29-videos-internet-archive/ https://protesilaos.com/codelog/2025-07-29-videos-internet-archive/ A few days ago, Amin Bandali contacted me about the prospect of mirroring my videos to the Internet Archive. The idea is to have the option of a video hosting platform that respects user freedom. I agreed and confirmed the free/libre copyleft terms I share all my publications under (GNU GPLv3+ for code, Creative Common BY-SA 4.0 for prose, GNU FDL for my technical manuals).

Amin has since done the work and documented it here: https://kelar.org/~bandali/2025/07/25/protesilaos-videos-archive.html. The publication also points to the Python script which performs the requisite operations. The script relies on the source code of my website to extract the relevant data. Amin describes the underlying technical considerations, given the large number of videos that needed to be downloaded from YouTube and uploaded to the Internet Archive.

On my part, I made a small change to the template of my website that produces the HTML output of entries with an embedded video. Those have links to the source on YouTube and, now, to the corresponding Internet Archive page. For example, my latest “Prot Asks” video with Ihor, the Emacs Org mode maintainer, is available here: https://archive.org/details/prot-codelog-2025-07-26-prot-asks-ihor-emacs-org-maintainer-history-travel-material-science/.

These “raw links”, as opposed to the embedded frame, are also helpful for users who receive my publications via RSS/Atom feeds (and I do share the entire blog post, by the way, rather than an excerpt because that is the most convenient way to read RSS).

Thanks to Amin for this initiative!

]]>
I will talk about Emacs on the @linkarzu YouTube channel An exchange with Christian of the @linkarzu channel on YouTube about Emacs and how I use it every day. Sun, 27 Jul 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-07-27-talk-emacs-linkarzu-youtube-channel/ https://protesilaos.com/codelog/2025-07-27-talk-emacs-linkarzu-youtube-channel/ The @linkarzu channel on YouTube covers topics related to NeoVim, terminal emulators, and Emacs, among others: https://www.youtube.com/@linkarzu. They recently had a roundtable about “NeoVim versus Emacs” in which two members on the side of either community shared their thoughts and had a fun time together: https://www.youtube.com/watch?v=SnhcXR9CKno.

Christian, the author of @linkarzu, learnt about me via feedback about the roundtable and contacted me shortly thereafter. We agreed to have a video exchange focused on Emacs. The idea is for me to share my thoughts on the matter and demonstrate my day-to-day workflow.

The live event is for paying members of @linkarzu and can be checked here: https://www.youtube.com/live/KD9uiDdQDzI (Thursday, July 31 at 15:00 Europe/Athens). The recording of the video will be available to everyone shortly afterwards and will be free of charge.

Christian wanted to check with me if this practice is acceptable. I confirmed that it is fine by me and am looking forward to a nice chat!

Once the video is published, I will also share it on my website.

]]>
Emacs: cursory version 1.2.0 Information about the latest version of my Cursory package for GNU Emacs. Tue, 22 Jul 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-07-22-emacs-cursory-1-2-0/ https://protesilaos.com/codelog/2025-07-22-emacs-cursory-1-2-0/ Cursory lets users define preset configurations for the cursor. Those cover the style of the cursor (e.g. box or bar), whether it is blinking or not, and how fast, as well as the colour it uses. Having distinct presets makes it easy to switch between, say, a “reading mode” with an ambient cursor and a “presentation mode” with a cursor that is more noticeable and thus easier to spot.

Below are the release notes.


Version 1.2.0 on 2025-07-22

This version contains small additions to a stable package.

Set the last preset when starting up Emacs

The new function cursory-set-last-or-fallback makes it easier to set the last known preset when starting Emacs or via a hook such as after-init-hook. Internally, it takes care to fall back to a set of default values that always work.

Before the introduction of cursory-set-last-or-fallback users had to do something like this:

;; Old way of setting a preset:
(cursory-set-preset (or cursory-last-selected-preset cursory-recovered-preset 'box))

;; Old way of doing the above via a hook:
(add-hook 'after-init-hook (lambda () (cursory-set-preset (or cursory-last-selected-preset cursory-recovered-preset 'box))))

Those would also fail if the named preset did not exist (box in the above example). Whereas the addition of a fallback preset guarantees a result that works.

Note that I am defining the cursory-fallback-preset using defconst instead of exposing it as a user option. This is to avoid a scenario where the values are accidentally set incorrectly.

Presets can define a :cursor-color

This is a new attribute which corresponds to the background value of the cursor face.

  • When the value is nil or unspecified (the default), Cursory does not modify the cursor face.

  • When the value is a hexadecimal RGB color value, like #123456 it is used as-is. Same if it is a named color among those produced by the command list-colors-display.

  • When the value is the symbol of a face (unquoted), then the foreground of that face is used for the cursor face, falling back to default.

Concretely, users can have something like this in their configuration:

(setq cursory-presets
      '((box
         :cursor-color "#21439f"
         :blink-cursor-interval 1.2)
        (baring
         :cursor-type (bar . 2)
         :cursor-color error ; the `error' face will typically be red (see `list-faces-display')
         :blink-cursor-interval 0.8)
        (underscore
         :cursor-color "green" ; see `list-colors-display'
         :cursor-type (hbar . 1)
         :blink-cursor-interval 0.3
         :blink-cursor-blinks 50)
        (t ; the default values
         :cursor-color unspecified ; use the theme's original
         :cursor-type box
         :cursor-in-non-selected-windows hollow
         :blink-cursor-mode 1
         :blink-cursor-blinks 10
         :blink-cursor-interval 0.2
         :blink-cursor-delay 0.2)))

Remember to read the documentation of cursory-presets for all the rest.

The cursory-mode persists the :cursor-color while changing themes

Before, the cursory-mode would only take care to save the last selected preset and to persist it across Emacs sessions. In addition to that, it now also ensures that loading a new theme does not override the :cursor-color.

The cursory-set-preset prompt is smarter about its default value

When the cursory-set-preset is called interactively, it uses the minibuffer to prompt for a preset among the cursory-presets.

In the past, its default value would simply be the last selected preset. Cursory would not check whether that symbol was still a member of the cursory-presets. This had the potential to set the wrong configurations.

Now the prompt only uses as its default value the last selected and existing preset among those found in the history of selections. It will not provide a default if it cannot find any.

Note that the “default value” in the context of the minibuffer refers to the input that will normally be provided if the user types RET without writing anything into the minibuffer.

]]>
Emacs: dired-preview version 0.6.0 Information about the latest version of my dired-preview package for GNU Emacs. Fri, 18 Jul 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-07-18-emacs-dired-preview-0-6-0/ https://protesilaos.com/codelog/2025-07-18-emacs-dired-preview-0-6-0/ This is a simple package to automatically preview in a window the file at point in Dired buffers. Preview windows are closed when they are no longer relevant, while preview buffers are killed if they have not been used for other purposes beside previewing. The package provides several customisation options to control its behaviour.

Below are the release notes


Version 0.6.0 on 2025-07-18

This is a small release that provides quality-of-life refinements.

Optionally do not trigger a preview when entering the directory

The new user option dired-preview-trigger-on-start controls whether a preview is produced automatically when (i) entering a directory while (ii) the dired-preview-mode or its global counterpart is enabled.

The default value is non-nil, which preserves the behaviour we have always had of previewing outright. When set to nil, the preview does not happen upon entering a directory and is triggered only after one of the commands in denote-preview-trigger-commands is invoked.

I did this is in response to issue 31 by dasoju: https://github.com/protesilaos/dired-preview/issues/31.

Define which commands trigger a preview

The denote-preview-trigger-commands is now declared as a “user option” rather than a generic variable, meaning that users are encouraged to customise it (and it technically is available via the Custom interface and related). Everything should otherwise work the same as before.

The preview does not interfere with dired-dwim-target

Previous versions would make dired-dwim-target not return the directory of the other window. Whereas we want the preview to not influence how Dired behaves when copying or renaming files.

The bug was addressed in patch release 0.5.2.

Fixed a temporary bug in dired-preview-page-up

It was missing the macro we define to perform operations in the preview window.

Thanks to Alex Popescu for telling me that the command was not working. This was done in issue 28: https://github.com/protesilaos/dired-preview/issues/28.

The bug was addressed in patch release 0.5.1.

]]>
Emacs: reorder Denote file name components Video where I explain how to use the 'denote-file-name-components-order' and retroactively make all your Denote files follow your preference. Wed, 09 Jul 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-07-09-emacs-denote-reorder-components/ https://protesilaos.com/codelog/2025-07-09-emacs-denote-reorder-components/ Raw link: https://www.youtube.com/watch?v=30uvxQMVqhg

In this ~13-minute video I explain how to use the Denote user option denote-file-name-components-order. Then I show how to retroactively rename all the files that have the Denote file-naming scheme so that they follow the desired order. In the process, I cover the command denote-sort-dired (alias denote-dired), which helps produce a flat listing of Denote files, even if they exist in subdirectories of the denote-directory.

The code used in this video:

;; The default:
(setq denote-file-name-components-order '(identifier signature title keywords))

;; Any order will work.  Here is the one I am using for this demonstation:
(setq denote-file-name-components-order '(identifier signature keywords title))

;; And here is another:
(setq denote-file-name-components-order '(identifier keywords title signature))

;; And yet another one for the sake of completeness:
(setq denote-file-name-components-order '(title keywords signature identifier))

(defun prot/denote-rename-all-to-reorder-components ()
  "Call `denote-dired-rename-files' without any prompts.
In other words, preserve the value of each Denote file name component.

Use this command if you wish to modify the user option
`denote-file-name-components-order' and then want your existing Denote
files to retroactively follow that order."
  (interactive)
  (let ((denote-prompts nil))
    (call-interactively 'denote-dired-rename-files)))
]]>
Emacs: mct version 1.1.0 Information about the latest version of my mct package for GNU Emacs. Mon, 07 Jul 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-07-07-emacs-mct-1-1-0/ https://protesilaos.com/codelog/2025-07-07-emacs-mct-1-1-0/ Opinionated changes and enhancements to the default minibuffer completion UI of Emacs:

  • Live completions to update the results as you type.

  • Passlist and blocklist of commands or completion categories to control whether the *Completions* buffer shows up eagerly.

  • Other relevant options to control when the *Completions* are displayed.

  • Per command or completion category sorting methods.

  • A cleaner *Completions* buffer, optionally without a mode line.

  • Commands to cycle from the minibuffer to the *Completions* and vice versa.

In essence, MCT is (i) a layer of interactivity on top of the out-of-the-box completion experience, and (ii) glue code that combines built-in functionalities to make the default completion framework work like that of more featureful third-party options.

Below are the release notes.


Version 1.1.0 on 2025-07-07

This version contains several refinements to an already stable package.

Sort by command or completion category

The new user option mct-sort-by-command-or-category determines how completion candidates are sorted.

This is an alist where each element is of the form (SYMBOLS . SORT-FUNCTION).

SYMBOLS is either a symbol or a list of symbols. SYMBOLS can refer to the symbol of a function or completion category. It can also be t, which refers to the fallback value.

SORT-FUNCTION is a function that takes a list of strings and returns a list of strings, sorting them accordingly. Examples of a SORT-FUNCTION are:

  • mct-sort-by-alpha
  • mct-sort-by-alpha-then-by-length
  • mct-sort-by-history
  • mct-sort-by-directory-then-by-file

To not perform any sorting on the completion candidates that match SYMBOLS set SORT-FUNCTION to nil.

If there are conflicting configurations between a SYMBOLS function and completion category, then the function takes precedence (for example find-file is set to sort directories first whereas the file completion category is set to sort by history).

Optional indicator for completing-read-multiple

Users of Emacs prior to version 31 do not have a built-in way to inform them when they are dealing with a completing-read-multiple minibuffer prompt. Emacs 31 introduces the user option crm-prompt and its related functionality to tell the user what they need to know.

The mct-completing-read-multiple-indicator can be used in the meantime to achieve the same results. It is set to a non-nil value by default. Opt out by changing it to nil.

The *Completions* are persistent when needed

This concerns the case where a command or completion category is part of the mct-completion-passlist or when the user option mct-live-completion is set to non-nil or visible. In such cases, the completion candidates are on display and we want to keep them there while performing a dynamic completion, such as with the find-file command (“dynamic” in the sense that it returns a new list of candidates to match the current path).

Persisting the *Completions* means that as we narrow the list, we still see all the matching results.

In the past, we provided the option mct-persist-dynamic-completion though we do not need it anymore.

I was inspired to make this change in response to a question posed by Ryan Davis regarding the behaviour of mct-persist-dynamic-completion. This was done in issue 7: https://github.com/protesilaos/mct/issues/7.

Miscellaneous

  • Vertical alignment of the *Completions* buffer is more precise. Thanks to Jessie Hu for the contribution in pull request 6: https://github.com/protesilaos/mct/pull/6.

  • The command mct-choose-completion-exit no longer tries to expand further. In the previous implementation it would try to match the last known selection from the history when using a file prompt. For example we have this workflow:

    • In the previous prompt we type /path/to/file/ and exit.
    • Now we type /pa, the completions pop up, we select /path and invoke mct-choose-completion-exit. This wrongly expands into /path/foo/ instead of taking just /path (given that it has no further input to determine an extension of that string).

    Now the command will do the right thing based on the user’s input.

]]>
Emacs: doric-themes version 0.2.0 Minimalist themes for GNU Emacs to complement my ef-themes (maximalist) and modus-themes (moderate). Sat, 05 Jul 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-07-05-emacs-doric-themes-0-2-0/ https://protesilaos.com/codelog/2025-07-05-emacs-doric-themes-0-2-0/ These are my minimalist themes. They use few colours and will appear mostly monochromatic in many contexts. Styles involve the careful use of typography, such as italics and bold italics.

If you want maximalist themes in terms of colour, check my ef-themes package. For something in-between, which I would consider the best “default theme” for a text editor, opt for my modus-themes.

Below are the release notes.


Version 0.2.0 on 2025-07-05

This version introduces several refinements to the individual themes comprising the Doric themes collection. Changes pertain to the intensity of colours in use. While each tweak is small, their cumulative effect contributes to a more consistent design.

Users who are interested in the contrast ratio values and relevant colour distance can refer to the contrasts.org file that is part of the project’s Git repository: https://github.com/protesilaos/doric-themes.

I extended support for several faces or face groups including:

  • ace-window
  • dictionary
  • embark-keybinding
  • man
  • markdown-metadata-key-face
  • package-mark-delete-line
  • package-mark-install-line
  • read-multiple-choice-face
  • rcirc
  • spacious-padding
  • textsec-suspicious
  • which-key-key-face
  • woman

Some other faces that were already covered are revised in the interest of theme-wide consistency. Again, changes are subtle.

The colour of the directory icons in all-the-icons and nerd-icons packages is toned down a little bit to avoid exaggerations.

Several spacing-sensitive faces, like Org tables and code blocks, unconditionally inherit the fixed-pitch face. This means that, in principle, they are rendered in a monospaced font even when the user activates variable-pitch-mode or sets the default face to a proportionately spaced typeface. Users who need to specify the applicable font family can either use the following, mutatis mutandis, or take a look at my fontaine package:

(set-face-attribute 'default nil :family "Aporetic Sans Mono" :height 160)
(set-face-attribute 'variable-pitch nil :family "Aporetic Sans" :height 1.0)
(set-face-attribute 'fixed-pitch nil :family "Aporetic Sans Mono" :height 1.0)

Other theme packages of mine have an option for “mixed fonts” (like modus-themes-mixed-fonts), but I think I will not be providing options for the Doric themes. At least not for the time being while I explore the design space for minimalist themes.

]]>
Emacs: beframe version 1.4.0 Information about the latest version of my beframe package for GNU Emacs. Sat, 28 Jun 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-06-28-emacs-beframe-1-4-0/ https://protesilaos.com/codelog/2025-06-28-emacs-beframe-1-4-0/ beframe enables a frame-oriented Emacs workflow where each frame has access only to the list of buffers visited therein. In the interest of brevity, we call buffers that belong to frames “beframed”.

Below are the release notes


Version 1.4.0 on 2025-06-28

This version adds some minor improvements to a stable package.

Per-frame Xref histories

The built-in Xref mechanism is typically used to navigate to the definition of the symbol at point in a programming major mode. The command xref-find-definitions (M-. by default) jumps to the source, while xref-go-back (M-, by default) goes back in the history of visited positions until it reaches the starting point.

When beframe-mode is enabled, each new frame has its own Xref history. This means that finding a definition in one frame does not interfere with the Xref history of another frame.

“Beframed” buffer prompt text is now optional

When beframe-mode is enabled, it sets the standard read-buffer-function to one that filters buffers by frame. Any command that uses that, such as switch-to-buffer (C-x b by default) is thus beframing its completion candidates.

Such prompts get a prefix to inform the user of their behaviour. By default this is [Beframed]: it is subject to the user option beframe-prompt-prefix. Users who do not wish to have any prefix can set this option to nil or an empty string.

When there is a string, it is styled with the face beframe-face-prompt-prefix.

]]>
Emacs: modus-themes version 4.8.0 Information about the latest version of my highly accessible themes for GNU Emacs. Wed, 11 Jun 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-06-11-emacs-modus-themes-4-8-0/ https://protesilaos.com/codelog/2025-06-11-emacs-modus-themes-4-8-0/ I just published the latest stable release of the Modus themes. The change log entry is reproduced further below. For any questions, you are welcome to contact me. I will now work to apply these same changes to emacs.git, so please wait a little longer for the updates to trickle down to you.


4.8.0 on 2025-06-11

This is a small release that corrects a mistake I made in the previous version. It also introduces some minor refinements.

Matching parentheses are easy to spot

In version 4.7.0, I made the mistake of merging some stylistic tweaks to show-paren-mode that I was experimenting with. The idea was to get a feel for how the subtle colouration of matching delimiters affects the usability of the themes. In short, it is not a good default for our purposes (though users have the option to override the applicable colours, as explained in the Modus themes manual).

Thanks to Morgan Willcock for reporting the unwanted change in issue 139: https://github.com/protesilaos/modus-themes/issues/139.

The bg-paren-match of modus-vivendi-tinted is a bit greener

We go from #5f789f to #4f7f9f. The latter fits better with the rest of the theme.

Refined the “mail” semantic mappings of the tinted themes

This concerns message.el and anything building on top of it, like Gnus, Mu4e, and Notmuch. I made modus-operandi-tinted and modus-vivendi-tinted use two colours that are more in line with the established patterns of their respective theme. The changes are small, but contribute to a more consistent experience.

A new property semantic mapping is available

By default, it uses the same colour as the variable. Users who want to have more refined colouration in supported modes (typically involving tree-sitter), can change the relevant “palette overrides” user option we provide, such as modus-themes-common-palette-overrides or modus-operandi-palette-overrides and related.

Thanks to Alexandr Semenov for requesting this in issue 141: https://github.com/protesilaos/modus-themes/issues/141.

My tmr package is now supported

Its faces were already consistent with the Modus themes, though now I cover them at the theme level to subject them to palette overrides.

The “ancient” Gnus messages are styled properly

Those are only ever seen if the user configures Gnus in a certain way and follows a specific workflow. They now get a subtle foreground value. This is in response to the issue 119 by sivaramn: https://github.com/protesilaos/modus-themes/issues/119.

The modus-themes-rotate command can now go backwards

When called with a prefix argument (C-u by default), this command will rotate the modus-themes-to-rotate from right to left. Otherwise, it goes from left to right.

Thanks to Jacob S. Gordon for the contribution. It was sent as a patch as part of issue 143: https://github.com/protesilaos/modus-themes/issues/143.

]]>
Emacs: spacious-padding version 0.7.0 Information about the latest version of my 'spacious-padding' package for GNU Emacs. Sun, 01 Jun 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-06-01-emacs-spacious-padding-0-7-0/ https://protesilaos.com/codelog/2025-06-01-emacs-spacious-padding-0-7-0/ This is a small release that makes spacious-padding-mode work as intended when used in tandem with the Emacs daemon and subsequent calls to emacsclient -c. I made the function responsible for triggering the “spacious padding” effects work with individual frames and then I responded to issue 33 by Lou Woell about integrating that with the server-after-make-frame-hook: https://github.com/protesilaos/spacious-padding/issues/33.

Additionally, the package now defines two faces that can be used to configure the user option spacious-padding-subtle-mode-line (read its documentation string for all the possible values it accepts).

Here is how they can be set (default value is nil):

(setq spacious-padding-subtle-mode-line
      '( :mode-line-active spacious-padding-subtle-mode-line-active
         :mode-line-inactive spacious-padding-subtle-mode-line-inactive))

Reload the spacious-padding-mode for changes to take effect.

When configured this way and with default styles they make the mode line use a minimalist overline with no background colour. The active mode line has a more noticeable border than the inactive ones. All my themes are designed to support this aesthetic (though themes can style those faces as they see fit).

About Spacious Padding

This package provides a global minor mode to increase the spacing/padding of Emacs windows and frames. The idea is to make editing and reading feel more comfortable. Enable the mode with M-x spacious-padding-mode. Adjust the exact spacing values by modifying the user option spacious-padding-widths.

Inspiration for this package comes from Nicolas Rougier’s impressive designs and Daniel Mendler’s org-modern package.

]]>
Emacs: doric-themes version 0.1.0 Minimalist themes for GNU Emacs to complement my ef-themes (maximalist) and modus-themes (moderate). Tue, 27 May 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-05-27-emacs-doric-themes-0-1-0/ https://protesilaos.com/codelog/2025-05-27-emacs-doric-themes-0-1-0/ I just published the first stable version of my new minimalist themes for Emascs. The Doric themes use few colours and will appear monochromatic in many contexts. Styles involve the careful use of typographic features and subtleties in colour gradients to establish a consistent rhythm.

If you want maximalist themes in terms of colour, check my ef-themes package. For something in-between, which I would consider the best “default theme” for a text editor, opt for my modus-themes.

Below are sample screen shots. The typefaces on display come from my Aporetic fonts.

Samples

doric-cherry

doric-cherry theme sample

doric-earth

doric-earth theme sample

doric-light

doric-light theme sample

doric-marble

doric-marble theme sample

doric-wind

doric-wind theme sample

doric-dark

doric-dark theme sample

doric-fire

doric-fire theme sample

doric-obsidian

doric-obsidian theme sample

doric-plum

doric-plum theme sample

doric-water

doric-water theme sample

]]>
Emacs: live package maintenance (denote, doric-themes, etc.) today 2025-05-21 at 11:00 Europe/Athens time I am doing a live stream today where I will be maintaining some of my packages for Emacs. Wed, 21 May 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-05-21-emacs-live-denote-doric-themes/ https://protesilaos.com/codelog/2025-05-21-emacs-live-denote-doric-themes/ Raw link: https://www.youtube.com/watch?v=JCgI54VxuK0

At 11:00 AM Europe/Athens, I will start streaming my work on some of the Emacs packages I have authored and maintain. I will engage with the chat, if there are any comments, but my focus will be on the code.

The packages I plan to cover are denote, denote-org, denote-sequence, doric-themes. Depending on how it goes, I will work on more of my packages.

The video will be recorded and can be watched later.

All my Emacs-related work: https://protesilaos.com/emacs.

]]>
Emacs: my new Doric themes Minimalist themes for GNU Emacs to complement my ef-themes (maximalist) and modus-themes (moderate). Tue, 13 May 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-05-13-emacs-doric-themes/ https://protesilaos.com/codelog/2025-05-13-emacs-doric-themes/ The doric-themes is my new in-development package for Emacs. It is a set of themes that conform with a minimalist aesthetic: they use few colours and appear monochromatic in many contexts. Below are the screen shots.

In terms of my overall theme work for Emacs, the doric-themes are the most minimalist, ef-themes the most maximalist, and the modus-themes remain what I consider the best “default theme” style. All of them are designed to be highly legible.

I plan to add doric-themes to GNU ELPA within the next days. For the time being, they are only available from source code: https://github.com/protesilaos/doric-themes.

Finally, the backronym for “Doric” is “Doric Only Really Intensifies Conservatively”.

Enjoy your new theme!

Samples

doric-light

doric-light theme sample

doric-marble

doric-marble theme sample

doric-earth

doric-earth theme sample

doric-wind

doric-wind theme sample

doric-dark

doric-dark theme sample

doric-obsidian

doric-obsidian theme sample

doric-fire

doric-fire theme sample

doric-water

doric-water theme sample

]]>
Live @ 2025-05-11, 14:00 Europe/Athens: ‘Ask Me Anything’ about Emacs, Linux, and Life in general I will do a live stream where I answer all questions from the people in the chat. The event will be recorded. Fri, 09 May 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-05-09-live-stream-emacs-linux-life/ https://protesilaos.com/codelog/2025-05-09-live-stream-emacs-linux-life/ Raw link: https://www.youtube.com/watch?v=0N7vshEYOok

On Sunday, the 11th of May 2025, at 14:00 o’clock of time zone Europe/Athens, I will do a live stream where I will answer every question posted in the chat. The idea is to cover any of the topics I already write/talk about on my website, including Emacs, my recently published “Emacs Lisp Elements” free book, libre software, politics, philosophy, and everyday affairs.

I will answer every question from top to bottom to the best of my abilities and will not give any of those formulaic non-answers. No tricks; no gimmicks!

The plan is to do a minimum of two hours, but may extend it for at least one or two more hours depending on the participation in the chat.

The event will be recorded: no worries if you cannot make it live.

Talk to all of you soon!

]]>
Emacs: ef-themes version 1.10.0 Information about the latest version of my colourful-yet-legible themes for GNU Emacs. Tue, 29 Apr 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-04-29-emacs-ef-themes-1-10-0/ https://protesilaos.com/codelog/2025-04-29-emacs-ef-themes-1-10-0/ The ef-themes are a collection of light and dark themes for GNU Emacs that provide colourful (“pretty”) yet legible options for users who want something with a bit more flair than the modus-themes (also designed by me).

Below are the release notes.


Version 1.10.0 on 2025-04-29

This version introduces minor refinements to an already stable package.

The palette preview uses a tabulated interface

The commands ef-themes-preview-colors and ef-themes-preview-colors-current produce a preview of the given theme’s palette. In the past, we were using a bespoke buffer for this task, just how the built-in command list-colors-display does it.

Now we rely on the built-in tabulated-list-mode to get a cleaner tabulated view. Plus, users can sort by column.

Support for more faces or face groups

  • Added support for my tmr package. This will be especially noticeable in its tabulated view (used to show timers, with the command tmr-tabulated-view (alias tmr-list-timers)).

  • Added explicit support for my spacious-padding package. Specifically, this is for the faces spacious-padding-subtle-mode-line-active and spacious-padding-subtle-mode-line-inactive. Those can be configured as part of the user option spacious-padding-subtle-mode-line.

    (setq spacious-padding-subtle-mode-line
          '( :mode-line-active spacious-padding-subtle-mode-line-active
             :mode-line-inactive spacious-padding-subtle-mode-line-inactive))
    
  • Made the helpful headings use whatever the style of level 1 headings is, as defined by the user option ef-themes-heading. Thanks to John Haman for applying the relevant code we have for the modus-themes. The change is small (and comes from my modus-themes, anyway), meaning that John does not need to assign copyright to the Free Software Foundation.

  • Added support for the howm package.

  • Extended support for the auto-dim-other-buffers package to include its auto-dim-other-buffers-hide-face.

  • Made sure that all new transient faces conform with the design priorities of the themes. Concretely, this means that they do not support any colour-coding: all keys look the same, regardless of whether they mean “continue”, “exit”, or anything else. Colour-coding with a full spectrum of colours cannot be accessible (and I do not believe colour-coding alone even works because the colours have nothing else to be associated with, like how a red line in a diff buffer also goes together with the minus sign).

    Thanks to Kevin Fleming for including the transient-key-stack face that I had originally missed. This was done in pull request 54: https://github.com/protesilaos/ef-themes/pull/54. The change is small, meaning that Kevin does not need to assign copyright to the Free Software Foundation

  • Extended support for adoc-mode courtesy of Leilei332. This was done in pull request 52: https://github.com/protesilaos/ef-themes/pull/52.

    The change is within the ~15-line limit, meaning that its author does not need to assign copyright to the Free Software Foundation.

]]>
Aporetic fonts version 1.2.0 Release notes for the latest version of my custom 'Aporetic' fonts. Sun, 27 Apr 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-04-27-aporetic-fonts-version-1-2-0/ https://protesilaos.com/codelog/2025-04-27-aporetic-fonts-version-1-2-0/ Customised build of the Iosevka typeface, with a consistent rounded style and overrides for almost all individual glyphs in both upright (roman) and slanted (italic) variants. This is the successor to my now-discontinued “Iosevka Comfy” fonts.

Below are the release notes.


The major change for this release is that Aporetic Sans Mono and Aporetic Serif Mono are rendered in a strictly monospaced width. This means that characters such as the em dash () occupy the same space as the regular dash.

Before, Aporetic Sans Mono and Aporetic Serif Mono had some characters that were proportionately spaced. This would upset the expectations of terminal emulators and thus break the display, sometimes with characters overlapping when they should not.

Other changes are more subtle. They pertain to the style of individual characters, namely:

  • The Greek lower case lambda (λ) has a flat top instead of a straight one. The legs remain straight. This makes it consistent with the design of the Greek lower case delta (δ), among others.

  • The Greek lower case mee (μ) has a rounder right corner, which is in line with a whole range of characters.

  • The micro sign is the same design as the Greek lower case mee, even though these are technically two distinct code points.

  • The at sign (@) of Aporetic Sans and Aporetic Serif (i.e. the proportionately spaced fonts I provide) is a bit taller than it was before. This makes it look more related to its monospaced counterpart, which is also relatively tall.

I also added support for some more Greek characters, as well as the Latin eth (ð), thorn (þ), and thorn capital (Þ).

All other changes are done to retain the aesthetic of the fonts while dealing with the breaking changes introduced by the upstream Iosevka project.

]]>
Emacs: show-font version 0.3.0 Information about the latest version of my show-font package for GNU Emacs. Sat, 26 Apr 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-04-26-emacs-show-font-0-3-0/ https://protesilaos.com/codelog/2025-04-26-emacs-show-font-0-3-0/ This package lets you preview a font inside of Emacs. It does so in three ways:

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

Sources:

Below are the release notes.


Version 0.3.0 on 2025-04-26

This version adds some refinements to an already stable package.

The command show-font-list is an alias for show-font-tabulated

The show-font-list command was using a custom buffer that listed font families and their corresponding short preview. It did not have any other feature.

I made changes under the hood to rely on the built-in tabulated-list-mode which is a standard and gives us the option to sort by column. The show-font-list is thus an alias for the new command show-font-tabulated. Right now the sorting facility only applies to reversing the name-based order. In the future we may have more columns, such as if we describe a font as “Latin”, “Greek”, etc.

The tabulated list marks fonts that cannot be previewed

In the past, the font listing would include families that could not display the show-font-pangram or, indeed, any Latin character. Those would be rendered as empty boxes.

I have now introduced a simple heuristic to test that the given family supports Latin characters. If it does not, then (i) it is highlighted with a different colour, (ii) it shows “No preview” instead of the pangram, and (iii) it displays the information in the Emacs default font family. Some families do not play nice with this approach though, as they pass the test but still do not display any Latin characters. This happens with icon fonts.

The long-term goal is to support different scripts and show the appropriate text for each of them.

The show-font-sentences-sample adds more to the show-font-select-preview

The new user option show-font-sentences-sample is a list of strings that can be used to exhibit common patterns and letter combinations. The default value is carefully designed to show if a font family is stylistically consistent, such as with how it draws i, l, t, or h, n, m, and so on. Plus, it teaches you some obscure words like “scholarch”, “antipode”, and “heteroclite”: use them with your Greek friends—and if they do not know those words, then they must buy you a café frappé!

Miscellaneous

  • The face show-font-title-small is an obsolete alias for the more appropriately named show-font-title-in-listing.
  • The prompt used by the command show-font-select-preview now correctly uses its own history and default value.
  • The default value of the user option show-font-character-sample includes some more patterns to better test the adequacy of a font family. This sample is displayed in the buffer produced by the command show-font-select-preview.
]]>
Emacs: tmr version 1.1.0 Information about the latest version of my TMR package for GNU Emacs. Fri, 18 Apr 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-04-18-emacs-tmr-1-1-0/ https://protesilaos.com/codelog/2025-04-18-emacs-tmr-1-1-0/ TMR provides facilities for setting timers using a convenient notation. Lots of commands are available to operate on timers, while there also exists a tabulated view to display all timers in a nice grid.

Below are the release notes.


Version 1.1.0 on 2025-04-18

This version makes small refinements to an already stable package.

All of tmr-tabulated.el is part of tmr.el

The command tmr-tabulated-view, which produces a grid with timers+descriptions, used to be in a separate file. It now is part of the singular tmr.el to keep things simple. Users who were using (require 'tmr-tabulated) or similar will now get a warning. Simply load tmr instead.

Refined the behaviour of the tmr-tabulated-view command

When the command tmr-tabulated-view (alias tmr-list-timers) is called interactively, it uses the *tmr-tabulated-view* buffer just as it did before. Though it also evaluates the new user option tmr-list-timers-action-alist: it is a variable that controls where the buffer is displayed. The default value displays the buffer at the bottom of the Emacs frame and makes some other tweaks for usability.

Watch my video on the display-buffer-alist for further details on how to control the display of buffers: https://protesilaos.com/codelog/2024-02-08-emacs-window-rules-display-buffer-alist/.

The tmr-tabulated-view command is further revised to make it callable from a program. One scenario where we do this is to interrupt the termination of Emacs if there are running timers (more below).

TMR interrupts the termination of Emacs if it must

In the past, we did not have anything to prevent the termination of Emacs if timers were running: Emacs would simply shut down. Now we define the tmr-kill-emacs-query-function, which is added to the standard kill-emacs-query-functions: if there are running timers, it asks for confirmation before closing Emacs. To make it easier for users to decide how to proceed, it also pops up the list with all the timers (i.e. it uses tmr-tabulated-view from Lisp, as noted above).

The list view is easier to follow

The buffer produced by tmr-tabulated-view now uses more colours to make it easier to track the data it presents. These are all the faces it applies:

  • tmr-tabulated-start-time: The time when the timer was started.

  • tmr-tabulated-end-time: The time when the timer is set to end.

  • tmr-tabulated-remaining-time: The remaining time.

  • tmr-tabulated-acknowledgement: Whether the timer needs to be “acknowledged” after it ends (if it is marked as “acknowledged”, then it will not go away until the user confirms they have seen it).

  • tmr-tabulated-description: The text describing what the timer is about.

]]>
Emacs: modus-themes version 4.7.0 Information about the latest version of my highly accessible themes for GNU Emacs. Thu, 17 Apr 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-04-17-emacs-modus-themes-4-7-0/ https://protesilaos.com/codelog/2025-04-17-emacs-modus-themes-4-7-0/ I just published the latest stable release of the Modus themes. The change log entry is reproduced further below. For any questions, you are welcome to contact me. I will now work to apply these same changes to emacs.git, so please wait a little longer for the updates to trickle down to you.


4.7.0 on 2025-04-17

This release introduces many subtle stylistic tweaks to the “tinted”, “deuteranopia”, and “tritanopia” theme variants.

The modus-themes-list-colors command uses a tabulated list

This command and its modus-themes-list-colors-current variant help users see the colour values and semantic palette mappings defined by the given theme. In the past, their buffer was designed in the same spirit as that of the command list-faces-display, whereas now it is like the buffer of the command list-packages. Concretely, users may now sort by column. Do M-x describe-mode while in that buffer to learn about the available commands and their respective key bindings.

The “tinted” themes have slightly different colours

The overall feel of the modus-operandi-tinted and modus-vivendi-tinted themes is the same as before. Though in a side-by-side comparison between the old and new versions reveals lots of subtle differences. The general idea is to make the themes a bit more consistent by tweaking the foreground values to be more harmonious in combination with their background.

The “deuteranopia” themes are more consistently blue and yellow

These are the modus-operandi-deuteranopia and modus-vivendi-deuteranopia, which are optimised for users with red-green colour deficiency. In the past, these themes used blue and yellow hues wherever a concept of “success” versus “failure” had to be established. This approach is more generalised now, to include programming syntax highlighting and many other contexts. In short, the themes are more blue+yellow, while retaining their original feel.

The “tritanopia” themes are more consistently red and cyan

As above, the modus-operandi-tritanopia and modus-vivendi-tritanopia themes, which are optimised for users with blue-yellow colour deficiency, use a red+cyan palette in more places. Overall, they feel like they did before, only they are more consistent.

Miscellaneous

  • Extended support for the icomplete faces that are coming in Emacs version 31.

  • Added support for treemacs faces, courtesy of Rahul Juliato in pull request 121: https://github.com/protesilaos/modus-themes/pull/121. Rahul has assigned copyright to the Free Software Foundation.

  • Added support for the tldr package.

  • Extended support for adoc-mode. Thanks to Leilei332 for the contribution in pull request 137: https://github.com/protesilaos/modus-themes/pull/137. The change is within the ~15-line limit, meaning that the author does not need to assign copyright to the Free Software Foundation.

  • Added support for my spacious-padding package, specifically the faces it can use when the spacious-padding-subtle-mode-line user option is enabled.

  • Added support for the howm package.

  • Extended support to the new faces of the transient package. More specifically, all those faces use the same colour for key bindings because the idea of colour coding keys (e.g. light yellow means something different than dark blue) does not work in practice when considering accessibility. Such semantics should not be limited to differences in colour: they should also have distinct indicators, such as ASCII or Unicode characters.

  • Revised the avy package’s faces to only use one coloured background. The multiple coloured backgrounds have been a perennial problem for our accessibility requirements and have made the themes needlessly more complex just to support an edge case. With this simplified style, avy continues to work fine: it simply is less flamboyant. Other interfaces with avy-like model of interaction, such as optional extensions to the vertico and corfu packages, have these same changes, in the interest of consistency.

  • Update the meow sample configuration in the manual. This package is not directly supported at the theme level because (i) I do not use it and (ii) it is very hard for an outsider to it to trigger the display of all of its faces in the right context. Without seeing how all of them look together, I cannot come up with a reliable design. The manual offers a “good enough” approximation.

  • Broadened the support of the vterm faces to include the “bright” colours, while updating those that were already covered. Thanks to Edgar Vincent for informing me that some of the vterm faces were changed a while ago. This was done in issue 317 on the GitLab mirror: https://gitlab.com/protesilaos/modus-themes/-/issues/317.

  • Revised the org-column-title face to inherit the fixed-pitch face if the user option modus-themes-mixed-fonts is non-nil. This user option makes it possible to have a buffer with proportionately spaced fonts (such as by enabling variable-pitch-mode), while keeping spacing-sensitive elements, like tables and code blocks, in a monospaced font.

    Thanks to pedro-nonfree for bringing this matter to my attention in issue 129: https://github.com/protesilaos/modus-themes/issues/129.

  • Simplified the helper function modus-themes--retrieve-palette-value to make it more efficiently. Thanks to Basil L. Contovounesios for the contribution in merge request 60 on the GitLab mirror: https://gitlab.com/protesilaos/modus-themes/-/merge_requests/60.

  • Reworded the minibuffer prompt of the modus-themes-list-colors command.

  • Made Ivy and IDO subdirectories and “virtual” buffers easier to tell apart from matching text highlights.

  • Included coverage for the auto-dim-other-buffers-hide-face of the package auto-dim-other-buffers

  • Covered the built-in abbrev-table-name face.

]]>
Emacs: Denote version 4.0.0 Information about the latest version of my Denote package for GNU Emacs. Tue, 15 Apr 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-04-15-emacs-denote-4-0-0/ https://protesilaos.com/codelog/2025-04-15-emacs-denote-4-0-0/ Denote aims to be a simple-to-use, focused-in-scope, and effective note-taking and file-naming tool for Emacs.

Denote is based on the idea that files should follow a predictable and descriptive file-naming scheme. The file name must offer a clear indication of what the contents are about, without reference to any other metadata. Denote basically streamlines the creation of such files or file names while providing facilities to link between them (where those files are editable).

Denote’s file-naming scheme is not limited to “notes”. It can be used for all types of file, including those that are not editable in Emacs, such as videos. Naming files in a constistent way makes their filtering and retrieval considerably easier. Denote provides relevant facilities to rename files, regardless of file type.

Below are the release notes.


Version 4.0.0 on 2025-04-15

This is a massive release. There is one breaking change, which should be easy to adapt to: this pertains to the reorganisation of the project to separate the “core” of Denote from its “extensions”. The core is the denote package. Each extension now has its own package (details below).

Other than that, this version includes lots of new features for searching and linking as well as quality-of-life refinements. We have generalised the infrastructure for performing queries in the denote-directory and made the buffers with the search results more useful.

Take your time to read through this publication. I am writing it for you. Also remember that the most up-to-date resource for anything related to Denote is its manual. You are always welcome to contact me: https://protesilaos.com/contact. Or join the development on the Git repository.

As usual, special thanks to Jean-Philippe Gagné Guay for making high quality contributions to Denote since the beginning of the project ~3 years ago. Those will not always be headline features, but are important improvements to the underlying code base.

I mention contributions from Jean-Philippe and others in its context. Though I do not cover implementation details, otherwise this document will be the size of a book. This does not mean that they are no important though. Please consult the Git commit log for all the technicalities.

All the “extras” are in separate packages, including the Org dynamic blocks

In previous versions of Denote, we included some optional extensions as part of the denote package. These included the files denote-org-extras.el (Org dynamic blocks, among others), denote-journal-extras.el (streamlined for journaling), denote-silo-extras.el (working with multiple Denote silos).

The files denote-md-extras.el (Markdown extras) and denote-sequence.el (sequence notes, including Luhmann-style alphanumeric sequences) were also part of the project during the last development cycle, though they never made it into a tagged release.

All these are now available as standalone packages on the official GNU ELPA archive:

  • denote-org: In the Emacs configuration file, replace all instances of denote-org-extras with denote-org.

  • denote-journal: Replace denote-journal-extras with denote-journal.

  • denote-silo: Replace denote-silo-extras with denote-silo.

  • denote-markdown : Replace denote-md-extras with denote-markdown.

  • denote-sequence: No changes to any of the defined symbols. Simply get the new package.

I will document each of these packages further below. The plan, going forward, is to maintain all the packages and coordinate their new versions.

More things in “core”

While the extras are moved out to their own code repositories, all other features are merged into denote.el. Those include everything that was in denote-sort.el and denote-rename-buffer.el.

  • The “sort” mechanism is mostly for package developers. We use it extensively in our Org dynamic blocks, which are now part of the denote-org package.

  • The denote-dired command (alias denote-sort-dired) is the only user-facing “sort” command we have always provided. It produces a fully fledged Dired buffer showing the results of the given search for file names. The matching files are sorted according to the user’s expressed preference. The details are described in the manual.

  • The denote-rename-buffer-mode and all of its user options are unchanged. This mode automatically renames the buffer of a given Denote file so that it is easier to read it. Again, the manual covers the technicalities.

Users do not need to make changes, unless they are explicitly loading denote-sort-dired and denote-rename-buffer. In that case, they may just remove those calls: only denote needs to be loaded.

The denote-query-mode

Many of the features I will describe below produce search results via the built-in Xref mechanism. Xref performs a search with a Grep or Grep-like program, subject to the user option xref-search-program. The buffer those search results are displayed in runs the denote-query-mode. It supersedes denote-backlinks-mode.

The denote-query-mode supports the following:

  • Results are shown in the context, with the exact match in highlight.
  • Matches are grouped by file. Each file is a “heading”.
  • Headings can be folded with TAB, just how it is done in Org buffers.
  • The results can be used for further queries. Type C-h m (describe-mode) to learn about all the relevant commands.

We have had support for Xref since the original version of Denote. It now is more generalised to cover backlinks, query links, and denote-grep (more below).

Use query links for file contents or file names

Denote has always provided the option to link directly to a file with a given name by referencing its identifier. This can be done with the command denote-link, among a few others like it (always consult the manual of Denote).

In addition to these “direct links”, we also support “query links”. Those do not point to a file but instead trigger a search. The results are placed in a buffer that uses the appropriate major mode.

There are two types of query links:

  • Query file contents: Use the command denote-query-contents-link to insert a query link at point for “file contents”. It perform a search inside files in the denote-directory and put the results in a denote-query-mode buffer.

  • Query file names: Use the denote-query-filenames-link to insert a query link for “file names”. It performs the query against file names (not contents!) and puts the results in a dired buffer.

The display of the buffer with the query link results is controlled by the user option denote-query-links-display-buffer-action.

Query links are styled a little bit differently than direct links. Compare the denote-faces-link with denote-faces-query-link. Both should look okay with most themes.

Denote query links are supported as part of the denote: hyperlink type. They are available in all file types we define (per the user option denote-file-type) and should, in principle, work in any custom file type (advanced users can check the variable denote-file-types).

Backlinks now always show their context

In the past, the command denote-backlinks would produce a bespoke buffer showing a list of file names that included links to the current file (any file with the Denote file-naming scheme can have backlinks, by the way, including PDFs, videos, etc.). This buffer did not provide any additional functionality. We used to support the option to show results in their context via denote-backlinks-show-context. Those would be rendered in a standard Xref buffer.

The contextual results are now the default and sole option. This is because we have expanded the functionality of those buffers to use the denote-query-mode, as explained above. Plus, it makes our code base simpler.

Users will notice how backlikns look just like a query link for file contents. This is because backlinks are the original query links since day one of Denote.

Direct links to a file with matching contents

The command denote-link-to-file-with-contents allows users to produce a direct link to a file whose contents (not file name!) includes the given query.

Similarly, the command denote-link-to-all-files-with-contents generates a typographic list (bullet list) to all files whose contents match the given query.

The manual covers all linking commands in depth.

The essence of denote-search is part of denote

The denote-search package by Lucas Quintana uses the infrastructure of Denote to perform searches in file contents. We now provide its feature set as part of core denote.

We decided to do this since query links already introduced all of the requisite generalisations to denote-query-mode.

Users can rely on the commands denote-grep, denote-grep-marked-dired-files, and denote-grep-files-referenced-in-region.

The placement of these buffers is subject to the user option denote-grep-display-buffer-action.

This functionality was introduced in two pull requests by Lucas Quintana, 571 and 573, with further changes by me:

Lucas has assigned copyright to the Free Software Foundation.

I think this was a much-needed addition to the core of Denote. It complements denote-dired and query links.

Formatting of links with denote-link-description-format

The old user option denote-link-description-function is deprecated and superseded by the new denote-link-description-format. The new user option still accepts a custom function as its value, so the old behaviour should be retained.

What the new denote-link-description-format supports is an easier way to customise the description of a link by using format specifiers for common options. For example, users who only want to see the title of the linked file can do this:

(setq denote-link-description-format "%t")

The documentation of this user option covers all the format specifiers and further details.

Miscellaneous changes for all users

  • The command denote-add-front-matter is superseded by denote-rename-file and related. Those renaming commands will add missing front matter or rewrite the modified lines of existing front matter. This is due to refinements made by Jean-Philippe Gagné Guay to the file renaming mechanism. We discussed this deprecation in issue 498: https://github.com/protesilaos/denote/issues/498. Also thanks to Samuel Flint for reporting an earlier problem with file name signatures: https://github.com/protesilaos/denote/issues/492.

  • The user option denote-open-link-function specifies the function used by Denote to open the file of a direct link.

  • The user option denote-org-store-link-to-heading can now be set to form generic context links without a PROPERTIES drawer and corresponding CUSTOM_ID. Set the value of this variable to 'context. Read its documentation for further details.

  • Also about denote-org-store-link-to-heading, we have changed its default value to nil, which is what we were doing for most of Denote’s history. This means that, by default, org-store-link and anything building on top of it will create a link only to the current Denote file, like denote:IDENTIFIER, but not to the current heading within that file. To create links to the file+heading, set the value of this variable to 'id.

  • The command denote-dired-link-marked-notes is an alias for denote-link-dired-marked-notes.

  • The user option denote-sort-dired-extra-prompts control what denote-dired (alias denote-sort-dired) prompts for. It accepts either a nil value or a list of symbols among sort-by-component, reverse-sort, and exclude-regexp. The order those symbols appear in the list is significant, with the leftmost coming first.

  • There is a new denote-sort-identifier-comparison-function variable which determines how identifier-based sorting should be done by default. It complements the existing denote-sort-title-comparison-function, denote-sort-keywords-comparison-function, denote-sort-signature-comparison-function. Thanks to Maikol Solís for the contribution in pull request 517: https://github.com/protesilaos/denote/pull/517. The change is small, meaning that Maikol does not need to assign copyright to the Free Software Foundation (though I believe the paperwork is done, anyway).

  • Lots of refinements to the doc strings of individual variables and/or functions as well as the manual.

  • Lots of other contributions to discussions and questions on the Git repository. Granted, these are not “changes” per se but are part of the development effort nonetheless.

  • Made denote-get-path-by-id use denote-get-file-extension-sans-encryption instead of denote-get-file-extension. This fixes a bug where the extension is duplicated if it has an encryption component. Thanks to eum3l for the patch in pull request 562: https://github.com/protesilaos/denote/pull/562. The change is small, meaning that the author does not need to assign copyright to the Free Software Foundation.

  • Same as above for denote--rename-file, which was done in pull request 557: https://github.com/protesilaos/denote/pull/557.

For developers or advanced users

The following have been added or modified.

  • NEW Function denote-file-has-denoted-filename-p: Return non-nil if FILE respects the file-naming scheme of Denote. This tests the rules of Denote’s file-naming scheme. Sluggification is ignored. It is done by removing all file name components and validating what remains. Thanks to Jean-Philippe Gagné Guay for the pull request 515: https://github.com/protesilaos/denote/pull/515.

  • NEW Functions denote-infer-keywords-from-files: Return list of keywords in denote-directory-files. With optional FILES-MATCHING-REGEXP, only extract keywords from the matching files. Otherwise, do it for all files. Keep any duplicates. Users who do not want duplicates should refer to the functions denote-keywords.

  • MODIFIED Function denote-keywords: Returns an appropriate list of keyword candidates, while accounting for the value of the user option denote-infer-keywords. It now also accepts the optional FILES-MATCHING-REGEXP parameter.

  • MODIFIED Function denote-directory-files: Returns a list of absolute file paths in variable denote-directory. It now accepts the optional EXCLUDE-REGEXP parameter.

  • MODIFIED Function denote-format-file-name: Formats a file name. The way it treats its ID parameter has changed. Please read its doc string. Thanks to Jean-Philippe Gagné Guay for the pull request 496: https://github.com/protesilaos/denote/pull/496.

  • ALIAS Function denote-retrieve-filename-keywords-as-list: This is a name that is easier to discover than denote-extract-keywords-from-path, because of the many other functions with the denote-retrieve-* prefix.

  • MODIFIED Function denote-retrieve-filename-identifier: Extracts the identifier from FILE name, if present, else returns nil. To create a new one from a date, refer to the denote-get-identifier function. Thanks to Jean-Philippe Gagné Guay for the pull request 476: https://github.com/protesilaos/denote/pull/476.

  • MODIFIED Function denote-get-identifier: Converts DATE into a Denote identifier using denote-id-format. If DATE is nil, it returns an empty string as the identifier. Also by Jean-Philippe in pull request 476 mentioned right above.

  • MODIFIED Function denote-date-prompt: Prompts for a date, expecting YYYY-MM-DD or that plus HH:MM (or even HH:MM:SS). Can also use Org’s more advanced date selection utility if the user option denote-date-prompt-use-org-read-date is non-nil. It now has the optional parameters INITIAL-DATE and PROMPT-TEXT. Thanks to Jean-Philippe Gagné Guay for the pull request 576: https://github.com/protesilaos/denote/pull/576.

  • NEW Function denote-retrieve-groups-xref-query: Accesses the location of xrefs for QUERY and group them per file. Limit the search to text files.

  • NEW Function denote-retrieve-files-xref-query: Returns sorted, deduplicated file names with matches for QUERY in their contents. Limits the search to text files.

  • NEW Function denote-retrieve-xref-alist: Returns xref alist of files with the location of matches for QUERY. With optional FILES-MATCHING-REGEXP, it limits the list of files accordingly (per denote-directory-files). At all times, it limits the search to text files.

  • NEW Function denote-prepend-front-matter: Prepend front matter to FILE. The TITLE, KEYWORDS, DATE, ID, SIGNATURE, and FILE-TYPE are passed from the renaming command and are used to construct a new front matter block if appropriate.

  • MODIFIED Function denote-rewrite-front-matter: Rewrites front matter of note after denote-rename-file (or related). The FILE, TITLE, KEYWORDS, SIGNATURE, DATE, IDENTIFIER, and FILE-TYPE arguments are given by the renaming command and are used to construct new front matter values if appropriate. If denote-rename-confirmations contains rewrite-front-matter, prompt to confirm the rewriting of the front matter. Otherwise produce a y-or-n-p prompt to that effect. Thanks to Jean-Philippe Gagné Guay for the pull request 558: https://github.com/protesilaos/denote/pull/558.

Denote “extensions” that are not in the denote package anymore

denote-journal integrates nicely with M-x calendar

The calendar can now highlight days that have journal entry. It may also be used as a date picker to view or write a journal entry for that day.

Other than that, the package is providing the same functionality as the discontinued denote-journal-extras.el.

denote-org is almost the same as the discontinued denote-org-extras.el

The only addition to dynamic blocks the optional :not-regexp parameter. This is a regular expression that can further filter the results of a search, such that the matching items are removed from the output.

The official manual of denote-org covers the technicalities.

Also thanks to Elias Storms for fixing a small issue with the “missing links” Org dynamic block, in pull request 486: https://github.com/protesilaos/denote/pull/486

denote-silo is the same as the discontinued denote-silo-extras.el

I have only made small tweaks to it, but nothing that changes the user experience.

denote-markdown for some Markdown-specific extras

This package provides some convenience functions to better integrate Markdown with Denote. This is mostly about converting links from one type to another so that they can work in different applications (because Markdown does not have a standardised way to define custom link types). It also defines an “Obsidian” file type which does not have any front matter but only uses a level 1 heading for the title of the note.

The code of denote-markdown used to be bundled up with the denote package before version 4.0.0 of the latter and was available in the file denote-md-extras.el. Users of the old code will need to adapt their setup to use the denote-markdown package. This can be done by replacing all instances of denote-md-extras with denote-markdown across their configuration.

Write sequence notes (or “folgezettel”) with denote-sequence

Users who want their notes to have an inherent structure can use denote-sequence. The idea is to have thoughts that naturally form sequences and are named accordingly. The sequence scheme is either numeric or alphanumeric. The manual of the package explains all the details.

I had a lot of fun developing this comprehensive package during the winter holidays.

Thanks to Claudio Migliorelli, Kierin Bell, Mirko Hernandez for helping me fix some issues during development:

The consult-denote also gets a small update

This has always been a standalone package. I made the function consult-denote-file-prompt read the special-purpose variable denote-file-prompt-use-files-matching-regexp. This is related to commit e0f1d47 in denote.git, about issue 536 as reported by Alan Schmitt: https://github.com/protesilaos/denote/issues/536. The variable denote-file-prompt-use-files-matching-regexp is meant to be let bound and is for advanced users or developers.

Feature freeze at least until the end of April 2025

I will not develop new features or accept pull request for a couple of weeks. The idea is to focus on fixing any bug reports. We can then publish point releases quickly.

New features can be included after we are confident that the packages we have are okay.

Git commits

This is just an overview of the Git commits, though remember that there is more that goes into a project, such as the reporting of inconsistencies, discussion of new ideas, et cetera. Thanks to everybody involved! Plus, some commits are large while others are tiny.

~/Git/Projects/denote $ git shortlog 3.1.0..4.0.0  --summary --numbered
   470	Protesilaos Stavrou
    90	Jean-Philippe Gagné Guay
     6	Kierin Bell
     4	Alan Schmitt
     3	eum3l
     2	Claudio Migliorelli
     2	Lucas Quintana
     2	grtcdr
     1	Elias Storms
     1	Laurent Gatto
     1	Maikol Solís
     1	Octavian
     1	TomoeMami

The following are not accurate because they only reflect the changes after the reorganisation I made. But we have to start from somewhere.

~/Git/Projects/denote-journal $ git shortlog  --summary --numbered
    54	Protesilaos Stavrou
     2	Honza Pokorny
     1	Vineet C. Kulkarni

~/Git/Projects/denote-sequence $ git shortlog  --summary --numbered
    22	Protesilaos Stavrou

~/Git/Projects/denote-silo $ git shortlog  --summary --numbered
    17	Protesilaos Stavrou

~/Git/Projects/denote-org $ git shortlog  --summary --numbered
    15	Protesilaos Stavrou

~/Git/Projects/denote-markdown $ git shortlog  --summary --numbered
    11	Protesilaos Stavrou
]]>
Emacs: My new ‘Emacs Lisp Elements’ book I wrote a book that provides a big picture view of the Emacs Lisp programming language. Sat, 12 Apr 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-04-12-emacs-lisp-elements-book/ https://protesilaos.com/codelog/2025-04-12-emacs-lisp-elements-book/ I just published the book “Emacs Lisp Elements”. It is available for free and in freedom under the same terms as all documentation that ships with GNU Emacs:

I provide a big picture view of the Emacs Lisp programming language by combining prose with code. The goal is to give readers an idea of how Elisp works by showing some of the main concepts or patterns discernible in everyday code.

Some chapters are beginner-friendly, while others dive into deeper waters. Though I think everything is still approachable, as I try to explain basic concepts and take things one step at a time.

The book is not meant to be a replacement for the built-in Emacs Lisp Reference Manual. It simply gives you enough information to reason about Elisp. Once you start extending Emacs, the rest will follow naturally.

I hope you enjoy it and continue to have fun with Emacs.

]]>
Emacs: dired-preview version 0.5.0 Information about the latest version of my dired-preview package for GNU Emacs. Wed, 09 Apr 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-04-09-emacs-dired-preview-0-5-0/ https://protesilaos.com/codelog/2025-04-09-emacs-dired-preview-0-5-0/ This is a simple package to automatically preview in a window the file at point in Dired buffers. Preview windows are closed when they are no longer relevant, while preview buffers are killed if they have not been used for other purposes beside previewing. The package provides several customisation options to control its behaviour.

Below are the release notes


Version 0.5.0 on 2025-04-09

This version contains a few bug fixes and minor refinements that should improve the behaviour of the package.

Revised how preview windows are deleted

In the past, dired-preview-mode could delete windows that held another buffer, thus undoing the window layout that was present before a preview buffer was displayed. Now dired-preview-mode makes sure to only delete windows that have not had another buffer shown in them, i.e. windows that were created just for preview purposes.

Directories no longer get misunderstood as “large files”

We tweaked how we test the type of the buffer-to-be-preview such that directories are not mistaken for “large files”. This was an issue for Mac computers that Sean Devlin brought to my attention in issue 27: https://github.com/protesilaos/dired-preview/issues/27.

The dired-preview-delay has a 0.1 second minimum to avoid instability

A value of 0 could lead to a noticeably degraded experience while navigating the Dired buffer. Thanks to Yiyu Zhou for reporting the matter in issue 2 on the GitLab mirror: https://gitlab.com/protesilaos/dired-preview/-/issues/2.

Files without an extension can also be ignored

The user option dired-preview-ignored-extensions-regexp will now also match files without an extension, such as the .DS_Store on Mac computers.

Thanks to Sean Devlin for the contribution in pull request 26: https://github.com/protesilaos/dired-preview/pull/26. The change is within the ~15-line limit, meaning that Sean does not need to assign copyright to the Free Software Foundation.

The preview buffer is the “other window” for scrolling purposes

The commands which scroll the other window, such as scroll-other-window now operate on the preview buffer when that is displayed. Thanks to Karthik Chikmagalur for proposing this in issue 24: https://github.com/protesilaos/dired-preview/issues/24.

This is in addition to the commands we already provided for scrolling the preview window, namely, dired-preview-page-up and dired-preview-page-down. Do M-x describe-keymap and then search for dired-preview-mode-map: it is in effect when dired-preview-mode is enabled.

]]>
Emacs: stylistic refinements to the “tinted” Modus themes Status update on the development process of the 'modus-themes' package. Sun, 06 Apr 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-04-06-emacs-modus-tinted-refinements/ https://protesilaos.com/codelog/2025-04-06-emacs-modus-tinted-refinements/ As part of the current development target of the modus-themes package, I am introducing small changes to the modus-operandi-tinted and modus-vivendi-tinted themes. These concern fine details, some of which most users will probably not even notice. Though the cumulative effect of these changes is obvious once we compare the themes to their main counterparts, namely, modus-operandi and modus-vivendi. I am doing this to improve the consistency of the “tinted” themes. I think existing users will appreciate the attention to detail.

Below are some screen shots with the out-of-the-box design of the themes (remember that they are highly customisable). I also include pictures with spacious-padding-mode enabled (from my spacious-padding package). Notice that in this case the mode lines are just an overline, which is done by customising the user option spacious-padding-subtle-mode-line.

I plan to install those changes to emacs.git and make them available via GNU ELPA as part of modus-themes version 4.7.0, which I hope to publish some time this month or in May.

Modus Operandi VS Modus Operandi Tinted

Sample of modus-operandi theme

Sample of modus-operandi-tinted theme

Sample of modus-operandi theme

Sample of modus-operandi-tinted theme

Modus Vivendi VS Modus Vivendi Tinted

Sample of modus-vivendi theme

Sample of modus-vivendi-tinted theme

Sample of modus-vivendi theme

Sample of modus-vivendi-tinted theme

About the Modus themes

Highly accessible themes, conforming with the highest standard for colour contrast between background and foreground values (WCAG AAA). They also are optimised for users with red-green or blue-yellow colour deficiency.

The themes are very customisable and provide support for a wide range of packages. Their manual is detailed so that new users can get started, while it also provides custom code for all sorts of more advanced customisations.

Since August 2020, the original Modus themes (modus-operandi, modus-vivendi) are built into Emacs version 28 or higher. Emacs 28 ships with modus-themes version 1.6.0. Emacs 29 includes version 3.0.0. Emacs 30 provides version 4.4.0. Version 4 is a major refactoring of how the themes are implemented and customized. Such major versions are not backward-compatible due to the limited resources at my disposal to support multiple versions of Emacs and of the themes across the years.

]]>
Emacs: ‘denote-journal’ integration with ‘M-x calendar’ The new version of my 'denote-journal' package will integrate with the Emacs 'calendar'. Mon, 31 Mar 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-03-31-emacs-denote-journal-calendar/ https://protesilaos.com/codelog/2025-03-31-emacs-denote-journal-calendar/ I just made it possible for users of my denote-journal package to interact with the M-x calendar as part of their journaling workflow.

Highlight dates with a Denote journal entry

The new minor mode denote-journal-calendar-mode highlights dates in the M-x calendar which have a corresponding Denote journal entry. The applied face is called denote-journal-calendar: I made it draw only a box around the date, thus respecting existing colouration. Here is a demonstration, which also includes red-coloured dates for holidays:

Generic Emacs calendar

The denote-journal-calendar-mode is buffer-local and meant to be activated inside the M-x calendar buffer, thus:

(add-hook 'calendar-mode-hook #'denote-journal-calendar-mode)

View the journal entry for the current date

While navigating the calendar buffer, use the command denote-journal-calendar-find-file to visit the Denote journal entry corresponding to the date at point. If there are multiple journal entries, the command will prompt you to select one among them.

Create or view journal entry for the current date

The command denote-journal-calendar-new-or-existing creates a new journal entry for the date at point or visits any existing one. This is like denote-journal-new-or-existing-entry but for the given M-x calendar date.

Part of development

Remember that I have split denote into several packages, one of which is denote-journal. I plan to coordinate the release of new versions across all Denote-related packages, so expect the aforementioned to be available at around the same time as denote version 4.0.0 (which is going to be massive, by the way).

About Denote journal

The denote-journal package makes it easier to use Denote for journaling. While it is possible to use the generic denote command (and related) to maintain a journal, this package defines extra functionality to streamline the journaling workflow.

The code of denote-journal used to be bundled up with the denote package before version 4.0.0 of the latter and was available in the file denote-journal-extras.el. Users of the old code will need to adapt their setup to use the denote-journal package. This can be done by replacing all instances of denote-journal-extras with denote-journal across their configuration.

About Denote

Denote is a simple note-taking tool for Emacs. It is based on the idea that notes should follow a predictable and descriptive file-naming scheme. The file name must offer a clear indication of what the note is about, without reference to any other metadata. Denote basically streamlines the creation of such files while providing facilities to link between them.

Denote’s file-naming scheme is not limited to “notes”. It can be used for all types of file, including those that are not editable in Emacs, such as videos. Naming files in a consistent way makes their filtering and retrieval considerably easier. Denote provides relevant facilities to rename files, regardless of file type.

]]>
Emacs: Denote ‘query links’ (links that trigger a search) In this video demonstration, I show the new in-development functionality of Denote for 'query links'. Fri, 28 Mar 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-03-28-emacs-denote-query-links/ https://protesilaos.com/codelog/2025-03-28-emacs-denote-query-links/ Raw link: https://www.youtube.com/watch?v=zqzAFj50MhE

In this ~16-minute video, I demonstrate the new, in-development “query links” functionality of Denote. These are links that trigger a search when you interact with them. There are two types of query links: (i) search in file contents, or (ii) search in file names. When there are matches for a given query, those are displayed in a separate buffer, which uses the appropriate major mode. Query links complement the “direct links” Denote has always supported. Internally, they use the same infrastructure that Denote backlinks rely on (and we have had backlink support since the beginning).

Denote sources

Denote is a simple note-taking tool for Emacs. It is based on the idea that notes should follow a predictable and descriptive file-naming scheme. The file name must offer a clear indication of what the note is about, without reference to any other metadata. Denote basically streamlines the creation of such files while providing facilities to link between them.

Denote’s file-naming scheme is not limited to “notes”. It can be used for all types of file, including those that are not editable in Emacs, such as videos. Naming files in a consistent way makes their filtering and retrieval considerably easier. Denote provides relevant facilities to rename files, regardless of file type.

]]>
Emacs: first look at query links for Denote version 4.0.0 Report of the in-progress implementation of Denote 'query links'. Mon, 24 Mar 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-03-24-emacs-denote-query-links/ https://protesilaos.com/codelog/2025-03-24-emacs-denote-query-links/ The next version of Denote is shaping up to be a huge one. One of the newest features I am working on is the support for “query links”. Those use the same denote: link type infrastructure but exhibit a different behaviour than the direct links we have always had. Instead of pointing to a file via its unique identifier, they initiate a search through the contents of all files in the denote-directory. This search uses the built-in Xref mechanism and is the same as what we have already been doing with backlinks (basically, a grep).

In short:

  • Direct links: Those point to a file via its unique identifier. For example, denote:20250324T074132 resolves to a file path. Clicking on the link opens the corresponding file. Org export will also take care to turn this into a file path.
  • Query links: Those do not point to any file per se. They are a string of one or more words or regular expression which is matched against the contents of files. For example, denote:this is a test produces a buffer listing all matches for the given query. Clicking on the matching line in that buffer opens the file at that point (just how our backlinks work when they show context—I am generalising this mechanism).

Direct links can point to any file, including PDFs, videos, and pictures (assuming it is renamed to use the Denote file-naming scheme). Whereas query links are limited to text files.

Development discussion and screenshots

This is a work-in-progress that lives on its own branch as of this writing. I will not elaborate at length right now as the implementation details may change. I have, nonetheless, created an issue on the GitHub repository where interested parties can provide their feedback. It also includes some screenshots I took: https://github.com/protesilaos/denote/issues/561. The code includes other changes which pertain to how we handle backlinks and constitutes a simplification of the code base.

The idea is to add the functionality to the main branch in the coming days or weeks. Then I will do a video about it and/or explain more.

That granted, do not forget that the official manual is the most up-to-date reference and the single source of truth.

Denote sources

Denote is a simple note-taking tool for Emacs. It is based on the idea that notes should follow a predictable and descriptive file-naming scheme. The file name must offer a clear indication of what the note is about, without reference to any other metadata. Denote basically streamlines the creation of such files while providing facilities to link between them.

Denote’s file-naming scheme is not limited to “notes”. It can be used for all types of file, including those that are not editable in Emacs, such as videos. Naming files in a consistent way makes their filtering and retrieval considerably easier. Denote provides relevant facilities to rename files, regardless of file type.

[ Further down on this list I include more of my Denote-related packages. ]

]]>
Emacs: how I build from emacs.git on Debian stable Step-by-step guide on how I build Emacs from source on Debian stable. Sat, 22 Mar 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-03-22-emacs-build-source-debian/ https://protesilaos.com/codelog/2025-03-22-emacs-build-source-debian/ I have been following the master branch of the emacs.git repository for many years now. It helps me test new features and make necessary adjustments to all the packages I develop/maintain. Below I explain how I make this happen on my computer, which is running Debian stable (Debian 12 “Bookworm” as of this writing). If you are a regular user, there is no reason to build from source: just use the latest stable release and you should be fine.

Configure the apt development sources

To build Emacs from source on Debian, you first need to have the deb-src package archive enabled. In your /etc/apt/sources.list file you must have something like this:

deb http://deb.debian.org/debian/ bookworm main
deb-src http://deb.debian.org/debian/ bookworm main

After modifying the sources, run the following on the command line to fetch the index with new package names+versions:

sudo apt update

Get the Emacs build dependencies

Now that you have enabled the deb-src archive, you can install the build dependencies of the Debian emacs package with the following on the command line:

sudo apt build-dep emacs

With this done, you are ready to build Emacs from source.

Get the Emacs source code

You need the git program to get the source code from the emacs.git website. So install it with this command:

sudo apt install git

Now make a copy of the Emacs source code, using this on the command line:

git clone https://git.savannah.gnu.org/git/emacs.git ~/path/to/my/copy-of-emacs.git

Replace ~/path/to/my/copy-of-emacs.git with the actual destination of your preference. I have a ~/Builds directory where I store all the projects I build from source. I thus do:

git clone https://git.savannah.gnu.org/git/emacs.git ~/Builds/emacs.git

If the cloning process is too slow on your end, perform a shallow clone instead. For example:

git clone --depth 1 https://git.savannah.gnu.org/git/emacs.git ~/Builds/emacs.git

And if the Savannah website is not responsive, then clone from the GitHub mirror (with the --depth 1 if necessary):

git clone https://github.com/emacs-mirror/emacs.git ~/Builds/emacs.git

Switch to the Emacs directory

Assuming you have the copy of emacs.git stored at ~/Builds/emacs.git, you switch to that directory with the following:

cd ~/Builds/emacs.git

Keep in mind that unless you explicitly switch to another branch, you are on master, i.e. the latest development target.

NOTE: All subsequent commands are ran from your equivalent of ~/Builds/emacs.git.

Run the autogen.sh the first time

This script will generate the configuration scaffold. You only really need to do this once (and I always forget about it for this very reason). Simply do this on the command line:

./autogen.sh

It checks that you have all you need to get started and prints output like this:

Checking whether you have the necessary tools...
(Read INSTALL.REPO for more details on building Emacs)
Checking for autoconf (need at least version 2.65) ... ok
Your system has the required tools.
Building aclocal.m4 ...
Running 'autoreconf -fi -I m4' ...
Building 'aclocal.m4' in exec ...
Running 'autoreconf -fi' in exec ...
Configuring local git repository...
'.git/config' -> '.git/config.~1~'
git config transfer.fsckObjects 'true'
git config diff.cpp.xfuncname '!^[ 	]*[A-Za-z_][A-Za-z_0-9]*:[[:space:]]*($|/[/*])
^((::[[:space:]]*)?[A-Za-z_][A-Za-z_0-9]*[[:space:]]*\(.*)$
^((#define[[:space:]]|DEFUN).*)$'
git config diff.elisp.xfuncname '^\([^[:space:]]*def[^[:space:]]+[[:space:]]+([^()[:space:]]+)'
git config diff.m4.xfuncname '^((m4_)?define|A._DEFUN(_ONCE)?)\([^),]*'
git config diff.make.xfuncname '^([$.[:alnum:]_].*:|[[:alnum:]_]+[[:space:]]*([*:+]?[:?]?|!?)=|define .*)'
git config diff.shell.xfuncname '^([[:space:]]*[[:alpha:]_][[:alnum:]_]*[[:space:]]*\(\)|[[:alpha:]_][[:alnum:]_]*=)'
git config diff.texinfo.xfuncname '^@node[[:space:]]+([^,[:space:]][^,]+)'
Installing git hooks...
'build-aux/git-hooks/commit-msg' -> '.git/hooks/commit-msg'
'build-aux/git-hooks/pre-commit' -> '.git/hooks/pre-commit'
'build-aux/git-hooks/prepare-commit-msg' -> '.git/hooks/prepare-commit-msg'
'build-aux/git-hooks/post-commit' -> '.git/hooks/post-commit'
'build-aux/git-hooks/pre-push' -> '.git/hooks/pre-push'
'build-aux/git-hooks/commit-msg-files.awk' -> '.git/hooks/commit-msg-files.awk'
'.git/hooks/applypatch-msg.sample' -> '.git/hooks/applypatch-msg'
'.git/hooks/pre-applypatch.sample' -> '.git/hooks/pre-applypatch'
You can now run './configure'.

Do not be intimidated by it. Focus on the final line instead, which directs you to the configure directive.

Explore the build flags

How exactly you build Emacs depends on your preferences and system-specific requirements. At the end of this post, I copy my current configuration, though I advise against copying it without understanding what it does.

If you have no specific preferences, just use the defaults by running this on the command line:

./configure

It will set up the build environment for you. If, however, you wish to explore your options and customise the emacs program you will get, then issue the following command and carefully read its output:

./configure --help

The minimum I recommend is to specify where the build artefacts are stored. I use this, which has not caused me any issues over the years:

./configure --prefix=/usr/local

Configure the build environment with your preferred flags

Once you have understood the available options, go ahead and run configure. For example:

./configure --prefix=/usr/local --with-x-toolkit=gtk3

Whenever you need to rebuild Emacs with some new flags, run the configure command again, passing it the relevant flags. If you wish to keep the same options for a new build, then simply do not run configure again.

Make the program

Once configure finishes its work, it is time to run the make program. For new builds, this is as simple as:

make

Sometimes you have old build artefacts that conflict with changes upstream. When that happens, the build process will fail. You may then need to use:

make bootstrap

In general, make is enough. It will be slow the first time, but will be faster on subsequent runs as it reuses what is already there. A make bootstrap will always be slow though, as it generates everything anew.

Install the program that was made

After make is done, you are ready to install Emacs:

sudo make install

You will not need escalated privileges (i.e. sudo) is you specified a --prefix with a user directory during the configure step. How you go about it is up to you.

Keeping Emacs up-to-date

Whenever you wish to update from source, go to where your copy of emacs.git is (e.g. ~/Builds/emacs.git) and pull the latest changes using the git program:

git pull

Then repeat make and make install. Remember that you do not need to re-run configure unless you specifically want to modify your build (and if you do that, you probably need to make bootstrap).

Learn about the latest NEWS

Emacs users can at all times learn about changes introduced in their current version of Emacs with M-x view-emacs-news. It is bound to the key C-h n by default. This command opens the current NEWS file. With a numeric prefix argument, you get the NEWS of the given Emacs version. For example, C-u 27 C-h n shows you what Emacs version 27 introduced.

Compare your NEWS to those of emacs.git

With the help of the built-in Emacs ediff package, you can compare your latest NEWS to those coming from emacs.git. I always do this after pulling the latest changes from source (with git pull).

From the root directory of your copye of emacs.git (e.g. ~/Builds/emacs.git), and while using Emacs, you can do M-x project-find-file (C-x p f) to search the Emacs “project” for a file called etc/NEWS. This is where the latest user-facing changes are recorded.

If you are not sure where you are on the filesystem while inside Emacs, do M-x cd (or M-x dired or M-x find-file), select the root directory of your emacs.git, hit RET, and then do M-x project-find-file.

Now that you have emacs.git/etc/NEWS in a buffer, also load your copy of NEWS with M-x view-emacs-news (C-h n).

Then do M-x ediff-buffers, which will prompt for two buffers to compare. First select your version of NEWS and then that of emacs.git.

NOTE: I think the default Ediff interface is problematic. Put the following in your configuration to make it work in a single frame:

(setq ediff-split-window-function 'split-window-horizontally)
(setq ediff-window-setup-function 'ediff-setup-windows-plain)

Also watch my video with the Ediff basics: https://protesilaos.com/codelog/2023-11-17-emacs-ediff-basics/.

This is it. You are now in the flow of building Emacs from source. Good luck with everything!

My current build options

--prefix=/usr/local --without-xinput2 --without-compress-install --without-gpm --without-selinux --with-native-compilation=yes --with-sound=no --without-gif --without-tiff --with-cairo --with-harfbuzz --with-tree-sitter=ifavailable --with-json --without-gsettings --without-gconf --with-x-toolkit=no --without-toolkit-scroll-bars --without-xft --without-xaw3d

I am not updating old publications, unless otherwise noted. The most up-to-date recode of my Emacs build is documented in my dotemacs: https://protesilaos.com/emacs/dotemacs.

Inspect the value of the Emacs variable system-configuration-options to find out how your Emacs is built.

Have fun!

]]>
Emacs: Denote is becoming many packages I am almost done splitting the 'denote' Emacs package into 'core' and 'extensions'. Here is what users need to know. Fri, 14 Mar 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-03-14-emacs-denote-many-packages/ https://protesilaos.com/codelog/2025-03-14-emacs-denote-many-packages/ In February I announced the plan to reorganise the Denote project into “core” and “extensions”: https://protesilaos.com/codelog/2025-02-11-emacs-splitting-denote-many-packages/. In essence, Denote is a file-naming scheme: you create new files and/or rename existing ones (of any file type). Having that naming scheme empowers you to retrieve stuff more easily without the need for advanced tooling.

Though it turns out we can do a lot of useful things on top of this simple-yet-powerful idea: custom Dired listings, Org dynamic blocks, sequence notes, journaling, and many more. Having a clear separation between core and extensions makes it easier for us to implement all the features we want without worrying that the main package is becoming bloated.

Concretely, much of the functionality that was part of the denote package will now be provided by other packages. To this end, I just made a change to the official elpa.git repository:

commit f23ff49fb8df22390fe139b432f763860a354175
Author: Protesilaos Stavrou <[email protected]>
Date:   Fri Mar 14 07:14:55 2025 +0200

  * elpa-packages (denote-journal, denote-markdown, denote-org, denote-sequence, denote-silo): Add new packages

 elpa-packages | 10 ++++++++++
 1 file changed, 10 insertions(+)

Finalising the reorganisation of Denote

What remains to be done is for me to merge the reorganise-denote branch of denote.git into main. I will do this as soon as the new packages are indexed on GNU ELPA (maybe later today or tomorrow).

Users of the GNU ELPA package will not be affected immediately. Those who build from source will, however, have to take action.

Expect breaking changes

Users will experience breaking changes when they update to the new denote package: functionality will be missing. In principle, all those should be easy to fix: install the appropriate new package and rename the functions/variables in your configuration accordingly. In detail:

  • The file denote-journal-extras.el becomes the package denote-journal. In your configuration replace denote-journal-extras with denote-journal.
  • The file denote-org-extras.el (Org dynamic blocks and related) becomes the package denote-org. In your configuration replace denote-org-extras with denote-org.
  • The file denote-silo-extras.el becomes the package denote-silo. In your configuration replace denote-silo-extras with denote-silo.

Additionally, the files that were in development but never made it as part of a formal release, namely, denote-md-extras.el and denote-sequence.el, will debut as their own packages: denote-markdown and denote-sequence, respectively.

You are welcome to ask me any questions

I am reluctant to introduce breaking changes, though this has to be done for the long-term wellness of the project. If you have any questions, please contact me directly or open an issue on the GitHub repository. I am happy to help you.

A concerted release cadence

All new packages are marked as version 0.0.0, which means that only those who track GNU-devel ELPA (or build from source) will notice them. The formal release will coincide with the new version of denote (4.0.0), which I expect to publish some time in April or May 2025.

]]>
Live @ 2025-03-15, 14:00 Europe/Athens: ‘Ask Me Anything’ about Emacs, Linux, and Life in general I will do a live stream where I answer all questions from the people in the chat. The event will be recorded. Sat, 08 Mar 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-03-08-live-stream-emacs-linux-life/ https://protesilaos.com/codelog/2025-03-08-live-stream-emacs-linux-life/ Raw link: https://www.youtube.com/watch?v=p5VPxbr-2ds

On Saturday, the 15th of March 2025, at 14:00 o’clock of time zone Europe/Athens, I will do a live stream where I will answer every question posted in the chat. The idea is to cover any of the topics I already write/talk about on my website, including Emacs, free software, politics, philosophy, and everyday affairs.

I will answer every question from top to bottom to the best of my abilities and will not give any of those formulaic non-answers.

The plan is to do a minimum of two hours, but may extend it for at least one or two more hours depending on the participation in the chat. My electricity should be okay because the weather forecast shows a clear day with fairly warm temperatures (finally!).

The event will be recorded, so no worries if you cannot make it live.

Talk to all of you soon!

]]>
Emacs: fontaine version 3.0.0 Information about the latest version of my fontaine package for GNU Emacs. Thu, 20 Feb 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-02-20-emacs-fontaine-3-0-0/ https://protesilaos.com/codelog/2025-02-20-emacs-fontaine-3-0-0/ Fontaine allows the user to define detailed font configurations and set them on demand. For example, one can have a regular-editing preset and another for presentation-mode (these are arbitrary, user-defined symbols): the former uses small fonts which are optimised for writing, while the latter applies typefaces that are pleasant to read at comfortable point sizes.

Below are the release notes.


Version 3.0.0 on 2025-02-20

This version changes the underlying implementation of Fontaine’s font configuration presets. In principle, this should not have any effect on how users experience the package, though there are some important details that are different.

Fontaine is now a “theme”

Fontaine has always modified typography-related faces, such as default, fixed-pitch, and variable-pitch, to apply the font family, height, and weight specified by the user. In the past, this was done in a way that could get overridden under certain conditions, such as by loading a theme after setting a Fontaine preset configuration.

By making Fontaine a theme, we guarantee that its settings are not undone. In practice, this means that users do not have to re-apply the current preset after loading a theme. The function fontaine-apply-current-preset is thus obsolete.

In Emacs, a “theme” is a bundle of configurations. Those typically cover colours (such as with my modus-themes), but a theme can focus on other settings as well. For example, the popular use-package is internally done as a theme (check the value of custom-known-themes).

Fontaine is a theme in the same way use-package is, meaning that it will (i) persist its effects, (ii) not show up in the custom-enabled-themes and so not be affected by something like (mapc #'disable-theme custom-enabled-themes), and (iii) not be an option among those presented by load-theme.

There are no known bugs, though please contact me if you encounter a scenario where Fontaine does not do the right thing. Thanks, in this regard, to Haruko and Emily Hyland for reporting a couple of bugs:

Fontaine no longer has frame-specific effects

In the past, users could apply a Fontaine preset to the current frame without affecting other frames. While this could be useful in certain situations, it was ultimately making the code more complex for marginal gains. As part of the transition to a theme, which is anyway global, I am removing everything related to frame-specific functionality.

Quality-of-life refinements

  • The fontaine-generic-face-families are used when necessary to guard against nil values. Those font families are symbolic references to whatever the operating system is configured to use (e.g. on Linux this is handled by fontconfig).

  • If Fontaine is instructed to load an invalid preset, it displays a warning and does nothing else. Before, it would produce an error, which could prevent Emacs from starting up normally if this were to happen at startup. A warning is enough to inform the user of what is happening.

  • Same principle as above when Emacs is not ran in a graphical interface. In text terminals, Fontaine cannot work because it is not possible to have different font families, styles, and heights, than those of the terminal (hence the backronym of FONTAINE “Fonts, Ornaments, and Neat Typography Are Irrelevant in Non-graphical Emacs”). Thanks to Jorge Gomez for the patch in pull request 13: https://github.com/protesilaos/fontaine/pull/13. Further tweaks by me.

  • The fontaine-toggle-preset command will produce an error if it cannot find the preset it is supposed to switch to. The toggle is between the last two loaded presets, as done by the command fontaine-set-preset (the fontaine-mode takes care to persist the relevant history).

]]>
Emacs: dired-preview version 0.4.0 Information about the latest version of my dired-preview package for GNU Emacs. Tue, 18 Feb 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-02-18-emacs-dired-preview-0-4-0/ https://protesilaos.com/codelog/2025-02-18-emacs-dired-preview-0-4-0/ This is a simple package to automatically preview in a window the file at point in Dired buffers. Preview windows are closed when they are no longer relevant, while preview buffers are killed if they have not been used for other purposes beside previewing. The package provides several customisation options to control its behaviour.

Below are the release notes


Version 0.4.0 on 2025-02-18

This version contains several refinements and bug fixes.

Preview buffers have a mode line indicator

Preview buffers have a prefix to their name to make them stand out. This is controlled by the user option dired-preview-buffer-name-indicator, which is a string that defaults to [P].

Control how preview buffers are cleaned up

The way dired-preview works is to display a buffer and then keep a list of preview buffers to economise on redisplaying it again. This list of buffers is relevant for as long as we are in the Dired buffer, otherwise all buffers therein are killed (buffers that were alive before being previewed are not touched).

By default we delete from oldest to newest the accumulated buffers when they exceed 10 in total. Though users can modify this behaviour by editing the value of the new user option dired-preview-kill-buffers-method (its doc string explains the technicalities).

Thanks to artelse for discussing this with me in issue 20: https://github.com/protesilaos/dired-preview/issues/20.

The dired-preview-display-action-alist has a new optional function

The dired-preview-display-action-alist is the user option which controls where the preview window is displayed. Its value can either be the symbol of a function or a display-buffer-alist entry.

By default, we have a “do-what-I-mean” function that tries to find a good placement for the window. The new dired-preview-display-action-alist-below function has a straightforward behaviour: it always shows the preview below the current window and it always makes the preview window 0.3 times the height of the Emacs frame.

Encypted files are no longer previewed

This is to ensure that potentially sensitive contents are not displayed by accident, such as during a video call.

We no longer preview the “self” directory

We should not trigger a preview when the cursor is over the implicit . directory, as that causes a recursion that breaks things. Thanks to Inkbottle007 for reporting the bug in issue 23: https://github.com/protesilaos/dired-preview/issues/23.

Miscellaneous

  • Fixed a scenario where we would try to delete the last available window on the current frame. This should never happen. Thanks to artelse for reporting a relevant bug in the discussion of issue 22: https://github.com/protesilaos/dired-preview/issues/22.

  • Fixed a case when hexl-follow-ascii could fail to find an overlay under certain conditions. This did not create any noticeable problems, though having an error there would interfere with any workflow that would rely on toggle-debug-on-error.

  • The preview window will automatically be closed if the user switches outside the given Dired buffer. We now do not consider a change to the minibuffer as being “outside” this context. This way, a quick M-x to, say, enable a minor mode does not have any effect on the window layout.

  • Suppressed the messaging facility of the underlying tracking of preview buffers. Otherwise, Dired would notify us that the directory has changed whenever we would preview a new one, which is superfluous.

  • The body of the dired-preview-trigger function, which determines whether a preview will be displayed, is encapsulated in a condition-case. This helps capture errors and thus have a more predictable behaviour.

  • The dired-preview-display-action-alist has a more accurate declaration which allows for its correct customisation inside the Custom UI interface. In particular, it will behave the same way as the display-buffer-alist, where relevant.

]]>
Aporetic fonts version 1.1.0 Release notes for the latest version of my custom 'Aporetic' fonts. Wed, 12 Feb 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-02-12-aporetic-fonts-version-1-1-0/ https://protesilaos.com/codelog/2025-02-12-aporetic-fonts-version-1-1-0/ Customised build of the Iosevka typeface, with a consistent rounded style and overrides for almost all individual glyphs in both upright (roman) and slanted (italic) variants. This is the successor to my now-discontinued “Iosevka Comfy” fonts.

Below are the release notes.


This release includes two stylistic corrections that pertain to Aporetic Serif and Aporetic Serif Mono.

  • The first change is to the slanted (italic) form of the letter t. Before, it was mistakenly set to have a curved, upward-facing bottom stroke, which would clash with the flat bottom of i and l. Now the slanted t has a flat bottom as intended. The upright (roman) variants are always flat in this regard.

  • The second change is to the letter m in both upright and slanted forms. Before, the m would have a top left serif, as intended, but not a bottom right tail. The tail is a feature of other glyphs that need to have such a style, like a, h, n, u: it imposes a proper rhythm together with the rest of the serif details. Now the m has its missing bottom right tail, making everything consistent.

    [ The m has a shorter middle leg in all the “mono” families” to improve readability, especially at small point sizes. The proportionately spaced fonts use a normal middle leg, as m is naturally wider there and thus is already perfectly legible. The other details are the same. ]

]]>
Emacs: I am in the process of splitting Denote into many packages Development note on the future of my 'denote' package for Emacs. The plan is to separate the core from its extensions. Tue, 11 Feb 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-02-11-emacs-splitting-denote-many-packages/ https://protesilaos.com/codelog/2025-02-11-emacs-splitting-denote-many-packages/ I am reorganising the denote package to have a clear separation between “core” and “extensions”. The idea is to decouple the two. The denote package shall provide only the core functionality, while all other features we already have will be available as standalone packages.

The reason I am doing this is because the project has organically grown over time to encompass lots of useful-yet-inessential applications, such as Org dynamic blocks, journaling capabilities, and sequence schemes, among others.

All those extras are nice to have, though they dilute the message about what Denote is, making it seem far more complex than it actually is. They are also held back by the minimalist outlook of the core: they cannot be developed to their logical end, as any dependency they incorporate becomes a dependency of the whole project, which makes no sense (e.g. we can have a transient.el to interact with Denote commands, but this is in no way essential, so why force it upon everyone who downloads the denote package?).

The core

Denote essentially is a file-naming scheme. We create new files or rename existing ones to have file names that are easy to retrieve with even basic tools. This is my use-case and the reason I wrote Denote: I name my videos, PDFs, pictures, and “notes” with the Denote file-naming scheme, making it easy for me to find everything.

I think the Denote file-naming scheme is ingenious, though the real value is in having a scheme—any scheme—to force consistency in how you name things. Consistency begets predictability, which in turn increases the likelihood of finding your data.

The other part of retrieving information is through links. Part of the Denote file-naming scheme is the date+time, which is a unique identifier. We can thus link to any file in the denote-directory using its identifier. Once we have these “forward links”, we can easily figure out what the “backward links” of a given file are, i.e. which files link to the current one.

This is the core, plus a few other conveniences that I need not enumerate herein.

The extensions

Anything that builds on the aforementioned is an “extension” and will have its own Git repository as well as user manual. To this end, I have already removed denote-sequence.el from the denote core and made it its own entity:

The plan is to do the same with the “Org extras”, such as with all the Org dynamic blocks, the “Markdown extras”, the “journal extras”, and the “silo extras”. Once all the packages are ready for widespread use, I will add them to GNU ELPA. Until then, everything is a WORK-IN-PROGRESS.

For the time being, the technical discussion is done in issue 543: https://github.com/protesilaos/denote/issues/543. The code which will eventually be merged into the main branch resides in the reorganise-denote branch: https://github.com/protesilaos/denote/tree/reorganise-denote.

For the longer-term benefit of the project

There will be no reduction in the total set of features we provide. This is only a matter of reorganising what we have, namely, to (i) make it easier for new users to understand what Denote is, (ii) pick only the extensions they require, (iii) make it possible to decentralise the maintenance of the project should I ever need to step down (which is not happening, but as a matter of principle).

Those granted, keep in mind that Denote is not a “second brain” and will not make you smarter. It is a flexible and capable tool, truly Emacs-y in its adaptability, that you can use as part of a workflow that makes sense to you. Let us then decouple the core from its extensions and continue to give users the best possible experience with every piece of code and documentation that we write.

]]>
Iosevka Comfy is discontinued; hello ‘Aporetic’ fonts Release notes for the latest tagged release of my Aporetic fonts. Tue, 04 Feb 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-02-04-aporetic-fonts-1-0-0/ https://protesilaos.com/codelog/2025-02-04-aporetic-fonts-1-0-0/ I am discontinuing the development of the Iosevka Comfy fonts, effective immediately. My new fonts are called Aporetic and are the successor to my earlier project.

Aporetic fonts:

Iosevka Comfy:

Legal reason for the change

“Iosevka” is a reserved name. I had not realised this until I reread the SIL Open Font License, Version 1.1, specifically:

3 No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users.

Technical reasons for the change

I wanted to change the names of the font families to make them more intuitive. Instead of something like “Iosevka Comfy Motion Duo” I now have “Aporetic Serif”. The full list is further below.

I also had to reduce the number of variants and font weights to both (i) streamline what I am offering and (ii) make it possible to build the fonts on my computer.

Changes relative to Iosevka Comfy

The fonts are these:

Current name Old name
Aporetic Sans Iosevka Comfy Duo
Aporetic Serif Iosevka Comfy Motion Duo
Aporetic Sans Mono Iosevka Comfy
Aporetic Serif Mono Iosevka Comfy Motion

I no longer provide “fixed” and “wide” variants.

All glyphs are the same as before except for the zero (0), which is now always rendered with a forward slash and a wider body. The reason for this change is that the narrow oval shape could be mistaken for a Greek theta (θ).

Font weights are also reduced to just regular and bold.

Why “aporetic”

It is a nice Greek word and no other fonts with this name exist.

]]>
Emacs: aLtCaPs version 1.3.0 Information about the latest version of my text-transformation package for GNU Emacs. It helps convey sarcasm or mockery. Tue, 28 Jan 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-01-28-emacs-altcaps-1-3-0/ https://protesilaos.com/codelog/2025-01-28-emacs-altcaps-1-3-0/ This version does not include any user-facing changes. I made some internal refinements and ensured everything works as expected. Just use the sample configuration to get started:

(use-package altcaps
  :ensure t
  :bind
  ("C-x C-a" . altcaps-dwim)
  :config
  ;; Optionally force letter casing for certain characters (for legibility).
  (setq altcaps-force-character-casing
      '(("i" . downcase)
        ("l" . upcase))))

About altcaps

The altcaps package is a small, focused-in-scope tool that helps users communicate mockery or sarcasm effectively. It does this by alternating the letter casing of characters in the words it affects.

]]>
Emacs: organise your init file (outline-minor-mode or Org literate config) A video demonstration of using either outline-minor-mode or Org to manage your Emacs init.el. Sun, 26 Jan 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-01-26-emacs-organise-init/ https://protesilaos.com/codelog/2025-01-26-emacs-organise-init/ Raw link: https://www.youtube.com/watch?v=Dkoy3NrLN9g

In this 25-minute video I show two ways to organise your Emacs init.el file. One approach is to keep editing the code in Emacs Lisp and to leverage the “outline”, while the other is to use a literate Org file whose code blocks will be “tangled” to the init.el. I explain all the technicalities and show examples. More resources:

]]>
Emacs: show-font version 0.2.0 Information about the latest version of my show-font package for GNU Emacs. Sat, 25 Jan 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-01-25-emacs-show-font-0-2-0/ https://protesilaos.com/codelog/2025-01-25-emacs-show-font-0-2-0/ This package lets you preview a font inside of Emacs. It does so in three ways:

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

Sources:

Below are the release notes.


Version 0.2.0 on 2025-01-25

This version includes quality-of-life refinements.

Show fonts in a tabulated listing

The command show-font-tabulated will produce a listing of font families and their preview that uses the built-in tabulated interface. This interface is the same as the one used by M-x list-packages. Users can sort fonts by font family name (move point to the given column and type S or call M-x tabulated-list-sort).

When show-font-tabulated is called with a prefix argument (C-u by default), it prompts for a string or regular expression. It then shows only the font families matching the given input.

Limit font listing using a regular expression

The command show-font-list which we already had in version 0.1.0 is like the show-font-tabulated, but uses a bespoke buffer where each font and its preview are shown one after the other. Now it also accepts an optional prefix argument to limit the list to only the matching fonts.

The show-font-display-buffer-action-alist controls buffer placement

The preview buffers we use will now conform with the value of the new user option show-font-display-buffer-action-alist. This is a more advanced feature, due to how display-buffer works, so you may want to check the video I did recently about controlling where buffers are displayed: https://protesilaos.com/codelog/2024-02-08-emacs-window-rules-display-buffer-alist/.

The default value of show-font-display-buffer-action-alist will show the buffer at the bottom of the frame.

]]>
Emacs: beframe version 1.3.0 Information about the latest version of my beframe package for GNU Emacs. Fri, 24 Jan 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-01-24-emacs-beframe-1-3-0/ https://protesilaos.com/codelog/2025-01-24-emacs-beframe-1-3-0/ beframe enables a frame-oriented Emacs workflow where each frame has access only to the list of buffers visited therein. In the interest of brevity, we call buffers that belong to frames “beframed”.

Below are the release notes


Version 1.3.0 on 2025-01-24

This version contains quality-of-life refinements to an already stable package.

Make frame names unique, if needed

We provide the user option beframe-rename-function, which will be called with the new frame when beframe-mode is enabled. The idea is to automatically apply a helpful name to the frame that was created. The default function we use is beframe-rename-frame, which will do the right thing to get a suitable name. To make this even more robust, we now disambiguate equal frame names by appending a number to their name. So instead of having two or more frames all named hello, you get hello, hello<2>, and so on.

Thanks to Vedang Manerikar for the original contribution in pull request 12: https://github.com/protesilaos/beframe/pull/12. The change is within the ~15-line limit, meaning that Vedang does not need to assign copyright to the Free Software Foundation (though I believe the paperwork is done anyway). I made some further changes on top.

Remember that you can make certain commands automatically generate a frame and run therein by adding them to the list of beframe-functions-in-frames. A common use-case is to do this for switching to a new project, hence:

(setq beframe-functions-in-frames '(project-prompt-project-dir))

Use the optional beframe-transient instead of the prefix key map

We provide a regular prefix key map where Beframe commands are bound to. Users can access all the commands via a prefix key, such as with:

(define-key global-map (kbd "C-c b") #'beframe-prefix-map)

Users who prefer a more graphical interface can instead rely on the new beframe-transient. It is the same principle as the prefix key map:

(define-key global-map (kbd "C-c b") #'beframe-transient)

[ The difference between the two interfaces is small when using the which-key package. ]

The buffer prompt clarifies that it is “Beframed”

While using the beframe-mode, the standard read-buffer-function is set to a Beframe function that prompts for a buffer. The idea is to filter the list of buffers to only show those that are specific to the current/given frame. To make this more clear, the text of the prompt now has [Beframed] prepended to it.

I do not think we need a user option for this, though I am happy to reconsider if there is a good reason for it.

Miscellaneous

  • Fixed the function aliases of the “assume” and “unassume” commands that take a regular expression as input to perform their operation. The old aliases where written in the wrong way, such that they were rendering the original function void.

  • Bound a few more commands to the beframe-prefix-map. Everything should now be there, to improve discoverability (remember that C-h after an incomplete key sequence will produce a Help buffer that lists all the keys+commands which extend the given key sequence).

  • The name of the beframe-buffer-menu buffer is more descriptive. The command beframe-buffer-menu puts the beframed list of buffers in a buffer. Its old naming scheme was *Buffer list for NAME*, where NAME is the name of the frame. Whereas now it is *Buffer list for ‘NAME’ frame*.

  • Same as above for the frame-specific scratch buffers. Those are generated for new frames when beframe-create-frame-scratch-buffer is non-nil (the default) and beframe-mode is enabled.

]]>
Emacs: Org todo and agenda basics A video demonstration of using Org mode in Emacs to write and manage tasks. Thu, 16 Jan 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-01-16-emacs-org-todo-agenda-basics/ https://protesilaos.com/codelog/2025-01-16-emacs-org-todo-agenda-basics/ Raw link: https://www.youtube.com/watch?v=L0EJeN1fCYw

In this ~45-minute video I cover the basics of managing your task list with Org mode. The idea is to write tasks in a simple file and then use the Org agenda views to display and filter the tasks you are interested in. Throughout the video I also comment on relevant points about the overall workflow. The basic configuration I show in the video is below:

;; These are the defaults we want to change.  We do so in the
;; following `use-package' declaration.
(setq org-M-RET-may-split-line '((default . t)))
(setq org-insert-heading-respect-content nil)
(setq org-log-done nil)
(setq org-log-into-drawer nil)


(use-package org
  :ensure nil ; do not try to install it as it is built-in
  :config
  (setq org-M-RET-may-split-line '((default . nil)))
  (setq org-insert-heading-respect-content t)
  (setq org-log-done 'time)
  (setq org-log-into-drawer t)

  (setq org-directory "/tmp/testing-org/")
  (setq org-agenda-files (list org-directory))

  ;; Learn about the ! and more by reading the relevant section of the
  ;; Org manual.  Evaluate: (info "(org) Tracking TODO state changes")
  (setq org-todo-keywords
        '((sequence "TODO(t)" "WAIT(w!)" "|" "CANCEL(c!)" "DONE(d!)"))))
]]>
Emacs: denote-sequence.el will also support alphanumeric sequences The new optional 'denote-sequence' will also support alphanumeric sequences (Luhmann-style folgezettel). Sat, 11 Jan 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-01-11-emacs-denote-alphanumeric-sequences/ https://protesilaos.com/codelog/2025-01-11-emacs-denote-alphanumeric-sequences/ In a video from 2025-01-03 (sequence notes with Denote (denote-sequence.el)), I introduced the new optional extension for Denote, which streamlines the creation of file names with an inherent hierarchical relationship. This is expressed as a numeric sequence, where each level of depth is delimited by the equals sign. So 1=1=2 refers to the second child of the first child of the parent note 1.

A popular sequencing scheme is to combine numbers with letters (Luhmann-style folgezettel). This alphanumeric expression is more compact, though it might also be a bit harder to reason about. For example, 1a2 is the same as 1=1=2, which looks clean, but it gets tricky once you reach 1za5zx which is equivalent to 1=27=5=50.

Unlike the numeric scheme where there is an explicit depth delimiter (the =), the alphanumeric scheme establishes depth by alternating between numbers and letters. Thus, 1a2 and 1=1=2 are both three levels of depth.

I am in the process of giving users the option. They will be able to pick their sequencing scheme and then produce notes, re-parent them, and so on, with Denote taking care to use/generate the correct sequence each time. In principle, the two schemes are interoperable and there will be relevant commands to switch between them.

[ UPDATE 2025-01-12 11:25 +0200: Now merged into main and deleted the feature branch. ]

Below is the commit I worked on today. For now it lives in the alphanumeric-sequence-extension branch: https://github.com/protesilaos/denote/tree/alphanumeric-sequence-extension. I will merge it into main as soon as I am done with the user-facing parts, which I will probably do tomorrow or early next week. If you are interested to try out what is now available, please check the source code and let me know your thoughts.

commit 43bd30e6ebd9e948a390d11bc3ec84cf80e74576
Author: Protesilaos Stavrou <[email protected]>
Date:   Sat Jan 11 19:37:56 2025 +0200

  Make the groundwork for alphanumeric (Luhmann) sequences in denote-sequence.el

  The idea is to support both numeric and alphanumeric sequencing
  schemes, as documented in the new user option 'denote-sequence-scheme'.

  We now have the tools to correctly split, join, increment, and convert
  input accordingly, such that we can, for example, accurately produce a
  child of sequence "1a2" (we could already do that for numeric
  sequences).

  What is covered herein is just the groundwork. I still need to extend
  the helper functions which directly support the creation of new
  parent, child, or sibling sequences. While this still is a lot of
  work, the hard part is now done.

 denote-sequence.el   | 338 +++++++++++++++++++++++++++++++++++++++------------
 tests/denote-test.el |  34 +++++-
 2 files changed, 291 insertions(+), 81 deletions(-)

About Denote

Denote is a simple note-taking tool for Emacs. It is based on the idea that notes should follow a predictable and descriptive file-naming scheme. The file name must offer a clear indication of what the note is about, without reference to any other metadata. Denote basically streamlines the creation of such files while providing facilities to link between them.

Denote’s file-naming scheme is not limited to “notes”. It can be used for all types of file, including those that are not editable in Emacs, such as videos. Naming files in a consistent way makes their filtering and retrieval considerably easier. Denote provides relevant facilities to rename files, regardless of file type.

]]>
Emacs: custom Oxford University calendar weeks Sample code to show the Oxford University teaching terms in the Emacs calendar. Thu, 09 Jan 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-01-09-emacs-oxford-calendar-weeks/ https://protesilaos.com/codelog/2025-01-09-emacs-oxford-calendar-weeks/ UPDATE 2026-01-09 18:06 +0200: I have turned this into a package: https://protesilaos.com/codelog/2026-01-09-emacs-oxford-calendar-package/.


Over at Oxford University they use their own calendaring scheme to label the terms and weeks of their school year. Why? Because they can! And why would some guy in the mountains of Cyprus care? Because it’s fun to write Emacs Lisp!

The academic year is divided into three periods of teaching and three of vacation. The latter have no special names, while the former are called “Michaelmas”, “Hilary”, and “Trinity”. Each teaching term consists of a few weeks whose numbering starts from 1.

With some custom code, we can configure the Emacs M-x calendar to tell us (i) which term we are in for the current month of the Oxford academic year, if any, (ii) which term and week number we are in, if any, and (iii) which is the standard week number.

The generic ‘M-x calendar’ 😴

Here is how it looks without any customisations. Serviceable, but not conducive to the Oxford culture.

Generic Emacs calendar

The Oxford-friendly ‘M-x calendar’ 🎓

It is busier, for sure, though this is what you get for being at Oxford. Notice that when there is nothing Oxford-related, we just show the regular calendar information.

Oxford Emacs calendar

The code

UPDATE 2025-01-09 18:36 +0200: I revised a few lines of code to (i) work with either Sunday or Monday as the first day of the week, (ii) not show any Oxford week beyond the years specified in prot-oxford-dates.


I wrote this over the course of a few hours. It may be refined here and there, but I think it is already good enough. The only major improvement would be to implement the formula that Oxford uses to derive their dates. As I do not know it, the prot-oxford-dates have to be updated manually each year.

;; NOTE 2025-01-09: Perhaps there is some formula to always get the
;; dates, but I am not aware of it.  As such, these dates need to be
;; updated at the start of each school year.
;;
;; Source: <https://www.ox.ac.uk/about/facts-and-figures/dates-of-term>.
(defvar prot-oxford-dates
  '((michaelmas  (10 13 2024)  (12 7 2024))
    (hilary      (1  19 2025)  (3 15 2025))
    (trinity     (4  27 2025)  (6 21 2025)))
  "Alist of Oxford calendar terms with start and end date.
Each element is of the form (NAME START END), where NAME is the name of
the term, as a symbol, START is the start date and END is the end date.
START and END each are of the form (month day year), where each element
is a number.")

(defun prot-oxford--get-iso-week (date)
  "Get the ISO week of DATE.
DATE is a list of the form (month day year)."
  (unless (calendar-date-is-valid-p date)
    (error "The date `%s' does not conform with `calendar-date-is-valid-p'" date))
  (car
   (calendar-iso-from-absolute
    (calendar-absolute-from-gregorian date))))

(defun prot-oxford--get-term-week (term-start-week term-end-week iso-week prefix)
  "Return the number of the Oxford term week or nil.
Determine the week given TERM-START-WEEK and TERM-END-WEEK as Gregorian
week numbers.  Compare ISO-WEEK to them.

If `calendar-week-start-day' is a Monday, then start counting weeks from
0, because Oxford weeks start from Sunday (otherwise, Week 1 includes 6
days before the first Sunday).

When returning the number, concatenate it with PREFIX.  PREFIX is a
single letter string.  A longer PREFIX is trimmed accordingly."
  (when (and term-start-week term-end-week iso-week)
    (when-let* ((offset (pcase calendar-week-start-day
                          (0 1)
                          (1 0)))
                (number (cond
                         ((> iso-week term-end-week)
                          nil)
                         ((= term-start-week iso-week)
                          offset)
                         ((< term-start-week iso-week)
                          (+ (- iso-week term-start-week) offset))))
                (pre (if (> (length prefix) 1)
                         (substring prefix 0 1)
                       prefix)))
      (concat pre (number-to-string number)))))

(defun prot-oxford--get-term-weeks (term year)
  "Return Oxford TERM start and end week numbers as a list.
Check YEAR to determine if the date is out of bonds of the
`prot-oxford-dates'."
  (pcase-let* ((`(,beg-date ,end-date) (alist-get term prot-oxford-dates))
               (`(,_ ,_ ,term-year) beg-date)
               (beg-week (prot-oxford--get-iso-week beg-date))
               (end-week (prot-oxford--get-iso-week end-date)))
    (when (= term-year year)
      (list beg-week end-week))))

(defface prot-oxford-term-indicator
  '((((class color) (min-colors 88) (background light))
     :foreground "#224499")
    (((class color) (min-colors 88) (background dark))
     :foreground "#afc9f3")
    (t :inherit shadow))
  "Face to style the Oxford term indicator.")

(defface prot-oxford-regular-week
  '((t :inherit shadow))
  "Face to style the regular week.")

(defun prot-oxford-week (month day year)
  "Use MONTH DAY YEAR to determine current week.
Derive the Oxford term week based on the `prot-oxford-dates'."
  (pcase-let* ((`(,m-w-beg ,m-w-end) (prot-oxford--get-term-weeks 'michaelmas year))
               (`(,h-w-beg ,h-w-end) (prot-oxford--get-term-weeks 'hilary year))
               (`(,t-w-beg ,t-w-end) (prot-oxford--get-term-weeks 'trinity year))
               (gregorian-week (prot-oxford--get-iso-week (list month day year)))
               (oxford-week (or (prot-oxford--get-term-week m-w-beg m-w-end gregorian-week "M")
                                (prot-oxford--get-term-week h-w-beg h-w-end gregorian-week "H")
                                (prot-oxford--get-term-week t-w-beg t-w-end gregorian-week "T")
                                "")))
    (format " %2s  %2s  "
            (propertize oxford-week 'face 'prot-oxford-term-indicator)
            (propertize (format "%2s" gregorian-week) 'face 'prot-oxford-regular-week))))

(defun prot-oxford--get-term-month (term-name term-start-month term-end-month month)
  "Return the TERM-NAME of the term month or nil.
Determine the name given TERM-START-MONTH and TERM-END-MONTH as month
numbers.  Compare MONTH to them."
  (when-let* ((number (cond
                       ((> month term-end-month)
                        nil)
                       ((= term-start-month month)
                        1)
                       ((< term-start-month month)
                        (+ (- month term-start-month) 1)))))
    term-name))

(defun prot-oxford--get-months (term)
  "Get start and end months of `prot-oxford-dates' TERM as a list."
  (mapcar #'car (alist-get term prot-oxford-dates)))

(defun prot-oxford-month (year month)
  "Return abbreviated name of MONTH for YEAR.
Append the Oxford term name based on the `prot-oxford-dates'."
  (pcase-let* ((`(,m-beg ,m-end) (prot-oxford--get-months 'michaelmas))
               (`(,h-beg ,h-end) (prot-oxford--get-months 'hilary))
               (`(,t-beg ,t-end) (prot-oxford--get-months 'trinity))
               (oxford-term-name (or (prot-oxford--get-term-month "Michael" m-beg m-end month)
                                     (prot-oxford--get-term-month "Hilary" h-beg h-end month)
                                     (prot-oxford--get-term-month "Trinity" t-beg t-end month)
                                     "")))
    (format "%s %s %s"
            (propertize (calendar-month-name month :abbreviate) 'face 'calendar-month-header)
            (propertize (format "%s" year) 'face 'calendar-month-header)
            (propertize oxford-term-name 'face 'prot-oxford-term-indicator))))

(defun prot-oxford-intermonth-header ()
  "Return string for `calendar-intermonth-header'."
  (format "%s %s"
          (propertize "OX" 'face 'prot-oxford-term-indicator)
          (propertize "Week" 'face 'shadow)))

(setopt calendar-left-margin 10
        ;; Oxford assumes Sunday starts the week, but we want to work
        ;; with the ISO commercial dates, so Monday (1) is the first
        ;; day of the week.  But Sunday (0) will still work.
        calendar-week-start-day 1
        calendar-intermonth-spacing 12
        calendar-intermonth-header (prot-oxford-intermonth-header)
        calendar-intermonth-text '(prot-oxford-week month day year)
        calendar-month-header '(prot-oxford-month year month))
]]>
Emacs: the next Fontaine version will use a custom theme Announcement about the current developments in my 'fontaine' package for GNU Emacs. Wed, 08 Jan 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-01-08-emacs-fontaine-custom-theme/ https://protesilaos.com/codelog/2025-01-08-emacs-fontaine-custom-theme/ As part of the current development target of my fontaine package, the way I implement changes to fonts is done via a custom theme.

commit 69e80d4a93b28804f3b9d8a0b4328952c2f0d568
Author: Protesilaos Stavrou <[email protected]>
Date:   Wed Jan 8 10:42:35 2025 +0200

  BREAKING use a custom theme instead of 'set-face-attribute' internals

 fontaine.el | 179 +++++++++++++++++++++---------------------------------------
 1 file changed, 63 insertions(+), 116 deletions(-)

Before, I was relying on the internals of set-face-attribute which worked decently for the most part but required manual intervention to persist the face attributes between theme changes. Whereas the custom theme shall remain in effect no matter what, thus reducing complexity.

Furthermore, the custom theme allows me to declare the display specification in which the given face attributes (i.e. the font styles) apply. I can thus specify that these are for a graphical Emacs frame only.

A potential advantage is the ability to modify any face, even if it is not initialised, whereas set-face-attribute requires the face be defined, else it produces an error. This potential is not realised for the time being because there is no face of the sort that Fontaine affects. All the faces it modifies are loaded eagerly by Emacs. If I need to cover more faces though, it will be straightforward.

For users, the only obvious effect of this transition is the discontinuation of the option to set a Fontaine preset per frame. All face attributes are now always applied to all frames. I am doing this because the old design did not work reliably in all cases and was a niche feature anyway.

I am not aware of any regressions, though I continue to test the package. If you do try it before the new version is out, please let me know of any possible bugs or other improvements we can make.

About Fontaine

Fontaine allows the user to define detailed font configurations and set them on demand. For example, one can have a regular-editing preset and another for presentation-mode (these are arbitrary, user-defined symbols): the former uses small fonts which are optimised for writing, while the latter applies typefaces that are pleasant to read at comfortable point sizes.

]]>
Emacs: spacious-padding version 0.6.0 Information about the latest version of my 'spacious-padding' package for GNU Emacs. Mon, 06 Jan 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-01-06-emacs-spacious-padding-0-6-0/ https://protesilaos.com/codelog/2025-01-06-emacs-spacious-padding-0-6-0/ This package provides a global minor mode to increase the spacing/padding of Emacs windows and frames. The idea is to make editing and reading feel more comfortable. Enable the mode with M-x spacious-padding-mode. Adjust the exact spacing values by modifying the user option spacious-padding-widths.

Inspiration for this package comes from Nicolas Rougier’s impressive designs and Daniel Mendler’s org-modern package.

Release notes below.


This is a small release that makes some minor refinements. The package is otherwise stable and works as expected.

We use the spacious-padding theme instead of user

This is an internal detail with how we implement the “spacious” changes to the faces we cover. Before, we would override anything that the user would explicitly configure with custom-set-faces, either via their Elisp code or through the Custom User Interface and the snippet it automatically generates.

By storing our changes in the bespoke spacious-padding theme instead of the special user theme, we do not override the user’s preference. This is the right design in principle, though users may no longer get the same styles as before because faces they had configured before will now override what spacious-padding-mode does.

When in doubt, search your configuration for custom-set-faces, comment out the whole block, try to re-enable spacious-padding-mode, and see if the results are okay.

Thanks to Martin Marshal for making the initial change in pull request 26: https://github.com/protesilaos/spacious-padding/pull/26. The change is within the 15-line limit of permitted changes without the need for copyright assignment to the Free Software Foundation. I then followed it up with the creation of the ~spacious-padding theme.

The tab-line-tab-current face is supported

This means that tab-line-mode will look consistent when spacious-padding-mode is enabled, instead of some tabs looks smaller/different.

spacious-padding-mode works with window-divider-mode

Thanks to Pierre Baille and Tobias Tschinkowitz for bringing up the problem in issue 17: https://github.com/protesilaos/spacious-padding/issues/17.

]]>
Emacs: sequence notes with Denote (denote-sequence.el) A video demonstration of the new optional extension for Denote to create 'sequence notes' (denote-sequence.el). Fri, 03 Jan 2025 00:00:00 +0000 https://protesilaos.com/codelog/2025-01-03-denote-sequence-demo/ https://protesilaos.com/codelog/2025-01-03-denote-sequence-demo/ Raw link: https://www.youtube.com/watch?v=27krzVtflQY

In this ~21-minute video I demonstrate the new optional extension for Denote that I am developing. The denote-sequence.el is part of the denote package. Its purpose is to streamline the creation of “sequence notes”, i.e. files that have an inherent relationship between them. The sequence is represented as a number.

Note that the code is in-development and will be released as part of Denote version 3.2.0. I still plan to make some refinements, though the core functionality is already done.

About Denote

Denote is a simple note-taking tool for Emacs. It is based on the idea that notes should follow a predictable and descriptive file-naming scheme. The file name must offer a clear indication of what the note is about, without reference to any other metadata. Denote basically streamlines the creation of such files while providing facilities to link between them.

Denote’s file-naming scheme is not limited to “notes”. It can be used for all types of file, including those that are not editable in Emacs, such as videos. Naming files in a consistent way makes their filtering and retrieval considerably easier. Denote provides relevant facilities to rename files, regardless of file type.

]]>