protesilaos / ef-themes

Colourful and legible themes for GNU Emacs
GNU General Public License v3.0
309 stars 17 forks source link

Suggestion: better light/dark switcher #29

Open pazos opened 1 year ago

pazos commented 1 year ago

Hi, Prot.

First of all, thank you for both you contributions to emacs and your philosophical essays. I find them all quite useful :)

And your themes are amazing. All of them (modus, ef-themes, standard).

I comment here since ef-themes is composed by a large set of themes and it is a pitty to have to select just two to toggle between. But my suggestion would be to repurpose the bits below to make a theme switcher that's available for different themes (yours or not).

Feel free to either ignore completely, apply the suggestion for ef-themes alone or make my dreams come true :smile:

I'm very new to elisp so please excuse my jargon, which I believe is mostly incorrect ATM.

Suggestion

Make a standalone theme switcher that accepts an alist of light/dark themes. Here's a working sample:

(defcustom pzs-theme-alist '()
  "Pairs of light/dark themes."
  :type '(repeat (cons (symbol :tag "Light") (symbol :tag "Dark")))
  :group 'pzs-theme)

(defun pzs-theme--is-dark-p ()
  (let ((current-theme (car custom-enabled-themes)))
    (rassoc current-theme pzs-theme-alist)))

(defun pzs-theme--toggle-light (name)
  (let ((theme (car (rassoc name pzs-theme-alist))))
    (if theme
        (progn
          (mapc #'disable-theme custom-enabled-themes)
          (load-theme theme :no-confirm))
      (message "No light variant for %s" name)))) 

(defun pzs-theme--toggle-dark (name)
  (let ((theme (cdr (assoc name pzs-theme-alist))))
    (if theme
        (progn
          (mapc #'disable-theme custom-enabled-themes)
          (load-theme theme :no-confirm))
      (message "No dark variant for %s" name))))

(defun pzs-theme-toggle ()
  "Toggle between light/dark mode for the current theme."
  (interactive)
  (let ((theme (car custom-enabled-themes)))
    (if (pzs-theme--is-dark-p)
        (pzs-theme--toggle-light theme)
      (pzs-theme--toggle-dark theme))))

(provide 'pzs-theme)

;; Local Variables:
;; byte-compile-warnings: (not free-vars noruntime)
;; End:

That way users can customize that list and toggle them all with a single command/key chord.

Following the sample code above I'm using:

(defvar light-dark-themes
 '((standard-light . standard-dark)
   (modus-operandi . modus-vivendi)
   (ef-elea-light . ef-elea-dark))
 "Pairs of light/dark themes.")

(use-package pzs-theme
  :ensure nil
  :custom
  (pzs-theme-alist light-dark-themes)
  :init
  (load-theme 'ef-elea-light :no-confirm))

There're a few extras that can be useful as well. For instance the alist can be converted to a list of atoms with something like


(defun alist-to-list (alist)
  "List of atoms from an `ALIST'."
  (let ((array ()) pair)
    (while (setq pair (pop alist))
      (let* ((key (car pair))
             (value (cdr pair)))
        (push key array)
        (push value array)))
    array))

And used with completing-read to implement a load-theme alternative that shows only the themes the user defined. I didn't implement it myself, since I also use consult, so I'm doing:

(setq consult-themes (alist-to-list light-dark-themes))

While I'm fine with those bits of code in my emacs config I would be even happier if you can take care of them on a hopefully easy to implement, easier to maintain and way better documented package.

I know you're doing a lot of work for the community, so please consider this a friendly suggestion and not a request that rushes you to commit more work than you already do.

protesilaos commented 1 year ago

From: Martín Fernández @.***> Date: Fri, 25 Aug 2023 11:30:46 -0700

Hi, Prot.

Hello Martín,

Sorry for the belated reply. I did not have electricity at home and had trouble connecting to the Internet. Now I am back online.

First of all, thank you for both you contributions to emacs and your philosophical essays. I find them all quite useful :)

You are welcome!

And your themes are amazing. All of them (modus, ef-themes, standard).

I comment here since ef-themes is composed by a large set of themes and it is a pitty to have to select just two to toggle between. But my suggestion would be to repurpose the bits below to make a theme switcher that's available for different themes (yours or not).

Sounds good!

Feel free to either ignore completely, apply the suggestion for ef-themes alone or make my dreams come true :smile:

I would not ignore it anyway. We can discuss it and see how it goes.

I'm very new to elisp so please excuse my jargon, which I believe is mostly incorrect ATM.

Suggestion

Make a standalone theme switcher that accepts an alist of light/dark themes. Here's a working sample:

[... 41 lines elided]

That way users can customize that list and toggle them all with a single command/key chord.

This is looking good. The only problem I see with it is that it should not be limited to any specific theme package. Rather, we need a new package that offers this feature, perhaps proposing some likely defaults.

Following the sample code above I'm using:

(defvar light-dark-themes
 '((standard-light . standard-dark)
   (modus-operandi . modus-vivendi)
   (ef-elea-light . ef-elea-dark))
 "Pairs of light/dark themes.")

(use-package pzs-theme
  :ensure nil
  :custom
  (pzs-theme-alist light-dark-themes)
  :init
  (load-theme 'ef-elea-light :no-confirm))

Yes, this is the idea I have in mind for a new package and how it would look like.

There're a few extras that can be useful as well. For instance the alist can be converted to a list of atoms with something like


(defun alist-to-list (alist)
  "List of atoms from an `ALIST'."
  (let ((array ()) pair)
    (while (setq pair (pop alist))
      (let* ((key (car pair))
             (value (cdr pair)))
        (push key array)
        (push value array)))
    array))

Very well! There are interesting options that open up.

And used with completing-read to implement a load-theme alternative that shows only the themes the user defined. I didn't implement it myself, since I also use consult, so I'm doing:

(setq consult-themes (alist-to-list light-dark-themes))

Implementing it yourself would not be a problem. The idea is good either way.

While I'm fine with those bits of code in my emacs config I would be even happier if you can take care of them on a hopefully easy to implement, easier to maintain and way better documented package.

You mean that I should incorporate them in the ef-themes? I think they do not belong here. Or do you mean for me to provide/maintain this new package?

I know you're doing a lot of work for the community, so please consider this a friendly suggestion and not a request that rushes you to commit more work than you already do.

It is all good. Thank you!

-- Protesilaos Stavrou https://protesilaos.com

pazos commented 1 year ago

Hi, Prot. Thanks for your time

Yes, this is the idea I have in mind for a new package and how it would look like.

Great news, indeed.

Or do you mean for me to provide/maintain this new package?

Yes, I would use it :) I'm fairly sure others would find it interesting too.

Feel free to repurpose any bits of the code above as you find repurporsable :), they're in the public domain.