Subject: bug#45068: Patch for Modus themes 1.1.1?

From: Protesilaos Stavrou <[email-masked]>
Date: Sun, 28 Feb 2021 08:30:16 +0200

On 2021-02-27, 10:15 +0200, Eli Zaretskii <[email-masked]> wrote:

>> From: Protesilaos Stavrou <[email-masked]>
>> Cc: [email-masked]
>> Date: Sat, 27 Feb 2021 04:35:49 +0200
>> 
>> > A simple implementation that checks whether a theme is already loaded,
>> > and if not, looks it up in a suitable list of directories and loads
>> > when found.  The main part is to make sure themes are looked up in the
>> > directories where we expect them to be, as opposed to load-path, which
>> > is where 'require' looks for files to load.  A Lisp implementation
>> > should be fine, I think.
>> >
>> > Let me know if you need further clarifications.
>> 
>> Hello Eli,
>> 
>> This is what I could come up with.  It is not what you stipulated, as it
>> only accounts for the default themes' directory instead of checking the
>> 'custom-theme-load-path'.
>
> Hmm... I'm surprised.  What I had in mind was a simple use of
> locate-file, which already accepts a path argument, so you could pass
> custom-theme-load-path to it, and it would do the job.
>
> Maybe I misunderstand or misremember the problem which led us here.
> Wasn't the problem that 'load' and 'require' search along load-path
> instead of custom-theme-load-path?  IOW, could you show the code you'd
> use to load the other components of the theme if you could use 'load'
> and 'require'?  My idea was simply to replace
>
>   (require 'foo-themes)
>
> with
>
>   (require-theme 'foo-themes)
>
> Would that solve your original problem, assuming that require-theme
> would look for and load foo-themes.el?
>
> Thanks.

I retried and feel I am now closer to what you have described.  The
following is meant to go in custom.el:

    (defun require-theme (theme &optional directories)
      "Load THEME stored in `custom-theme-load-path'.

    THEME is a symbol or string that corresponds to the file name without
    its file type extension.  That is assumed to be either '.el' or '.elc'.

    If THEME names a valid theme, load and enable it.  Otherwise load the
    file, if present.  In the latter case, the file is intended to work as
    the basis of a theme declared with `deftheme'.

    With optional DIRECTORIES as a list of filesystem paths, search
    for THEME file in those locations instead and load it, if present."
      (let* ((theme-dirs (custom-theme--load-path))
             (custom-dirs (when (and directories (listp directories))
                            directories))
             (theme-name (cond
                          ((stringp theme)
                           theme)
                          ((symbolp theme)
                           (format "%s" theme))
                          (t
                           (error "`%s' must be either a symbol or string" theme))))
             (dirs (or custom-dirs theme-dirs))
             (file (locate-file theme-name dirs '(".el" ".elc"))))
        (cond
         ((custom-theme-p theme)
          (load-theme theme t))
         (file
          (load-file file)))))

This works in two ways:

1. To load a theme's dependency:

   (require-theme 'modus-themes)

2. To load and enable a theme:

   (require-theme 'modus-operandi)

I am using functionality 1 on a newly compiled Emacs with 'emacs -Q'.  I
placed my three files in etc/themes (modus-{operandi,vivendi}-theme.el
and modus-themes.el) and tried 'M-x load-theme RET modus-operandi' and
the same for modus-vivendi, as well as 'M-x customize-themes'.

-- 
Protesilaos Stavrou
protesilaos.com