Literate Emacs Configurations

I'd like to present some thoughts on literate configurations. This is one of those interesting bits in the Emacs configuration space that shows up from time to time. I'm in the “I don't do it this way” camp and I'll present some thoughts on why that is. For those of you who choose to be in the “I do it!” camp, well, that's fantastic! The great thing about Emacs is doing it “your” way, whatever “way” that is.

What is it anyway?

Donald Knuth wrote, “Literate programming” is a methodology that combines a programming language with a documentation language, thereby making programs more robust, more portable, more easily maintained, and arguably more fun to write than programs that are written only in a high-level language. The main idea is to treat a program as a piece of literature, addressed to human beings rather than to a computer. The program is also viewed as a hypertext document, rather like the World Wide Web.”1

In the sense of your Emacs configuration, it is basically writing everything in some markup language with executable code snippets woven through the prose documenting your decisions. The most common markup language in this context is the venerable Org mode. It is well supported, has a huge list of language integrations, including Emacs Lisp (of course), and is arguably one of the “killer features” available to Emacs users. It's also a very simple markup language with very little in the way of actual syntax and it exports to many different presentation formats. Forges like GitHub and GitLab will render Org files natively in the same way they render Markdown files. This make it very useful for influencers like Protesilaos Stavrou2 (also known as “Prot”) among others to host their Emacs configuration where people can read them, get some context on why or how the configuration works, and still see the code. David Wilson in a recent livestream3 converted his configuration back to a literate style and mentioned some of the advantages being:

  • Having things nicely organized in a single large Org file.
  • Easy to generate a website from the configuration.
  • Easy to describe why you do certain things in your configuration.

Why its a challenge

In the same video, David goes on to talk about why he stopped using it for a while:

  • He got tired of having to re-tangle his configuration files every time he synced his dot files between machines.
  • If you tangle (ie. generate) all the code files in your “dot files” folder and then symlink those to your home folder, you either have to ignore all the generated files or check them in with your Org file, which means lots of diffs when you re-tangle your Org file after each change.
  • There is the possibility you might change one of the generated files and forget to update the Org file, which would then overwrite your changes when you re-tangle your configuration.

Another challenge, it does take time to tangle your configuration, especially if yours is on the longish side. Do that every time you save your configuration and Emacs will seem to lag a few seconds as it tangles things.

Why I'm a “don't” person

Keeping in mind, these are my opinions, here are some reasons why I prefer not to use a literate configuration:

  • It's a hassle. Keeping things synced, both on the filesystem as well as in version control is just more than I prefer to manage.
  • It's easier to not use a literate configuration. No extra configuration, no slow down tangling things, no extra files to either ignore or version frequently, etc.
  • Documenting things can be done just as easily with code comments.
  • Organizing your configuration is a matter of discipline not markup. Using Org mode does not improve how well organized your code is if you don't discipline yourself to keep things organized. It's just extra syntax. The same is true of keeping your configuration in “module” files. Its only more organized if you maintain the discipline of keeping it organized.
  • I don't need to generate a website from my configuration. Anyone who wants to read it can do so on GitLab, which will render the Emacs Lisp code and comments just fine.

Outline modes – outline-minor-mode and allout-mode

There was a suggestion on David's stream regarding using allout-mode, one of the outline modes built-in to Emacs. I've used this mode in the past, but I usually end up back in Org mode because of all the features that project brings to the table.

allout-mode is a fairly simple outliner though and pretty easy to get into if you need a nice outlining tool. And by simple I mean, really simple. No frills. It outlines and that's about it. The default keyboard prefix is C-c SPACE which can be a bit to type, but once you get used to it, its not bad. That said, changing it to something like s-SPACE might make it more approachable.

Using the built-in outline modes (outline-minor-mode or allout-mode) seem to be a nice alternative. In fact, reading through the documentation on Comment Tips4, using three ;;; should start on the left column and are already considered headers in Outline mode, thus using them and turning on outline-minor-mode and you instantly get navigation keyboarding, the ability to collapse sections, etc. and you can document your code in the same way you would with Org mode using only the Emacs Lisp syntax, and no tangling required.

