Arjen Wiersma

emacs

{{< admonition type=“note” >}} Originally posted on 2024-09-30 (Monday). It was updated in January of 2025. {{< /admonition >}}

I ❤️ to build software. I sadly do not have a lot of time next to my daily work to spend on my side projects, so I have to be disciplined in where I invest time. I wish I could spend endless amounts of time on exploring new technologies, but sadly I simply do not have that time. In writing this is sometimes referred to as “to kill your darlings”.

Sir Arthur Quiller-Couch wrote in his 1916 book On the Art of Writing: “If you here require a practical rule of me, I will present you with this: ‘Whenever you feel an impulse to perpetrate a piece of exceptionally fine writing, obey it—whole-heartedly—and delete it before sending your manuscript to press. Murder your darlings.’”

Luckily for me, I just finished my latest round of education, so I now do have time to spend on building some of the ideas that have been floating around in my head for the last 3 years. And I did start out writing stuff. Some in {{< backlink “rust” “Rust”>}}, some in Go and others in Clojure.

Like many programmers I love to explore new languages, I think you always learn something new from them. As Clojure really taught me about functional programming when all I knew was imperative languages. In the end, after having a summer of not working on my studies I have 0 projects completed, but I do have 4 versions of them.

So, I decided to step back and evaluate. I decided to kill my darlings of different programming languages and focus solely on Clojure again. Development in Clojure conforms to Rule 6 for me. While working out the problem I love the interactive build method. I actually like the parentheses, I know... weirdo me 🤗.

update 2025: during the holiday season I got the book Zero 2 Prod, which is a book about making Rust project production worthy. Experience I already have in Java and Clojure. This sparked rule 6 for me for the {{< backlink “rust” “Rust”>}} language again. The experience following the book has been quite smooth, but the real proof is, of course, creating something yourself. I know, I am like a {{< sidenote “puppy” >}}I love puppies!{{< /sidenote >}} puppy chasing his tail... Let's see where this goes.

From reading the book I already see lots of improvement for my Hed tool.

You might even remember that I used to do a live-streaming series in Clojure. I still don't have a lot of time to continue that one, but who knows... I might drop some videos later again.

Since the summer I have been somewhat involved in Biff, a rapid prototyping web framework in Clojure. It provides a set of sensible defaults to just get started, and it allows you to easily change all its bits. I have been building my latest project on top of it, which, with a bit of luck, might even make it to production.

#clojure #development #rust #emacs

This is a longer form article. I is relevant as of February 18th 2023. If the circumstances of my environment changes I will try to update this article to reflect the situation. You can find the full source code of my dotfiles on Github.

I like consistency and simplicity. I do not like to use many different tools to do different things, I rather spend my time learning to use a few tools very well then to follow the hype on the latest trend of tools for something we have been doing forever.

This philosophy I transfer to pretty much everything in life. I have been using the same laptop bag for ages, I have a small mechanical keyboard, and I run the same version of my OS on all my devices. One device for on the go, the other for at home. They look the same and act the same, courtesy of an Linux distribution called NixOS.

Below you will find 2 screenshots, one from my laptop, the other from my desktop. The only difference is the size of the screen.

{{< figure src=“/ox-hugo/desktop.png” caption=”Figure 1: My Linux desktop on my laptop” >}}

{{< figure src=“/ox-hugo/desktop-large.png” caption=”Figure 2: My Linux desktop on my desktop” >}}

