Bowmansarrow

Emacs 30.1 released… and stuff broke.

Well, it's been over a year since I posted an update about Crafted Emacs! How time flies, right! I continue to support the project and have been thinking about different things to do with Crafted Emacs, but nothing really sticks as something that needs to be done.

Lost package-selected-packages value!!

However, with the release of Emacs 30.1, there are a few things I need to review. One thing kinda broke configurations depending on how you write your configuration. The new “feature” from Emacs has to do with the function that saves the values of defcustom variables. We make a call to the package--save-selected-packages by adding it to the after-init-hook. Notice there are two dash characters in the name. That generally means it is not a “public” API, and using it can be risky. Basically, the form of that function is this:

(defun package--save-selected-packages (&optional value) ... )

Notice the &optional value parameter? In Emacs version prior to 30.1 if that value was not present (ie its value is nil) it would use whatever the value of the package-selected-packages variable, which is a list of the packages to be installed. We update that value by calling add-to-list to append the packages to install, which is important essentially the first time you startup Emacs from your configuration. After that, they are already installed, so the value is checked and if there is nothing to do, no additional packages are installed. In Emacs prior to version 30.1, this was safe since we were already updating the value and the &optional value parameter would not be used if it were nil.

All that changes with Emacs 30.1 which resulted in something that looked like this:

(custom-set-variables
 ...
 '(package-selected-packages nil)
 ...)

That's a bit concerning as we need to check if all the packages are installed already, but the value is nil when we start Emacs (assuming you follow the pattern in the example configurations and load the custom.el file at the top of your init.el file). It is updated during initialization, but then written back out as nil after initialization.

That happens because the new code for that function checks to see if either the optional value is not nil or the value of after-init-time is set. When after-init-time is set, then the assumption is the provided (or possibly not provided) value parameter contains the list of installed packages and it gets sorted and set as the list package-selected-packages. Since we weren't providing that optional value, the result was the package-selected-packages was always nil. I had noticed this behavior and just thought it was something wrong with my configuration, but then Jabbo (one of the Crafted Emacs maintainers) raised a bug about it and provided a PR to solve the problem. The solution is to pass the package-selected-packages along as the (not so) &optional value.

Oh, and by the way…

We also added code for using the new preview completion function globally. David demonstrated it in a recent live stream. This configuration lives in the crafted-defaults-config module and gets turned off if you use the crafted-completion-config module with Corfu installed.

In other news…

There was an issue raised about tree sitter, upstream broke a few things like latex, janet, and markdown for different reasons. Jvdydev provided some guidance on how to work around the problem. We use the treesit-auto package to help automate the installation of grammars, and usage is by opt-in for the specific grammars you would actually use. If you ran into the problem from the issue, you could remove those from the list of grammars, and possibly try to install them manually or use the Emacs built-in functions to install them. My comment on that issue has an example installing the grammars for tsx and typescript. As the problem is outside the scope of Crafted Emacs (ie we depend on the author of the treesit-auto package to fix issues), there isn't much we can do, but, as you can see in the comments, we do try to be as helpful as possible.

A similar kind of problem was raised regarding org-appear and org version 9.7.2. The built-in version of org in Emacs prior to version 30.1 is 9.6.15 and the problem mentioned does not appear with that version. This is another situation where the problem is outside the scope of Crafted Emacs. I'll test again with Emacs 30.1 which includes org 9.7.11 and see if the problem persists and make an update to this blog with what I find.

[UPDATE] I could not duplicate the problem above as mentioned in this issue.

Finally, there was an issue that raised a question about setting the value of the package-archives based on the running Emacs version. The question was very well answered by Jvdydev but it turns out the question was actually about the inability to install emark-consult. Jvdydev provided an answer to that as well, at least as best as she could without an error message.

Conclusion

So, it's been slow on the Crafted Emacs front so far, but if you are using Crafted Emacs and notice anything a bit odd after the update to Emacs 30.1, please post an issue and we'll be happy to take look and either fix something in our code or possibly help you with your configuration. Of course, you can always submit a PR with your issue as well, we'd be happy to review it and possibly pull it in.

Happy Crafting!

Tags: #emacs

It's been a while since I posted a blog. After reviewing a couple of the more recent SystemCrafters live streams1 it seemed like a good time to add some thoughts on how Crafted Emacs might be used to solve similar problems. I wasn't able to participate live, I still have a day job and have meetings and stuff, so I had to watch them after-the-fact. Something I usually try to do anyway, but I prefer to participate in the streams as they happen.

Crafted Emacs for minimal configuration

In the live stream on 16 November 2024, David talks about his approach to rewriting his configuration. After not using a literate approach for a while, he has returned to using a literate approach to his config. Not my cup of tea, but I totally understand why he would go that route, and he gives reasons why he likes that approach during the stream. He also mentions only using GNU and Non-GNU ELPAs to help minimize his configuration. Crafted Emacs assumes you want every ELPA, but it does prioritize the GNU and Non-GNU ELPAs above MELPA-stable and MELPA. With Emacs 29, you get both GNU and Non-GNU ELPAs by default, so if you choose to limit yourself to just those, you don't need to use the crafted-early-config.el in your config, but you probably still need to add (require 'package) to your config if you intend to continue to use any of the crafted-*-packages.el modules as they need the package-selected-packages variable to be defined. For the completions David talked about, if you use the crafted-defaults-config.el module, those are setup by default for you. This includes the following snippet to control the size of the *Completions* buffer:

(add-to-list 'display-buffer-alist
             '("\\*Completions\\*"
               (display-buffer-reuse-window display-buffer-pop-up-window)
               (inhibit-same-window . t)
               (window-height . 10)))

If you are not using that module, but prefer to use the built-in completions (or something like icomplete, ido, or fido) the above snippet will help keep *Completions* window from taking over the screen. David discusses the completion styles and gives examples, so watch the live stream2 for a good overview of how that variable works.

With all that said, a minimal Crafted Emacs configuration might be something like this:

(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))

(load (expand-file-name "~/crafted-emacs/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")

;; needed if you want to use any of the crafted-*-packages modules
(require 'package)

(require 'crafted-defaults-config)

(add-to-list 'display-buffer-alist
             '("\\*Completions\\*"
               (display-buffer-reuse-window display-buffer-pop-up-window)
               (inhibit-same-window . t)
               (window-height . 10)))

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

(provide 'init)
;;; init.el ends here

You can also take a look at my post where I develop a minimal configuration.

Final thoughts…

Developing a minimal configuration is an interesting challenge. My configuration is not quite as minimal as it used to be, I have added packages over time as needed to be productive with tasks at work. I also have a “default” set of “can't live without” packages I choose to install. David chose to implement the portions of some packages he actually uses rather than install the full package. The pros of just installing the package is reduced cognitive load (someone else does the work of writing and updating features you need) and an ostensibly shorter base configuration. The pros of writing the packages by pulling just the functionality you use and molding it to your configuration as David does is less reliance on external packages. This is quicker to get up and running with just your configuration, which can be handy when on a remote host, or a system with corporate controls that prevent downloading code not vetted by the corporate IT infrastructure.

Regardless of your approach, Crafted Emacs can help you get started with the building blocks you need to be productive quickly. After that, it's up to you to whittle things down or write custom code or whatever to fit your own personal needs.

Happy Crafting!

Tags: #emacs #systemcrafters

Footnotes

1 See this one and this one for context.

2 Start here for completion styles