allout-mode adds additional flavor to those ;;; comments, so you only write ;;; plus the header level needed and you also get code navigation keyboarding, the ability to collapse sections, etc and you still only document your code with Emacs Lisp syntax and no tangling required. allout-mode also should allow generating your configuration as LaTeX, but there is a bug in my case which I'll try tracking down at some point. I don't need it as I don't need to generate my configuration in any other language than the default Emacs Lisp.

Getting started with allout-mode

I'll show an example here of how to get started using allout-mode. Using outline-minor-mode doesn't require anything, per se, but you might like to use something like this to turn it on in your configuration:

M-x add-file-local-variable-prop-line RET eval RET (outline-minor-mode 1) RET

This would assume you are just using multiple semi-colon's as described in the Emacs Lisp Comment Tips4. To use allout-mode requires just a little more setup and then some updates to those lines beginning with ;;;.

So, lets start with your init.el file.

  • M-x add-file-local-variable-prop-line RET mode RET emacs-lisp RET
  • M-x add-file-local-variable-prop-line RET eval RET (allout-mode 1) RET
  • M-x add-file-local-variable RET eval RET (allout-expose-topic '(0 :)) RET
  • M-x revert-buffer RET

The list item in that list sets the variables and executes the code, you'll get the standard Emacs warning about this, so you can choose to say 'y' to run it once. Other options exist to persist that decision as well. That's all you need to get things started. You should also customize the allout-auto-activation variable and set it to t, at least you should according to the various docstrings in allout.el.

To proceed from there, you add ;;;_* to major headings. A sub-heading can be added with ;;;_ * (Note the extra space). See the allout.el source to see a more detailed example. In my case, I generally use just these, with a couple of exceptions.

allout-mode allows you to set your bullets to something that means something semantically. For example ;;;_ ? might indicate a question (like, “do I need this section?”), ;;;_ ^ might indicate this section refers to the section above, for example if you are setting up IDE rules, you might have generic IDE configuration first, then sub-topics for each programming language:

;;;_* IDE
;;; This section configures eglot as my language server
(require 'crafted-ide-config)           ; Crafted Emacs module
(with-eval-after-load 'crafted-ide-config
  (crafted-ide-configure-tree-sitter '(latex python)))

;;;_ ^ Prog mode hooks
(with-eval-after-load "prog-mode"
  (keymap-set prog-mode-map "C-c e n" #'flymake-goto-next-error)
  (keymap-set prog-mode-map "C-c e p" #'flymake-goto-prev-error))

;;;_ ^ Python
(require 'my-ide-python)                ; My custom Python module

Example init.el file

To complete this blog post, here is the Crafted Emacs example init.el5 using allout-mode. To complete the requirement as mentioned by Mr. Knuth1, you should be able to export this to LaTeX, although, for me there seems to be a bug.

;;; init.el --- Crafted Emacs Base Example -*- mode: emacs-lisp; lexical-binding: t; eval: (allout-mode 1); -*-

;; Copyright (C) 2023
;; SPDX-License-Identifier: MIT

;; Author: System Crafters Community

;;; Commentary:

;; Base example init.el (extended from the info file).
;; Basic example of loading a module.

;;; Code:

;;;_* Initial phase

;;;_ ^ Custom File
;;; Load the custom file if it exists.  Among other settings, this will
;;; have the list `package-selected-packages', so we need to load that
;;; before adding more packages.  The value of the `custom-file'
;;; variable must be set appropriately, by default the value is nil.
;;; This can be done here, or in the early-init.el file.
(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
(when (and custom-file
           (file-exists-p custom-file))
  (load custom-file nil :nomessage))

;;;_ ^ Bootstrap crafted-emacs
;;; Bootstrap crafted-emacs in init.el
;;; Adds crafted-emacs modules to the `load-path', sets up a module
;;; writing template, sets the `crafted-emacs-home' variable.
(load (expand-file-name "../../modules/crafted-init-config"
;;; Adjust the path (e.g. to an absolute one)
;;; depending where you cloned Crafted Emacs.
;;; (load "/path/to/crafted-emacs/modules/crafted-init-config")

;;;_* Packages phase
;;; Collect list of packages to install. Do not just blindly copy this
;;; list, instead think about what you need and see if there is a
;;; module which provides the list of packages needed. This phase is
;;; not needed if manage the installed packages with Guix or Nix. It
;;; is also not needed if you do not need Crafted Emacs to install
;;; packages for a module, for example,
;;; `crafted-speedbar-config' does not require any packages to
;;; be installed.

;;; Add package definitions for completion packages
;;; to `package-selected-packages'.
(require 'crafted-completion-packages)

;;;_ ^ Manually select "ef-themes" package
(add-to-list 'package-selected-packages 'ef-themes)

;;;_ ^ Install the packages listed in the `package-selected-packages' list.
(package-install-selected-packages :noconfirm)

;;;_* Configuration phase
;;; Some example modules to configure Emacs. Don't blindly copy these,
;;; they are here for example purposes. Find the modules which work
;;; for you.

;;;_ ^ Completions
;;; Load configuration for the completion module
(require 'crafted-completion-config)

;;;_ ^ Crafted Emacs configuration
;;; Some more configurations that don't require packages to be installed
(require 'crafted-defaults-config)
(require 'crafted-startup-config)

;;;_* Optional configuration

;;;_ ^ Profile emacs startup
(defun ce-base-example/display-startup-time ()
  "Display the startup time after Emacs is fully initialized."
  (message "Crafted Emacs loaded in %s."
(add-hook 'emacs-startup-hook #'ce-base-example/display-startup-time)

;;;_ ^ Set default coding system (especially for Windows)
(set-default-coding-systems 'utf-8)

(provide 'init)

;;;_* Local emacs vars.
;;Local variables:
;;allout-layout: (0 :)
;;eval: (allout-expose-topic allout-layout)

;;; init.el ends here

Final thoughts

I'm generally not a fan of literate configuration. The idea isn't a bad one, it's just not for me. I don't see the point in writing in two different languages for this particular use-case, and there are simpler ways to get the same effect. I do think literate programming has it's place, for example, see this video from a recent meetup on the subject. I encourage you to try it both ways though, and to find the one which makes sense to you in your configuration.

Happy Crafting!






5 Yep, shameless plug.

Happy New Year

Hello Crafters, welcome to 2024! Hope everyone had a wonderful and safe holiday season, and now that is behind us time to get back to work, right!?!!

Crafted Emacs Update

Since the release of Crafted Emacs v2 last year, things have been a bit quite on the development front. Since the last time I gave an update there have been a few improvements:

  • Usage of eglot-ensure was changed to an “opt-in” configuration. This change included checking to see if the mode was actually available on the system before adding eglot-ensure to a hook. This makes a lot more sense now, not everyone will have all the programming modes installed, much less have the desire to turn on eglot for all of them.
  • There was a bug in the docs after the release, I missed removing a reference to the development branch. Thanks to @bird-dancer for noticing and providing the PR for the fix!
  • Another bug related to loading the custom-file was found by @jvalleroy, also thanks for the PR to fix it!
  • @mgmarlow has been fairly active, providing discussion, the patch for eglot-ensure mentioned above, and an example configuration for the rust programming language. Thank you!!
  • I changed our tree-sitter configuration, originally we tried to install every ts grammar by default, but a change to the tree-sit-auto broke it. Reviewing how we were using that package, it seemed we had been approaching the problem backwards all along, so it is also an “opt-in” rather than an “opt-out” configuration.

Example: Adding the Go language

There have been frequent questions around providing one language mode or another, or all of them, over the course of the project. With Crafted Emacs v2, we moved to more general modules, which a user could use as building blocks for extending Crafted Emacs as they see fit. You can read more of the language module discussion here if you wish.

Currently, we have the example of adding rust as a language module, I'll walk through the code I used recently to extend my own configuration for the Go language.

The initial process

I took a little time to search the internet for others who had configured Emacs for Go development. I also took some time to review the existing go-mode.el, which originally shipped with Go, but later was rewritten by Dominik Honnef, see the GitHub page for more information.

Updating my init.el configuration

I need to make several changes in my base configuration file:

  • I add to the list of packages which need to be installed
  • Turn on the tree-sitter mode for Go

Adding the needed packages

I need a couple of packages installed as Emacs doesn't know about Go out of the box. I add these lines early in my init.el file:

(add-to-list 'package-selected-packages 'go-eldoc)
(add-to-list 'package-selected-packages 'go-mode)

I evaluate these lines, then evaluate this (package-install-selected-packages :noconfirm) to get the packages installed.

Update treesit-auto to install go-ts-mode

I like to use tree-sitter modes, so I add go to the list I already have. Mine now looks like this (yours may be different):

(with-eval-after-load 'crafted-ide-config (crafted-ide-configure-tree-sitter '(go java javascript latex markdown python typescript)))

Putting together a custom module

I start by building on the work in crafted-ide-config:

(require 'crafted-ide-config nil :noerror)

This way, I get to take advantage of the work already done to setup eglot, tree-sitter modes, editorconfig, etc.

Setup project.el

We need to tell project.el about Go projects. project.el does not know about GOPATH or go modules, so we need to tell it how to find the go.mod file. This also enables eglot to work as it uses project.el to find project assets.

(require 'project)

(defun project-find-go-module (dir)
  (when-let ((root (locate-dominating-file dir "go.mod")))
    (cons 'go-module root)))

(cl-defmethod project-root ((project (head go-module)))
  (cdr project))

(add-hook 'project-find-functions #'project-find-go-module)

Setup hooks

Now, we need to setup some hooks to turn things on. I setup both go-mode and go-ts-mode here, but you may choose whichever. That said, go-mode and go-ts-mode are not equal. There are features provided in go-mode that are not available in the ts version. This lack of parity is a bit unfortunate, and exists for other language modes as well. Usually, the ts modes is much less fully featured.

You can reasonably pick one of the modes in the example below and leave the other one out, or just include both if you aren't sure, no harm done.

On the hooks, you'll see I order them using numbers. This is because I want to make sure flymake is loaded before the call to flymake-show-buffer-diagnostics.

For the before-save-hook I make sure it is first in the list (a negative number makes it earlier in the list), but I also make it buffer local, rather than a global setting. So the call to eglot-format-buffer only gets called on go buffers.

(require 'go-mode)
(require 'eglot)

;; these lines are only needed if you choose to use go-mode
(add-hook 'go-mode-hook 'flymake-mode 8)
(add-hook 'go-mode-hook 'flymake-show-buffer-diagnostics 9)
(add-hook 'go-mode-hook 'eglot-ensure 10)

;; these lines are only needed if you choose to use go-ts-mode.
(add-hook 'go-ts-mode-hook 'flymake-mode 8)
(add-hook 'go-ts-mode-hook 'flymake-show-buffer-diagnostics 9)
(add-hook 'go-ts-mode-hook 'eglot-ensure 10)

;; Optional: install eglot-format-buffer as a save hook.
;; The depth of -10 places this before eglot's willSave notification,
;; so that that notification reports the actual contents that will be saved.
(defun eglot-format-buffer-on-save ()
  (add-hook 'before-save-hook #'eglot-format-buffer -10 t))
(add-hook 'go-mode-hook #'eglot-format-buffer-on-save)
(add-hook 'go-ts-mode-hook #'eglot-format-buffer-on-save)

Setup gopls

Configuring gopls when using eglot happens on the eglot-workspace-configuration which can be set globally in your Emacs configuration or in a .dir-locals.el file in your project. I choose to set it in my Emacs configuration. For more configuration options for gopls see here

(setq-default eglot-workspace-configuration
              '((:gopls .
                        ((staticcheck . t)
                         (matcher . "CaseSensitive")))))

Setup flymake window height

And, finally, as I want the diagnostics window to popup when I open a Go file, I configure the window height to my preference. This sets the window height to 10 lines at the bottom of the frame so I can read the diagnostics as they popup. Recall, I add the function to open the flymake diagnostics window to the hook go-mode and go-ts-mode hooks.

(add-to-list 'display-buffer-alist
             '("^\\*Flymake diagnostics"
               (display-buffer-reuse-window display-buffer-pop-up-window)
               (window-height . 10)))

Updating my configuration

I put all that code in a file located in the custom-modules folder in my user-emacs-directory, which in my case is: $HOME/.emacs.d/custom-modules/my-ide-go.el. Crafted Emacs automatically puts the $HOME/.emacs.d/custom-modules onto the Emacs load-path list, so all that remains is to add the appropriate require in my init.el file:

(require 'my-ide-go)

Now, I can restart Emacs or just evaluate that one line and my Go configuration is installed!

Tags: #emacs

It's been slow… which is a good thing… I think

It's been a surprisingly slow month in Crafted Emacs land. After the release of V2, I sorta expected a flurry of messages or issues related to transitioning to the new release. None of that happened. Naturally, I'm surprised. I'm hoping it means we did a good job with Crafted Emacs on this release.

An interesting discussion…

There was a discussion started on creating per-language modules. The summary is basically we had tried something like that in Crafted Emacs V1, but there are issues trying to do that going forward. We opted to not try to provide per-language modules deliberately while providing a (hopefully) richer crafted-ide module to provide some baseline starting point for most languages. There are gotchas here as noted in the discussion, one of which happens to be the discrepancy between features provided by language mode and the corresponding tree sitter enabled module (ala python-mode vs python-ts-mode). There was a good suggestion of providing example configurations for language modules which could reside in the examples folder. This would be a welcome addition, so if you have one, perhaps consider submitting a PR. Common requests are for Python, Javascript, Rust, Go, and C/C++.

Odd behavior when loading a theme…

There is an odd message that might show up for you from time to time, it looks something like invalid function '(("gnu" . 99) ...). It might say something slightly different after the “invalid function” bit, but looking closely, it appears to be a value set in the custom-set-variables call usually held in the custom.el file. There is a related discussion on the Emacs mailing list here with a very detailed description of what's going on. In Crafted Emacs, we load the custom.el (assuming it exists) very early in the initialization process. There are several reasons for this, we want to load any customizations the user saved through the “Easy Customization” facilities provided out of the box in Emacs; having the values pre-loaded causes no harm when using customize-set-variable; the user could use the custom.el file as their base configuration on a different machine if they needed to spin things up quickly, but didn't have access to their entire Emacs configuration – for example on remote hosts. However, the side-effect is the values get marked as “CHANGED outside Customize”. Which is a surprise since we deliberately use the forms from the built-in customization system. We also save those values at the end of the initialization process to enable the behaviors above. What doesn't happen automatically though, when we use customize-set-variable and later customize-save-customized, neither form causes the values to be loaded again. Even when the values haven't changed from what was saved the last time Emacs was started and this time, the values get marked as “CHANGED”. I thought about calling customize-save-variable which sets the value and writes it to the custom.el file, but that would affect startup time. Not everyone cares about that – those of us who start Emacs once and then run it basically indefinitely don't care so much about startup time. Some people do, and I like for things to start snappily as well. The end result is we load the custom.el file a second time at the end of the initialization process so the values are marked as “SET and SAVED”. Doing so, I haven't been able to get the “invalid function …” error when I decide to change my theme in the middle of a running session.

Yep, that's me optimizing for a corner case. The only time a user would run into that error was when they tried to load a theme after Emacs had already started and after setting some variables with customize-set-variable, but not loading the changes from the custom-set-variables form. Even then, it wasn't a guarantee you'd hit it. Sometimes I had to call load-theme or M-x load-theme several times before I'd hit the error. It's pretty elusive.

And that is the only change to Crafted Emacs since the release.

A non-sequitur topic change…

December is nearly here, and this time of the year in most parts of the world begins celebrations of different holidays. I may (or maybe I won't) get another post out later in December, but in case I don't, on behalf of the Crafted Emacs team we wish you a happy and safe holiday season.

Happy Crafting!

Tags: #emacs

Crafted Emacs V2 Announcement

Crafted Emacs V2 is released! The current master branch is now updated to reflect the new approach to assisting getting your configuration up to speed. Info files exist, so feel free to C-h i m Crafted Emacs RET to read the manual from the comfort of Emacs!

There is a transition guide:

See the v1 to v2 transition guide

This is a breaking change for anyone using Crafted Emacs V1. For those wishing to track the former version of Crafted Emacs, that can be done by following the craftedv1 branch, which was the former master branch. This version will likely not see much in the way of maintenance, and is provided for legacy purposes and to assist those who may need to take some time to transition to v2.

The branches used during development of v2 have been deleted. The new master branch is the currently supported and official release of Crafted Emacs. Additionally, many issues have been closed. The ones remaining exist because they were topics we either planned for future release or document some decision.

If you have questions, feel free to create issues (best approach) or see if one of the maintainers is in the Emacs – System Crafters channel.

Happy Crafting!

Tags: #emacs

Crafted Emacs V2 Pre-release Announcement

After the RC1 announcement last month, we have had a flurry of small tasks and things to fix. Those are now done and we are ready to release Crafted Emacs V2.

We will be releasing Crafted Emacs V2 on Friday, 20 October 2023.

This will be a breaking change for anyone using Crafted Emacs V1 (the current version from the master branch). We will be moving branches around in git, which will likely add to the confusion, but after Friday this week, there will be a craftedv1 branch for those who wish to stay with the starter kit version of Crafted Emacs. This version will likely not see much in the way of maintenance, and is provided for legacy purposes and to assist those who may need to take some time to transition to v2.

After Friday, the branches used during development of v2 will cease to exist. Thus if you are tracking the alpha, beta, or RC1 branches, those will disappear. The new master branch will be the currently supported and official release of Crafted Emacs. Additionally, many (most) of the issues still outstanding will be closed as no-longer applicable since most were opened against v1 and are really old with no further discussion occurring on them.

Make sure to take a look at the v1 to v2 transition guide. N.B. This link work for the rest of this week, but not after the release. I'll post another blog entry with an updated link on Friday. If you have questions, feel free to create issues (best approach) or see if one of the maintainers is in the Emacs – System Crafters channel.

Happy Crafting!

Tags: #emacs

RC1 is available

Short note: Crafted Emacs RC1 is out. For those (and hopefully there are many) who wish to try it, you need to checkout the craftedv2RC1 branch.

Moving forward, there are a few things we are working on. We have some progress on a template to use when submitting issues, that should be available “soon”. We will be working on some guidance when transitioning to Crafted Emacs V2 from Crafted Emacs V1. We will also look to beefing up the documentation on contributing modules for Crafted Emacs. We have one for contributing documentation, but only a brief mention in the README.

None of those items are blockers for releasing Crafted Emacs V2. We'll leave RC1 in place for a couple of weeks, depending on community involvement and any issues encountered which need to be fixed. We may have a RC2 if there are enough issues to fix.

Finally huge thanks to my fellow contributors, Judy and Stefan, for putting in so much time and helping getting to this point so quickly!! You guys are awesome!

Happy Crafting!

Tags: #emacs

RC1 Progress

It's almost here. A ton of work has been done on the documentation front led largely by Stefan. I think I'm the actual blocker at the moment, as I need to document the Crafted OSX module. I'll get to that in the next few days. Once I complete that, we should be ready for a final internal review before cutting to a RC1 branch.

TODOs once RC1 is released

  • We need to develop a transition guide to address the differences between Crafted Emacs V1 and V2. We'd like for this to be a smooth transition, but V2 is completely different in mindset from V1, so there will be a lot of work to transition from one to the other.
  • I'll delete the deleted-modules directory
  • Double check comments in code to make sure they are still accurate.
  • Testing.

Crafted Emacs V2 release on the horizon

Once we get the RC1 branch put out the door, we'll be looking for as many as who are willing to put the screws to the configuration and file bug reports. Once those are resolved, we'll release V2. So the time between RC1 and a V2 release may be short or long depending on how many people are willing to test and file issues for us to look at and resolve. Once things are settled out for about a week or so, we'll do another internal review to make sure we have covered everything and then I'll push the next release and submit a blog post.


Fun fact (I'm sure you probably knew this), Emacs has a way to document changes in a ChangeLog file. So, I've given it a go for the past few weeks to keep track of changes since the my last post here. It's a bit of a duplication of work from one sense because the same information is in the *vc-change-log*, it just isn't formatted the same way. Not sure I'll keep up with it, but it has been an interesting exercise. So, here is what we have been up to recently:

  • Documentation for these modules:
    • Crafted Defaults
    • Crafted Evil
    • Crafted IDE
    • Crafted Init
    • Crafted Speedbar
    • Crafted Startup
    • Crafted Updates
    • Crafted Workspaces
    • The Getting Started Guide
  • Fixes for the Crafted Speedbar module
  • Fixes for the Crafted OSX module
  • Deleted the obsolete bootstrap directory.

In other news…

I've been using vc mode a lot more for my version control operations in Emacs. Magit provides quite the nice experience, but vc mode is also a lot nicer than what it seems a lot of people give it credit for. One of the nicest things about magit is the menu that pops up when need to do an operation. The status page is also well built and has some nice information on it. If I use vc-dir and then from there type L I get nearly the same information. At the top, I see my repository information, under that a list of things that changed or are unregistered, and in the bottom window, I see the *vc-change-log*. For me, there have been several cases where vc mode has been quicker to operate than magit. I haven't tried to track that down, but especially for local work, vc mode is extremely quick. Some operations take extra steps. For example in magit I can stage a new file and a changed file at the same time and commit that in one step. With vc, I have to register the new file, commit that, then possibly amend that commit to include the edited file because everything has to be in the same state and added is not the same as edited. In cases like that, I just use magit. Simpler to do. Otherwise, it's just as easy to use vc either directly from the buffer I'm editing or from vc-dir to mark multiple files and then commit them.

I've also tried working with forge in magit. For me, it's been a bit flaky. A couple of things to pay attention to: the repository name must match on both sides. So, for example, you must use git clone and not git clone because the case doesn't match and forge won't find the repository. Once you get that all worked out, you can pull the issues and PRs, but you can't approve or request changes on a PR from the forge interface. You can post comments though. Still a good package though, and if you work with PRs but don't need those features, it might work out for you. There hasn't been a release in over a year, and the released version has a number of defects which show up with odd messages like “Switching to deleted buffer”. There are fixes available, so you may prefer to pull forge directly from source with package-vc (or something similar) or just use the version from MELPA. I'll probably contact the author and ask for an updated release and I'd rather have the released version than the development version.

Happy Crafting!!

Tags: #emacs

Documentation work has been ongoing this month, as well as a few fixes. I'll get to that in a moment though.

New Teammate!

I have expanded our team to include Stefan Thesing (@sthesing) who has been doing a ton of work on getting documentation in order. He has raised a few points for thoughtful discussion and has also worked on a few code PRs as well. I appreciate his efforts and he seemed to be a good fit for the team. Judy and I had a conversation about it and decided to see if he wanted in. We are happy to announce his agreement and look forward to working together even more in the future!


Now that I have that wonderful news out of the way, here are some of the updates to the Crafted Emacs V2 Beta branch:

  • The way we figure out if a package is available for configuration was updated across the board. This took some thought and research, but we found a pretty good way forward (at least I think so). Stefan was instrumental in getting most of that work done.
  • Documentation. Lots and lots of documentation. Stefan reproduces the crafted-completion-config documentation replete with screenshots along the same lines as he did for the prior release. Duchene Horst provided an update for using the straight package manager.
  • Judy provided updates for named functions in hooks, other broken feature guards, the path for when the auto-insert template for Crafted Emacs modules fires, and consolidating how aggressive-indent-mode is configured.

RC1 on the horizon

We have a plan for a RC1 type of release. That is coming, hopefully soon. Right now, our goal is to complete the documentation of the modules listed in Issue 128, so if anyone wants to submit a PR for one of the modules that doesn't have a check mark next to it, please do so! The more help we get, the faster we get there!

Happy Crafting!!

Tags: #emacs

Life. It's a thing. So, I've been busy with work and stuff for the past couple of months and haven't taken the time to get an update out! Oh dear!

New Teammate!

Well, here you go! Even though my day job has been getting more and more hectic, I've still found time to continue working on Crafted Emacs. On that note, if you have been paying any attention to the repo, you may have noticed an uptick by one of our community in the comments on issues, and pull request submissions. She has been so helpful, I asked her to join me as a teammate and co-maintainer of Crafted Emacs, and she graciously accepted the position! So, today, I'm excited to introduce Judy (@jvdydev) as a co-maintainer!! No, I'm not working myself out of a job, but it certainly has been nice to have a second set of eyes and hands on the keyboard these past few weeks, and I'm really excited to be working together with her moving forward.


Now that I have that wonderful news out of the way, here are some of the updates to the Crafted Emacs V2 Beta branch:

  • Fix for some provide forms in a few modules. When I renamed the modules, I missed updating some of the provide forms so those modules weren't found when a require form tried to load them.
  • Richard Davis submitted a patch to help resolve the crafted-emacs-home in the event Git was not installed. This situation can occur when someone downloads a zip file from GitHub instead of cloning it. Ostensibly, this situation can occur when trying to get Emacs up and running on a work computer that doesn't allow installation of such tools as git.
  • A lot of documentation updates. Most of these came from Judy, and there are bunch of them, including a complete reorganization of the provided info file to make it clearer and link to existing Emacs documentation so we don't reinvent the wheel when writing docs for things already provided by Emacs itself.
  • I added a fix to handle not performing auto-insert on the custom-file, which is annoying when you are starting Emacs the first time, or any time after you delete the custom-file. A few suggestions were provided in the issue, I chose to advise the function instead.
  • And finally, the keycast module has been fixed.

Oh, and I did a stream with David where we introduced the Crafted Emacs V2 Beta launch, feel free to go back and watch that stream and hear all the plans for not just V2, but for the next release(s) of Crafted Emacs. No promises we will go fully down that road, but there are some good ideas I think will be interesting to put together. At the moment though, my focus is on the Crafted Emacs V2 Beta branch. I did back port the fix for the custom-file to the master branch, so you should be able to take advantage of that goodness with your next Crafted Emacs install. We are still looking for feedback on the modules, issues are the preferred method of reporting them, but you might find one of us in the Emacs room in the System Crafters space on Matrix (see:, so feel free to say hello and ask questions.

Happy Crafting!!

Tags: #emacs

Another month has passed. I've tried to get as much done as I can think of in order to move to a “beta” release (if you want to call it that). So, as I'm running out of things I think are critical to get done, I'm now announcing the move to a “beta” release!

To get here the following updates have been made:

  • Module consolidation for several similar modules.
  • Archival (soon to be deleted) of several modules replaced by the above effort.
  • Support built in package.el as the primary package management solution. Before, we included code to support both package.el and straight.el, that code has been removed, but there are some general instructions on using packagers other than package.el with Crafted Emacs.
  • Separate package lists from package configuration.
    • Using modules with the suffix packages simply adds “bundles” of packages to the list of selected packages. Doing so allow use of the built-in package-install-selected-packages function to install everything needed at once. Packages already installed are skipped without additional checks and is generally faster and easier to use. N.B. these are not required if the user installs their Emacs packages from external tools, for example guix or nix or other operating system package managers.
    • Using modules with the suffix config assumes packages have been installed and provides configuration for them. There are checks to make sure those packages are installed and enabled by the package system before configuring them.
  • Rewrite the file, consolidate some parts to make it more concise. The intention is people will actually read the README file rather than skip it due to how long it is.
  • Provide a “Getting Started” guide and link to it from the as well as in the generated info file included with Crafted Emacs.
  • Change the approach to configuration to push customized values to the default Emacs custom-set-variables section of the custom-file. This enables the user to decouple from Crafted Emacs and (mostly) not lose any configuration.
  • Simplified both early-init.el and init.el. Now these files are in the users control and we only provide examples of their use rather than providing the implementation.
  • Crafted Emacs no longer stores configuration in it's own folder. This was problematic for several reasons, as different packages dropped files or folders in the user-emacs-directory and we had to detect those and move them to the CRAFTED_EMACS_HOME. That effort was incomplete so files were scattered across the two directories leaving a confusing mess. Everything now is in the user-emacs-directory and the user has control over moving them to XDG locations if they choose, or possibly using something like a no-littering approach.

This is a very divergent approach compared to what Crafted Emacs has been so far. I'll be writing a transition guide for existing Crafted Emacs users. Those who wish to try it are encouraged to send feedback via issues on the project GitHub site.

Tags: #emacs