Customizing Emacs Muse – Part 2
We all know what an association list is right? If you want to map keys to values, you’re going to use an assocation list.
(defvar v '((GB "Great Britain") (UK "United Kingdom") (FR "France"))) (assoc 'GB v)
will return the pair
(GB "Great Britain").
They are used in a similar way to a hash in various scripting languages. For example, muse-html uses one,
muse-html-markup-strings to determine which text to use for each type of markup.
You might remember that previously I advocated the use of regex transforms to correct the html after generation is complete. However, that can cause problems. We therefore need to fix the association list to have the correct mapping.
Assocation lists have a bunch of functions which operate on them, e.g.
rassoc for looking things up and
assq-delete-all for removing elements. However, I couldn’t find one which changes elements.
(defun assoc-replace (seq values) "Replace an element within an association list where the cars match." (mapcar (lambda (elem) (let* ((key (car elem)) (val (assoc key values))) (if val (cadr val) elem))) seq))
This will allow me to replace both key and value within the association list at the same time. Normally, I’ll just need to replace the value so I made a helper which saves me from having to repeat the key.
(defsubst kv (k v) `(,k (,k . ,v)))
And now I can fix the assocation list
(defconst sq-code (concat "<b style=\"font-weight: normal; " "font-size: 115%; background: #eee " "padding: 3px;\">")) (setq muse-html-markup-strings (assoc-replace muse-html-markup-strings (list (kv 'begin-literal sq-code) (kv 'end-literal "</b>"))))
Alternatively, I could delete the existing elements and add the new ones on the start of the list, maybe with something like the following
(cons (cons 'begin-literal sq-code) (cons '(end-literal "</b>") (assq-delete-all 'begin-literal (assq-delete-all 'end-literal muse-html-markup-strings))))
But I think my way is neater.