Here are a few new features I’ve added to GNU ELPA and upstream GNU Emacs recently. Text is adapted from the in-tree documentation I wrote for the new features. Thanks to everyone who offered feedback on my patches.

New feature to easily bypass Eshell’s own pipelining

Prefixing |, < or > with an asterisk, i.e. *|, *< or *>, will cause the whole command to be passed to the operating system shell. This is particularly useful to bypass Eshell’s own pipelining support for pipelines which will move a lot of data.

This has long been an obstacle when it comes to using Eshell as one’s main shell. The new syntax is easy to use and covers a lot of different use cases.

New Eshell module to help supplying absolute file names to remote commands

After enabling the new eshell-elecslash module, typing a forward slash as the first character of a command line argument will automatically insert the Tramp prefix. The automatic insertion applies only when default-directory is remote and the command is a Lisp function. This frees you from having to keep track of whether commands are Lisp function or external when supplying absolute file name arguments.

This is another attempt to solve an Eshell papercut. Suppose you execute

 cd /ssh:root@@example.com:
 find /etc -name "*gnu*"

and in reviewing the output of the command, you identify a file /etc/gnugnu that should be moved somewhere else. So you type

mv /etc/gnugnu /tmp

But since mv refers to the local Lisp function eshell/mv, not a remote shell command (unlike find(1)), to say this is to request that the local file /etc/gnugnu be moved into the local /tmp directory. After you enable eshell-elecslash, to then when you type the above mv invocation you will get the following input, which is what you intended:

mv /ssh:root@example.com:/etc/gnugnu /ssh:root@example.com:/tmp

imenu is now bound to M-g i globally

This is a useful command but everyone has to come up with their own binding for it. No longer.

New macro-writing macros, cl-with-gensyms and cl-once-only

These two macros are quite interesting. In the history of Common Lisp-style macros, these are the only two macro-writing macros that have emerged as essential tools for intermediate and advanced macrology. Most any other macro-writing macros are either project- or programmer-specific. In his book on Lisp macros Doug Hoyte proposes an alternative to defmacro, defmacro!, which is just the same as defmacro except that it builds in facilities equivalent to cl-with-gensyms and cl-once-only. I’ve long wanted to have these macros available in core Emacs Lisp, too, and now they are.

New package on GNU ELPA: transient-cycles

Many commands can be conceptualised as selecting an item from an ordered list or ring. Sometimes after running such a command, you find that the item selected is not the one you would have preferred, but the preferred item is nearby in the list. If the command has been augmented with transient cycling, then it finishes by setting a transient map with keys to move backwards and forwards in the list of items, so you can select a nearby item instead of the one the command selected. From the point of view of commands subsequent to the deactivation of the transient map, it is as though the first command actually selected the nearby item, not the one it really selected.

Protesilaos Stavrou helped me test the package and has written up some usage notes.

This is an idea I came up with in 2020, and refined in my init.el since then. This year I made it into a package.

Posted Thu 21 Apr 2022 20:43:28 UTC Tags:

I like to look at the Emacs subreddit and something I’ve noticed recently is people asking “should I start by writing my own Emacs config, or should I use this or that prepackaged one?” There is also this new config generator published by Philip Kaludercic. I find implicit in these the idea that one’s init.el is a singular product. To start using Emacs, newcomers seem to think, you need to couple it with a completed init.el, and so there is the question of writing your own or using one someone else has written. I think that an appropriate analogy is certain shell scripts. If you want to burn backups to DVDs you might download someone’s DVD burning shell script which tries to make that easy, or you might write your own. In both cases, you are likely to want to tweak the script after you’ve started using it, but there is nevertheless a discrete point at which you go from having part of a script and not being able to burn DVDs, to having a completed script and now being able to burn DVDs. Similarly, the idea that you can’t start using Emacs until you couple it with an init.el is like thinking that there is a process of producing or downloading an init.el, and only after that can you begin using Emacs.

This thinking makes sense if you’re developing one of the large Emacs configuration frameworks like Spacemacs or Doom Emacs. The people behind those projects are seeking to build something quite different from Emacs, using Emacs as a base, and for many people using that new, quite different thing is preferable to using Emacs. Then indeed, until you’ve finished developing your configuration framework’s init.el to a degree that you’re ready to release version 0.1 of your framework, you haven’t got something that’s ready to use. Like the shell script, there’s a discrete point after which you have a product, and there’s lots of labour that must precede it. (I think it’s pretty cool that Emacs is flexible enough to be something on its own and also a base for these projects.)

