rediscovering registers

Although I had heard about registers before I never found a use for them. To me they seemed like worse bookmarks. Bookmarks can have meaningful, descriptive names whereas registers must named after a single character. Bookmarks persist across sessions whereas registers last only for the current session (though you can persist them via savehist). Bookmarks operate via bookmark handlers, functions which can accept an alist of essentially anything and interpret it in any way they want to generate the whatever was bookmarked. In contrast, registers have narrowly defined contents which can do a small and limited subset of what bookmarks can do. I never thought I would find a good use case for registers--until now.

One of the most well-established ways of reducing Emacs startup time is to temporarily adjust the values of certain variables during startup. Among these is the file-name-handler-alist, an alist that, as its name suggests, determines how special files should be handled by Emacs. This alist is consulted whenever a file is loaded. And while important in-session, only basic file handling is needed during startup. Therefore it is often recommended to set this to nil and reset its original value only after startup is over. To achieve this some Emacs configurations let-bind file-name-handler-alist around the main code of their init file. However, this is not ideal because emacs-startup-hook runs after the init.el is loaded and consequently will not benefit from a nil-valued file-name-handler-alist. Other Emacs configurations just define a "placeholder" variable--something like old-file-name-handler-alist--to store the value of file-name-handler-alist until startup at which point its value is restored by some user-defined hook. Having done it this way myself, I found that despite getting the job done I had lingering feelings that there was a better way. It seems wasteful and a misuse of defvar to define symbol as merely temporary internal storage. Moreover, this method does not scale well: for N symbols whose value you need to store you will need to define N placeholder variables.

In an attempt to do better, I defined an alist, oo-symbol-values-alist, to store symbols and their values as well as a corresponding getter and setter, oo-restore-value and oo-record-value respectively.

            
(defvar oo-symbol-values-alist nil)

(defun oo-record-value (symbol)
(push (cons symbol (symbol-value symbol)) oo-symbol-values-alist))

(defun oo-restore-value (symbol)
(set symbol (alist-get symbol oo-symbol-values-alist)))
            
        

Now, instead of defining new value-storing variables for every variable value I simply use the accessor functions I defined. I like this much more. Generally, naming something via defvar should be reserved for things that are special, things that we want to draw attention to, things that merit a name. Otherwise, naming in excess can distract readers from things that are actually important. In this particular case, where I store the value is not important. What is important is the fact that they are stored.

            
;; Record the value of `file-name-handler-alist`.
(oo-record-value 'file-name-handler-alist)
;; Set it to nil.
(setq file-handler-alist nil)
;; Restore its value after startup...
(oo-restore-value 'file-name-handler-alist)
            
        

Using Emacs it is not uncommon to discover some code you put together has actually already been implemented by an existing feature. This is exactly what happened after I came across this blog post from irreal concerning registers. Astonished by the striking similarity between the functions I wrote, oo-record-value and oo-restore-value, and the built-in register functions, get-register and set-register, I realized registers brought an iressistable opportunity to simplify my configuration while leveraging a built-in package and, consequently, replaced the code I had written in favor of registers (shown below).

            
;; Record the value of `file-name-handler-alist`.
(set-register :file-name-handler-alist file-name-handler-alist)
;; Set it to nil.
(setq file-name-handler-alist nil)
;; Restore its value after startup...
(setq file-name-handler-alist (get-register :file-name-handler-alist))
            
        

I started this article with comparing bookmarks to registers, explaining how I did not understand why anyone would ever use registers instead of bookmarks. Now I can give a better answer. With bookmarks you want what you store to actually be a "thing", which is why you name it and you persist it in the bookmark file. In contrast, you use registers when you want to store something that is temporary--an individual unnoteworthy means to an end-- which you specifically do not want to be a "thing".