Splitting up my .emacs, or "use-package doesn't solve all problems"

Over on the Fediverse, I shared a little story :

The current state of my GNU Emacs yak shaving:
; wc -l .emacs
1550 .emacs

Some of that is comments. Some of that is personal functions that I should move out to other files so I can have only use-package stuff in my .emacs. And some of it is large blocks for lsp-mode and company and some other stuff I'm probably never going to use again, which I should drop.

I got into my .emacs situation despite using use-package , which is the usual way people recommend to tame your Emacs configuration. Today I dealt with the whole thing by splitting my .emacs up into separate files , which is much better in general even if it's a bit more annoying in some ways.

My .emacs had accumulated a number of things over time, probably like many long term Emacs users. Besides infrastructure for use-package, it also had general Emacs settings I want, little personal commands and functions, simple use-package declarations, and a number of large, complex use-package declarations for packages that I need to significantly customize and tweak (and where I had lots of comments about the situation, written for my future self). Plus it also had commented out remains of experiments with things like origami-mode.

Some of these things I could remove to cut down my .emacs size, but a lot of them are intrinsically large, especially various use-package declarations. Things like Eglot, Corfu , and Vertico aren't really small packages with little to configure and adjust; they touch core areas of my Emacs experience where I have some strong opinions that don't match their default configurations. Making them work how I want them to is not necessarily a tiny process of one or two customizations. Using use-package basically encourages putting those customizations inline, as part of the overall use-package declaration, including little helper functions.

(Plus, modern modular things like Eglot require a bunch of additional packages for the full experience , and a bunch of small use-package declarations add up, especially when I add comments about why I have them.)

I took two approaches in my split. For personal functions and key bindings, I set up a number of new personal packages in ~/share/elisp and configured them in new use-package blocks (which also let me set hooks and establish key bindings). Then I took existing large use-package declarations (and small ones tied to them) and moved them all to a collection of separate files that I directly ' load-file ' in my .emacs. The separate files are organized by general purpose; I have one for LSP stuff, one for all aspects of completion , one for flymake and flycheck, and one for MH-E. I left unrelated small use-package declarations (many for small packages ) in my .emacs rather than try to push them to a 'miscellaneous' file where I'd probably forget about them.

(The resulting .emacs file has 18 use-package declarations left, five of which are for personal things and some of which are present purely so I can ' :diminish ' their modeline markers.)

What I take from this is that use-package is a perfectly good way to keep things organized but, somewhat obviously, it in no way guarantees that they will stay small or that I will refrain from adding packages.

Sidebar: use-package, load paths, load-file, and require

I don't have my ~/share/elisp directory tree on my Emacs load path, although maybe I should. For my collection of personal functions that I set up with use-package, I used ' :load-path ':

(use-package cks-misc
  :load-path "~/share/elisp"
  :commands (....)
  [...]
  )

(These things have no use-package usage inside themselves, they're just ELisp functions and so on.)

For the use-package declarations I moved to other files, I put them in ~/share/elisp/startup and did, eg:

(load-file "~/share/elisp/startup/lsp-startup.el")

It's probably more Emacs-proper to put things on my load path and then require the relevant name, but the load-file approach works, it directly expresses what I'm doing, and it hopefully makes it clear to future me that these aren't anything like normal packages.

Incidentally, as I discovered in the process of writing this entry but my readers may already know, when you use use-package's ' :load-path ', the directory is permanently added to ' load-path '; it's not just used once for this use-package (this is sort of spelled out in the documentation if you read carefully). I'm still going to use ' :load-path ' on everything that 'needs' it, although now I'm more tempted than before to extend ' load-path ' to my ~/share/elisp in my .emacs setup code.