With the great help from amazing Henrik Lissner (Doom Emacs author) and others, I have found answers to my questions:
- About multiple enabled themes. Why is it possible to enable multiple themes?
If you have multiple themes active at the same time, you have multiple groups of faces active at once.
e.g. Theme 1 sets the background of emacs to red. Theme 2 sets the color of bold text to blue. Theme 3 makes comments dark grey.
Activate them all and you have a red background, blue bold text, and dark grey comments.
Though, generally, folks don't design their themes to be modular.
- How to get faces for a loaded yet not enabled theme?
I think you'd need to look into (enable-theme)
I checked the code and found that (enable-theme)
does: (get theme 'theme-settings)
. That however returns a lot of data that I needed to streamline a bit; After a bit of bike-shedding, I wrote this:
(defun color-theme-get-faces (theme)
"Get list of faces with their attributes of a given THEME.
If theme is not loaded, it loads it first"
(let* ((theme (get theme 'theme-settings))
(theme-settings (if theme theme
(progn
(load-theme theme :no-ask :no-enable)
(get theme 'theme-settings))))
(extract-props (lambda (props)
"extracts face props based on display type"
(seq-reduce
(lambda (acc x)
(pcase-let ((`(((,disp-type ,disp-val)) ,face-props) x))
(if acc acc
;; prioritize graphic & color displays
(cond ((eq disp-val 'graphic) face-props)
((eq disp-val 'color) face-props)
((eq disp-type 'min-colors) face-props)
(t face-props)))))
props nil))))
(seq-remove
'null
(seq-map
(lambda (x)
(pcase-let* ((`(,prop-type ,face _ . (,props)) x))
(when (eq prop-type 'theme-face)
(list face (funcall extract-props props)))))
theme-settings))))
load-theme
is unclear to you.C-h f
akaM-x describe-function
. In terms of building your own, consider opening up the source code of your favorite theme and tweaking it to create a new one ... changing the name of the theme, creating a new file, etc.