Migrating to use no-littering
Table of Contents
1. Introduction
This document describes migration towards using no-littering for path theming.
2. Steps
2.1. Prepare code
You must not install no-littering with a package manager because it might automatically get loaded. Make sure installing it won't load it. If you are not sure, clone the repository somewhere but do not load or require the package. We need this to preserve the existing values set to themed variables.
Before you start, tangle this file by running M-x org-babel-tangle
and
load no-littering-migration.el
, for example by opening dired and
hitting L
on the file.
2.2. Save current values of your settings
First, we need to save the current values of the themed variables to be able to move the files from their existing locations. Execute the code below:
(setq no-littering-current-values (no-littering-get-current-variables))
2.3. Load no-littering
package
Now you can install the package with your package manager of choice. After installation, run:
(require 'no-littering)
2.4. Save new values
Now we save the new themed values set by no-littering.
(setq no-littering-new-values (no-littering-get-current-variables))
2.5. Generate migrations
We now have the old list and a new list and we can compare the
existing values to new values. The code below generates a migration
script which you have to review and execute manually.
In order to generate the script, place the cursor inside the code block
and press C-c C-c
.
(no-littering-generate-migration no-littering-current-values no-littering-new-values)
The result is a list of progn
forms which can be evaluated by placing
the point at the end of the progn
form and calling M-x eval-last-sexp
(usually bound to C-x C-e
).
The form looks like this:
(progn "abbrev-file-name" ; name of the variable (make-directory ;; create a parent dir for target "/home/matus/.config/emacs/etc/" t) (rename-file ;; old (current) file "/home/matus/.config/emacs/abbrev_defs" ;; new file "/home/matus/.config/emacs/etc/abbrev.el" 1))
If you are satisfied, execute it and move to the next one.
Some of the forms might error out when the source file does not exist. In that case there's nothing to do and you can move to the next one.
Occasionally, the generated code is not valid and you need to do the migration manually.
2.6. Remove customized values
If you were using customize-variable
before, you need to remove
customized settings or they will keep overwriting the values managed
by no-littering
. Simply run the following to remove all
customizations.
Make sure to backup your custom file before running this so you can compare the results.
(no-littering-custom-reset) (custom-save-all)
Likewise, remove any other customization of the paths managed by
no-littering
.
3. Code
(defun no-littering-get-themed-variables () "Return all variables recognized by no-littering." (with-temp-buffer (insert-file-contents "no-littering.el") (goto-char (point-min)) (re-search-forward "^(cl-letf") (beginning-of-line) (down-list) (forward-sexp 4) (let* ((data (cdr (read (current-buffer)))) (vars (cl-remove-if-not (lambda (form) (eq (car form) 'setq)) data)) (current-values (mapcar (lambda (form) (let* ((var (cadr form)) (value (and (boundp var) (symbol-value var)))) (when (stringp value) (setq value (file-truename value))) (cons var value))) vars))) current-values))) (defun no-littering-get-current-variables () "Return all variables recognized by no-littering currently used." (cl-remove-if (lambda (var) (not (cdr var))) (no-littering-get-themed-variables))) (defun no-littering-generate-migration (old-values new-values) (let* ((migrations (mapcar (lambda (var) (list (car var) (cdr var) (cdr (assq (car var) new-values)))) old-values)) (commands (mapcar (lambda (var) (if (stringp (nth 2 var)) (when (not (equal (nth 1 var) (nth 2 var))) `(progn ,(format "%s" (car var)) (make-directory ,(file-name-directory (nth 2 var)) t) (rename-file ,(nth 1 var) ,(nth 2 var) 1))) `(progn ,(car var) "Value is not a directory"))) migrations))) commands)) (defun no-littering--custom-reset-symbol (symbol) (put symbol 'variable-comment nil) (put symbol 'standard-value nil) (put symbol 'customized-value nil) (put symbol 'customized-variable-comment nil) (when (or (get symbol 'saved-value) (get symbol 'saved-variable-comment)) (put symbol 'saved-value nil) (put symbol 'saved-variable-comment nil))) (defun no-littering-custom-reset () (dolist (var (no-littering-get-themed-variables)) (no-littering--custom-reset-symbol (car var))))