Open oliverepper opened 1 year ago
this is literally the first Lisp code I ever wrote.
Wow, that is good!
The idea is promising! Though let's not interfere with the toggle for the time being.
I made some minor tweaks to your code:
(defun oe/rotate-list (list)
(when list
(append (cdr list) (list (car list)))))
(defun oe/cycle-themes (theme-list)
(load-theme (car theme-list) :no-confirm)
(oe/rotate-list theme-list))
(defvar modus-themes--cycle-themes modus-themes-items)
(defun oe/cycle-themes-and-print-log-msg ()
(setq modus-themes--cycle-themes (oe/cycle-themes modus-themes--cycle-themes))
(message "Theme: %s selected" (car (reverse modus-themes--cycle-themes))))
(defvar modus-themes--toggle-themes modus-themes-to-toggle)
(defun oe/toggle-themes-and-print-log-msg ()
(setq modus-themes--toggle-themes (oe/cycle-themes modus-themes--toggle-themes))
(message "Theme: %s selected" (cadr modus-themes--toggle-themes)))
(oe/cycle-themes-and-print-log-msg)
(oe/toggle-themes-and-print-log-msg)
The main difference is to set "private" variables (denoted by the --
in their name), so that we do not change global/public variables.
Below is my attempt at a "cycle" command:
(defun modus-themes--rotate-list-of-symbol (symbol)
"Rotate list value of SYMBOL by moving its car to the end.
Return the first element before performing the rotation.
This means that if `sample-list' has an initial value of `(one
two three)', this function will first return `one' and update the
value of `sample-list' to `(two three one)'. Subsequent calls
will continue rotating accordingly."
(unless (symbolp symbol)
(user-error "%s is not a symbol" symbol))
(when-let* ((value (symbol-value symbol))
(list (and (listp value) value))
(first (car list)))
(set symbol (append (cdr list) (list first)))
first))
(defvar modus-themes--cycle-themes modus-themes-items)
(defun modus-themes-cycle ()
"Cycle through the `modus-themes-items'."
(interactive)
(let ((theme (modus-themes--rotate-list-of-symbol
'modus-themes--cycle-themes)))
(modus-themes-load-theme theme)
(message "Loaded %s theme" theme)))
Those granted, we probably want to have a modus-themes-to-cycle
as a
companion to such a command. Its default value could be modus-themes-items
.
Hey Prot,
I made a few adjustments on my cycle-themes idea, so that it saves my last choosen theme and loads it again when I start Emacs. This works super nice for my cycle-function but since your toggle function does not return the selected theme it's hard to advice it with the oe/save-selected-theme-function.
(use-package modus-themes
:demand
:custom
(modus-themes-to-toggle '(modus-operandi modus-vivendi))
(modus-themes-disable-other-themes t)
(modus-themes-italic-constructs t)
(modus-themes-variable-pitch-ui t)
(modus-themes-mixed-fonts t)
(modus-themes-prompts '(bold))
(modus-themes-org-blocks 'tinted-background)
(modus-themes-headings
'(
(1 . (1.215))
(2 . (1.138))
(3 . (1.076))
(4 . (1.0))
(5 . (0.937))
(agenda-date . (variable-pitch italic 1.138))
(agenda-structure . (variable-pitch light 1.8))
(t . (medium))
))
(modus-themes-common-palette-overrides
'(
(border-mode-line-active bg-mode-line-active)
(border-mode-line-inactive bg-mode-line-inactive)
))
:bind ("<f5>" . modus-themes-toggle)
:config
(let ((last (expand-file-name "selected-theme.el" user-emacs-directory)))
(if (file-exists-p last)
(load last)
(load-theme (car modus-themes-to-toggle) :no-confirm))))
(defun oe/save-selected-theme (theme)
(with-temp-file (expand-file-name "selected-theme.el" user-emacs-directory)
(insert (format "(load-theme '%s :no-confirm)\n" theme))))
(defun oe/rotate-list (list)
(when list
(append (cdr list) (list (car list)))))
(defun oe/cycle-themes (theme-list)
(load-theme (car theme-list) :no-confirm)
(oe/rotate-list theme-list))
(defun oe/cycle-themes-and-print-log-msg ()
(interactive)
(defvar modus-themes--cycle modus-themes-items)
(setq modus-themes--cycle (oe/cycle-themes modus-themes--cycle))
(let ((selected-theme (car (reverse modus-themes--cycle))))
(message "Theme: %s selected" (car (reverse modus-themes--cycle)))
(oe/save-selected-theme selected-theme)))
(global-set-key (kbd "<f4>") #'oe/cycle-themes-and-print-log-msg)
Keep in mind that I am still new to Emacs/elisp. I'd glady take any idea to make f4 and f5 save the choosen theme.
Very well!
(defun oe/cycle-themes-and-print-log-msg ()
(interactive)
(defvar modus-themes--cycle modus-themes-items)
(setq modus-themes--cycle (oe/cycle-themes modus-themes--cycle))
(let ((selected-theme (car (reverse modus-themes--cycle))))
(message "Theme: %s selected" (car (reverse modus-themes--cycle)))
(oe/save-selected-theme selected-theme)))
The defvar
declares the variable. This usually is a top-level form because then the variable does not depend on the call to a specific function (if you expect the variable elsewhere, it will fail). Put the defvar
outside the function and in the function use the setq
you already have.
Maybe I am misreading this now, but in this let
form the second (car (reverse ...
could be replaced by selected-theme
.
About the choice of key, you can always use any key you want, though note that the default for f4
is to either conclude an in-progress keyboard macro or execute the last defined keyboard macro (kmacro definitions are done with f3
). I find those very useful.
Yes. You're right the second let should read selected-theme
. That was an oversight. Regarding the defvar
I used it like one would use the static
keyword in C (the var belongs to the function but storage needs to be outside of the function). Do you have an idea how I can save the last selected theme that is choosen by modus' own toggle function?
Do you have an idea how I can save the last selected theme that is choosen by modus' own toggle function?
Would this do what you need?
modus-themes.el | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/modus-themes.el b/modus-themes.el
index 3d4c1b4..c854002 100644
--- a/modus-themes.el
+++ b/modus-themes.el
@@ -1257,7 +1257,8 @@ (defun modus-themes-load-theme (theme)
after loading the THEME."
(modus-themes--disable-themes)
(load-theme theme :no-confirm)
- (run-hooks 'modus-themes-after-load-theme-hook))
+ (run-hooks 'modus-themes-after-load-theme-hook)
+ theme)
(defun modus-themes--retrieve-palette-value (color palette)
"Return COLOR from PALETTE.
Yes! And for what's it worth I think it's a better function, now. It has a side effect (setting up the theme) and now it tells the world not only that it did that side-effect but even how it parametrized this side-effect. ❤️
Very well! I just made the change.
This is very nice:
:bind ("<f5>" . (lambda () (interactive) (oe/save-selected-theme (modus-themes-toggle))))
Hi @protesilaos,
first of all thanks a lot for these great themes. I am very new to Emacs and your themes help making the switch pleasurable! I enjoyed this video https://youtu.be/kPNMHrF4Lq8 and it even helped me understanding a bit of how things are handled in Emacs.
One thing occurred to me, though. I think that the API
modus-themes-toggle
is giving up chances:Since I am even newer to Lisp than I am to Emacs I have not yet prepared a PR but I tried my best in Lisp so you know what I mean:
Please let me know if you like the idea. I might give it a shot but this is literally the first Lisp code I ever wrote.