NixOS {#nixos}

I use the NixOS distribution of Linux. NixOS is a wonderful operating system that works by declaring what you want your environment to be and then applying that declaration to the current version of the environment. That sounds difficult, but let me explain.

Suppose you have just installed a Linux distribution and you want to install the wonderful Emacs editor. In most distributions you will go to the package manager, search for Emacs and click on install. A few seconds later, Emacs is installed. With NixOS you edit a file that describes your environment, you will add a line to it saying that Emacs is part of your environment. When you have saved the file you will ask NixOS to create a new version of your environment, to do so it will install Emacs for you.

I say it will create a new version of your environment. This means there is an old version as well, right? Yes! NixOS has a concept of Generations. This means every change happens in its own version of the environment. So, if a change goes wrong, you just revert back to the previous version.

This sounds like a great deal of work, and it is. It is not for the new Linux user, that is for sure. If you spend some time learning NixOS I am sure you will be grateful for it. Just the other day I tried to use the wayland system on Linux, my configuration went horribly wrong and I was left with an unusable system. I rebooted the machine, selected the previous generation, and I was back where I started before the change. It is that useful!

As I share my configuration over multiple machines I split up the configuration into a machine specific version to my desktop, laptop, and the things that should run on both:

The shared configuration contains all the juice, it sets up the graphical user interface, creates users and assigns to groups. This means that when you run this configuration you will end up in a very barren i3 tiling window manager. More on that later.

Most of my applications are courtesy of something called home-manager. This is a user-space application that allows for easy changes to the environment. As none of these changes can actually wreck the environment I kept them outside of the default NixOS configuration.

My home-manager configuration takes care of installing all the user-space tools that I use. It also sets up my shell and configures the Emacs daemon.

You might wonder, do you create a configuration file every time you need a tool? No! When I just need a one-off tool I use something called nix-shell. In the screenshots above you will notice that I run neo-fetch. This program is not part of my normal system as I only use it for screenshots as the one above. Within a terminal I run it as follows: nix-shell -p neofetch --run neofetch. This will temporarily install neo-fetch and run it. Afterwards it can be cleaned up. I also do this for most of the tools, such as unzip. I only install then when I need them. This keeps everything that is installed very clean.

You might also notice that there are not programming language toolchains in my configuration. That is correct. When I have a programming project I use something called direnv, see the direnv webpage for some background.

Whenever I start a new programming project I run the following command in the project root: nix --extra-experimental-features "nix-command flakes" flake new -t github:nix-community/nix-direnv .. This will create a flake.nix file in which I can declare what this project needs as dependencies. As the rest of my environment is extremely clean, I will need to specify precisely what is needed. Take the listing below, it is part of a programming project in which I use Rust, Golang, Python and Java. Whenever I move into this project, all the tools will be installed. This also means that it works exactly the same on every single system where I use this setup.

{
  description = "A basic flake with a shell";
  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
  inputs.flake-utils.url = "github:numtide/flake-utils";

  outputs = { self, nixpkgs, flake-utils }:
    flake-utils.lib.eachDefaultSystem (system: let
      pkgs = nixpkgs.legacyPackages.${system};
    in {
      devShells.default = pkgs.mkShell {
        packages = with pkgs; [
          pkg-config
          openssl.dev
          cargo
          rustc
          rustfmt
          clippy
          rust-analyzer
          aoc-cli
          go
          gopls
          gotools
          govulncheck
          pkgs.jdk
          pkgs.jdt-language-server
          pkgs.python311
        ];
        # Environment variable specifying the plugin directory of
        # the language server 'jdtls'.
        JDTLS_PATH = "${pkgs.jdt-language-server}/share/java";
      };
    });
}
Code Snippet 1: A nix-direnv declaration for a polyglot programming project

This might seem like a hassle. It is true, it is more work then just installing Golang on Ubuntu and “just having it”. But once you use multiple systems or work together in groups you will start appreciating it, trust me.

i3 {#i3}

As I like simplicity I tend to not use elaborate windowing environments, such as Gnome or KDE. I try them out every once in a while, but I also go back to i3. Back in the day I ran enlightenment, but now I have been using i3 WM for quite some years. My configuration is quite mature and I generally only change it when I want to add a new tool to my daily use, or when tools get good updates such as polybar. The configuration is part of my dotfiles.

When I boot my system all I have is a top bar that contains the following information:

  • 💻 Active workspaces (each has its own icon and use)
  • 💾 Current fill state of my disks
  • 🛡️ VPN status
  • 🔊 Sound and its volume percentage
  • 🛜 Wifi state (laptop only)
  • 🔋 Battery state (laptop only)
  • ⏰ Time
  • 📥 Tray icons (flameshot, bluetooth and nextcloud)

That is it. After all those years working with computers, that is all I really need. If I could I would write a toggle for the bar as well, to only show up when needed. The very appealing thing about i3 is its tiling feature. I will never have windows that overlap. Everything is neatly ordered in workspaces and within workspaces in columns or rows. As I create dedicated workspaces everything has a specific place:

  1. Terminal (alacritty with tmux)
  2. Emacs
  3. Virtual Machines
  4. Firefox
  5. Chrome

From workspace 6 on I consider them “throw-away” workspaces. The things I will store there will be used only shortly. The exception is workspace 10 (or 0). This contains my Spotify.

To launch applications I use something called Rofi. It is a window switcher, application launcher and menu replacement tool. It is very easy to customize and you can make it exactly what you want. My configuration is available on github.

{{< figure src=“/ox-hugo/rofi.png” caption=”Figure 3: Rofi launching applications in i3” >}}

You can configure your environment exactly as you want. Take a look at r/unixporn for some more extreme versions of customized desktops.

#emacs #development #writing

Where to begin... {#where-to-begin-dot-dot-dot}

I just watched David Wilson's talk called M-x forever – why Emacs will outlast text editor trends. He gave this talk at EmacsConf 2021 which is a conference dedicated to Emacs. The talk made me reflect on my use of Emacs over the last years and then I realized that this year will mark 22 years that Emacs and I have been together. This (probably too long) article reflects on those years and dives into my use of Emacs.

First Contact {#first-contact}

Back in 1998 I was planning a move to the US. I had just finished my first professional programming gig writing a RAS Dialer for Freeler internet, the first “free” internet provider in The Netherlands. Pretty much everyone in The Netherlands (who had a modem and tried Freeler) was using my software to connect to the service. I was programming in various languages at the time, from Delphi (for the dialer) to Perl (yes, it was popular then!). This is when I first started playing with Linux and editors like Vi and Emacs.

When I moved to the US (San Francisco) I started working for Personify, a company focused on building an analytical platform for e-commerce sites. I started working in a small team which dealt with webserver logfile parsing. That sounds like a great job for Perl, right? My mentor worked in the same team and he guided me through the hectic time of working at a pre-2000 startup in Silicon Valley.

Picking Emacs for life {#picking-emacs-for-life}

As I was working closely with my mentor I started picking up on things he did. He was (and probably still is) a wizard behind the keyboard. He used Emacs as his editor. Naturally I gave it a try, but found it hard to really get productive with it and so I kept switching back and forth between Vi, Emacs and several other editors. It always amazed me how quick he was in getting stuff done. One day, my mentor told me to stop and take the time to learn my tools.

His reasoning was that when you learn your tool well it will not impede you from completing your task. You will be able to complete it as fast as you can simply because the tool becomes an extension of your thought process and it is possible to leverage the features it has to the benefit of the task at hand. It did not matter which tool I would choose, but pick one and learn it well. I accepted the challenge of working with a single tool for 30 days and see if my work speed would improve.

I chose to use Emacs, as it allowed me to look at the things he did. The availability of information on how to best use software was not as abundant as it is now. Now you can look up anything on YouTube or any blog, back then there was the Emacs Manual and other users that I ran into during technical meetups.

Now we are 22 years later and I still use Emacs everyday for pretty much anything. It has been with me through transitioning from Windows, to macOS and since 2017 full time on Linux. It came with me when moving between continents (back to Europe) and through various jobs at different companies.

Cheating on Emacs {#cheating-on-emacs}

I too have been tempted by new fashioned shiny tools that promised to be the next big thing in Editing. I even switched to Vim for a little while. The thing is, I always came back to Emacs. I think this is mostly due to the fact that new tools have something spectacular and then you want to adjust it and you find you can not do it to the degree that Emacs allows you to change the way it works for you.

While working with programming languages like Java the lure of IDEs has been quite tempting as well. In teams where pretty much everyone uses IntelliJ IDEA you stand out when just opening up Emacs. It often results in quite some interesting discussions as to what “makes a good developer”. Some people are quite unreasonable and think an IDE makes the developer, but I greatly disagree on that topic.

Serendipity {#serendipity}

Over the years there have been several serendipitous moments in the Emacs community for me. I will pick out 2:

  • I started sponsoring Jonas Bernoulli in 2021 for his work on Magit and back in 2012 he sent in a patch for my worklog package which I only found out while preparing this article and looking at the logs of my various projects.
  • I was referenced in a talk by Martin Clausen. He gave a presentation on a Clojure project and in the conclusion he talked about knowing your tools. We had been doing some live streams together working on Clojure projects and while he talked about using your tools effectively he casually dropped a “then you need to talk to this guy” and pointed my out in the crowd.

Giving back {#giving-back}

A YouTube series {#a-youtube-series}

In 2015/2016 I started working a little less and found time to do a Friday morning live-coding series. It featured me learning to write Clojure by building various projects. In the videos I, of course, used Emacs in pretty much every way possible.

I also created a series of videos called Productive Emacs in which I highlighted useful packages (focused on Clojure development). They were a big hit (at least I think so) and connected me to wonderful people like Mike Zamansky.

Writing packages {#writing-packages}

In my time with Emacs I have written and maintained some code as well. Most notably in 2003 I took over a package for tracking time (worklog) as I had a job where I need to track my time and naturally I chose to do this in Emacs.

I also have a grey theme out on melpa that is being used by several people. I always enjoy getting responses from the community when they like the work that has gone into making things.

Whenever I can I will post about some snippet of emacs-lisp I have written, such as my Advent of Code helper function. It retrieves the input for a puzzle during December and puts it into a file. It then prints the puzzle description and allows you to quickly get going. It is awesome to use your editor to make your life easier!

Providing patches {#providing-patches}

One of the most meaningful things in this entire ecosystem is to give back to the projects when you can. Whenever I run into a bug or oddity I will try and fix it. When my skill-set allows it I will send in a patch or documentation update to show my appreciation for the work people do. This entire community runs on people spending their free time working on code that helps many of us.

My configuration {#my-configuration}

Recently there was a twitter exchange with Bozhidat Batsov in which Stephen A. Ramsey calls Emacs a lifestyle choice as someone makes the remark that the people they know have been configuring Emacs as long as they have been using it.

{{< figure src=“/ox-hugo/twitter.png” >}}

I too am one of those that is always tinkering with my configuration. I think it is part of having such an extensible editor and using it constantly for everything. The community keeps making amazing packages that provide entire new dimensions to the use of Emacs (hi use-package, Projectile, Counsel, Ivy, Org-Roam, Company, and many many more) that it only makes sense to be critical and try out anything that seems useful and an improvement. The ease with which it is possible to add new functions to Emacs is amazing.

I said ease, but for new users it can be quite daunting to start with a configuration. That is why projects like Doom Emacs and Spacemacs are so important. I have tried both and I think the work done in them is amazing! I often go into their repositories and check out the packages they use and take snippets from their configuration.

A few years back I converted my pre-2000 init.el to a literal configuration using org-mode and babel. This allows you to treat your configuration as documentation and annotate it using the wonderful org-mode. Sadly I sometimes lack the discipline to properly annotate my configuration like Protesilaos does.

You can still check out my configuration in its repository. The wonderful thing of having a configuration in the open is that many people take from it. It has resulted in various connections around the globe that to this day exchange ideas and experiments using my configuration as a base.

Favorite packages {#favorite-packages}

So after all these years, there must be some favorite packages. Yes there are. It is important to note that I use Emacs for pretty much everything in my day-to-day live; from making presentations and documents in LaTeX, keeping notes and scheduling in org-mode, writing code in languages such as Java, C, Rust and Clojure and reading my Email. The list below is in no means a complete reference, but it gives a sense of what I do in my day-to-day life using Emacs.

Org-mode and Org-Roam {#org-mode-and-org-roam}

I think org mode can be seen as one of the most influential packages in the Emacs ecosystem. For me it has taken over most of my note-taking, document processing needs.

Lets start with my daily tasks. As a teacher I have many daily things to keep track of, from work that needs reviewing, classes that need preparing and the grading of papers. To keep track of everything and not loose sight of anything I have implemented a Getting Things Done (GTD) workflow.

Anything that lives in a browser is connected to my GTD system using org-protocol, anything that lives in Emacs is captured using capture templates. This means that anything that will take me more then 2 minutes to take care of will go into my GTD system and will be filed away with scheduling dates, deadlines and notes on the task itself. In my archive I have cleared over 10000 tasks in the current version of the system.

The article you are reading now is also an Org document. It lives in an archive called website and has an Emacs build script that generates this website in a Github Action.

As an extension to org-mode I use org-roam to keep track of knowledge snippets. This can be anything from development tricks, hacking methodology, background information on some technology to grading notes on papers. All this knowledge is captured in my org-mode archive and is accessible through a series of links in topic covering notes.

{{< figure src=“/ox-hugo/org-mode.png” >}}

Mu4e {#mu4e}

The use of org-mode continues into my Email. All my mail is read through mu4e. It seamlessly ties into my GTD workflow, its editing builds on the document processing I already do with org-mode and using various modules I can even read horrible HTML emails.

Most importantly, captures I have made from email into the GTD system will link directly to the email itself, so it is as if the system is one concise whole, making it very productive.

Magit {#magit}

As I put everything I find of value into git repositories I tend to use Magit quite a lot during the day. It has totally redefined how Emacs should do interfaces for tools and has shown the world how a good git interface can integrate into the editor. It puts anything else to shame in my opinion.

{{< figure src=“/ox-hugo/magit.png” >}}

Which-Key {#which-key}

A few years back I added which-key to my configuration after reading an article on discoverability of features. It is an amazing extension that allows you to press a key combination and it will pop-up a list of all following combinations that can be accessed from there. This greatly helps when you are trying to remember that one key sequence for that feature you don't use that often.

{{< figure src=“/ox-hugo/which-key.png” >}}

LSP / eglot {#lsp-eglot}

With the introduction of VSCode to the world Microsoft actually made something useful as well, the Language Server Protocol (LSP). The LSP is the thing that makes VSCode such a hit, it separated the editor frontend from the language understanding backend.

Emacs now has 2 LSP infrastructures, lsp-mode and eglot. I have tried both and eventually settled on using eglot for my daily programming tasks.

The lsp-mode package is the most extensive and feature loaded of the two, it also means it has a lot of configuration to tweak it to your liking. The package also takes care of installing the needed language server for your language and sets it up automatically.

On the other hand, eglot, is bare bones and configuration-less. Just drop it in and it works after manually installing a language server. It is simple and unobtrusive, and as I do a lot of screen sharing while coding I chose it over lsp-mode.

Both packages give Emacs an IDE set of features, such as context sensitive completion, formatting of code, refactoring, organization of imports and the execution of code actions on errors and warnings. It has redefined Emacs for me when it comes to writing code.

{{< figure src=“/ox-hugo/lsp.png” >}}

Projectile {#projectile}

The last of my favorite packages is projectile. As the name implies it is a tool to work with projects. As I said, I maintain a lot git repositories for anything I deem of importance. Projectile interacts with these git projects and allows you to quickly open files in the project, search them, run commands on them, switch between test and implementation code and so on.

As a productivity tool projectile makes code editing that extra bit enjoyable.

Helpful resources {#helpful-resources}

As the community is large there are several resources I keep track of to find new features, applications and packages.

Mastering Emacs : a book and website with cool and useful tricks in Emacs.

Emacs News by Sacha Chua : a weekly digest that summarizes the week of Emacs news, a great resource to read with a cup of coffee.

Emacs Reddit : the Emacs sub-reddit is extremely wonderful when it comes to sharing information. The community is great and supportive (who would say this about Reddit, right?)

YouTube : the following channels offer a lot of information; Protesilaos and System Crafters.

Closing thoughts {#closing-thoughts}

Emacs and I have been together for 22 years now and I don't see it changing anytime soon. Emacs itself is getting better and better with initiatives such as native-compilation and the Pure GTK patches. Its package ecosystem is in excellent condition and packages such as org-mode and eglot / lsp-mode make even the most demanding programming languages a joy to work with in Emacs.

Here's to another 22 years Emacs!

#writing #emacs