However, this temporal structure does not make sense to me when it comes to using just Emacs. I find the idea that one’s init.el is a singular product strange. In particular, my init.el is not something which transforms Emacs into something else, like the init.el that’s part of Doom Emacs does. It’s just a long collection of incrementally developed, largely unrelated hacks and tweaks. You could insist that it transforms default Emacs into Sean’s Emacs, but I think that misleadingly implies that there’s an overarching design and cohesion to my init.el, which just isn’t there – and it would be weird if it was there, because then I would be doing something more like the developers behind Doom Emacs. So if you’re not going to use one of the large configuration frameworks, then there is no task of “writing your own init.el” that stands before you. You just start using Emacs, and as part of that you’re going to write functions and rebind keys, etc., and your init.el is the file in which those changes are collected. The choice is not between writing your own init.el or downloading a prepackaged one. It’s between using Emacs, or using another product that has been built out of Emacs. The latter necessarily involves a completed init.el, but that’s an implementation detail.

I am very happy Kaludercic’s configuration generator has been made available, but I would be inclined to rename it. A new user of Emacs is likely to be overwhelmed with unintuitive defaults that have stuck around for mostly historical reasons. There are a lot of them, so it is a lot to ask of new users that they just identify the defaults that don’t suit them and add lines to their init.el to change those. When too many things are unintuitive, it’s hard to know where to start. Kaludercic’s configuration generator is a way to walk newcomers through the most significant defaults in a way that something structured like a reference manual would struggle to do. The result is some Lisp code, but I would prefer not to refer to that result as an Emacs configuration. It’s a series of configuration snippets that you can add to your Emacs configuration to help deal with the newcomer’s problem of too many unintuitive defaults.

I’m not sure it’s important to actually rename Kaludercic’s tool to something which says it’s a generator of configuration snippets rather than a generator of configurations. But I would like to challenge the idea that to start using Emacs you first need to couple it with a completed init.el. If you’re going to use Emacs, rather than Spacemacs or Doom Emacs, you can just start using it. If you find yourself butting up against a lot of unintuitive defaults, then you can use a walkthrough tool like Kaludercic’s to figure out what you need to add to your init.el to deal with those. But that is better understood as just more of the tweaking and customisation that Emacs users are always getting up to, not some prerequisite labour.

Posted Tue 26 Apr 2022 06:01:25 UTC Tags:

I am pleased to announce Consfigurator 1.0.0.

Reaching version 1.0.0 signifies that we will try to avoid API breaks. You should be able to use Consfigurator to manage production systems.

You can find the source at https://git.spwhitton.name/consfigurator for browsing online or git cloning.

Releases are made by publishing signed git tags to that repository. The tag for this release is named ‘v1.0.0’, and is signed by me.

On Debian/etc. systems, apt-get install cl-consfigurator

-8<-

Consfigurator is a system for declarative configuration management using Common Lisp. You can use it to configure hosts as root, deploy services as unprivileged users, build and deploy containers, install operating systems, produce disc images, and more. Some key advantages:

  • Apply configuration by transparently starting up another Lisp image on the machine to be configured, so that you can use the full power of Common Lisp to inspect and control the host.

  • Also define properties of hosts in a more restricted language, that of :POSIX properties, to configure machines, containers and user accounts where you can’t install Lisp. These properties can be applied using just an SSH or serial connection, but they can also be applied by remote Lisp images, enabling code reuse.

  • Flexibly chain and nest methods of connecting to hosts. For example, you could have Consfigurator SSH to a host, sudo to root, start up Lisp, use the setns(2) system call to enter a Linux container, and then deploy a service. Secrets, and other prerequisite data, are properly passed along.

  • Combine declarative semantics for defining hosts and services with a multiparadigmatic general-purpose programming language that won’t get in your way.

Declarative configuration management systems like Consfigurator and Propellor share a number of goals with projects like the GNU Guix System and NixOS. However, tools like Consfigurator and Propellor try to layer the power of declarative and reproducible configuration semantics on top of traditional, battle-tested UNIX system administration infrastructure like distro package managers, package archives and daemon configuration mechanisms, rather than seeking to replace any of those. Let’s get as much as we can out of all that existing distro policy-compliant work!

Posted Sat 30 Apr 2022 19:50:47 UTC