emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/ef-themes 95d922fb08 3/4: Implement user option ef-them


From: ELPA Syncer
Subject: [elpa] externals/ef-themes 95d922fb08 3/4: Implement user option ef-themes-headings
Date: Fri, 19 Aug 2022 04:57:34 -0400 (EDT)

branch: externals/ef-themes
commit 95d922fb080fd46842995ba9280ff9a9a666369d
Author: Protesilaos Stavrou <info@protesilaos.com>
Commit: Protesilaos Stavrou <info@protesilaos.com>

    Implement user option ef-themes-headings
    
    I think this is necessary as (i) it is impossible to find a scale that
    works for everyone, (ii) this option does not complicate the maintenance
    of the project as it does not affect colour combinations.
---
 README.org   | 112 +++++++++++++++++++++++++++
 ef-themes.el | 243 +++++++++++++++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 322 insertions(+), 33 deletions(-)

diff --git a/README.org b/README.org
index ca85d162a3..7378d4f2f9 100644
--- a/README.org
+++ b/README.org
@@ -138,6 +138,17 @@ Everything is in place to set up the package.
 ;; Also those which are optimized for deuteranopia (red-green color
 ;; deficiency): `ef-deuteranopia-dark', `ef-deuteranopia-light'.
 
+(setq ef-themes-headings ; read the manual's entry of the doc string
+      '((0 . (variable-pitch light 1.9))
+        (1 . (variable-pitch light 1.8))
+        (2 . (variable-pitch regular 1.7))
+        (3 . (variable-pitch regular 1.6))
+        (4 . (variable-pitch regular 1.5))
+        (5 . (variable-pitch 1.4)) ; absence of weight means `bold'
+        (6 . (variable-pitch 1.3))
+        (7 . (variable-pitch 1.2))
+        (t . (variable-pitch 1.1))))
+
 ;; We also provide these commands, but do not assign them to any key:
 ;;
 ;; - `ef-themes-select'
@@ -160,6 +171,107 @@ nonetheless, provide a light and a dark theme that are 
optimized for
 such users.  The named of the themes are: ~ef-deuteranopia-dark~ and
 ~ef-deuteranopia-light~ ([[#h:75d74aea-d17f-497f-a3b8-f0bf4c372de0][Loading a 
theme]]).
 
+* Customization options
+:PROPERTIES:
+:CUSTOM_ID: h:db8ba158-22f6-49f7-b2f2-1c8162e690dd
+:END:
+
+The =ef-themes= provide a limited set of user options which tweak
+secondary aspects of the theme.  No option affects coloration or the
+overall character of each theme 
([[#h:a6dd030c-6b6c-4992-83e8-3438b4607b51][Principles]]).
+
+** Option for headings
+:PROPERTIES:
+:CUSTOM_ID: h:a7a02817-e324-43e9-a7d8-fde024530af6
+:END:
+
+[ Part of {{{development-version}}} ]
+
+#+vindex: ef-themes-headings
+The user option ~ef-themes-headings~ provides support for individual
+heading styles for levels 0 through 8.
+
+This is an alist that accepts a =(key . list-of-values)= combination.
+The key is either a number, representing the heading's level (0
+through 8) or =t=, which pertains to the fallback style.
+
+Level 0 is a special heading: it is used for what counts as a document
+title or equivalent, such as the =#+title= construct we find in Org
+files.  Levels 1-8 are regular headings.
+
+The list of values covers symbols that refer to properties, as described
+below.  Here is a complete sample, followed by a presentation of all
+available properties:
+
+#+begin_src emacs-lisp
+(setq ef-themes-headings
+      '((1 . (light variable-pitch 1.5))
+        (2 . (regular 1.3))
+        (3 . (1.1))
+        (t . (variable-pitch))))
+#+end_src
+
+By default (a =nil= value for this variable), all headings have a bold
+typographic weight, a font family that is the same as the ~default~ face
+(typically monospaced), and a height that is equal to the ~default~
+face's height.
+
+- A ~variable-pitch~ property changes the font family of the heading to
+  that of the ~variable-pitch~ face (normally a proportionately spaced
+  typeface).  Also check the =fontaine= package (by Protesilaos) for
+  tweaking fonts via faces.
+
+- The symbol of a weight attribute adjusts the font of the heading
+  accordingly, such as ~light~, ~semibold~, etc.  Valid symbols are
+  defined in the variable ~ef-themes-weights~.  The absence of a weight
+  means that bold will be used by virtue of inheriting the ~bold~ face.
+
+- A number, expressed as a floating point (e.g. 1.5), adjusts the height
+  of the heading to that many times the base font size.  The default
+  height is the same as 1.0, though it need not be explicitly stated.
+  Instead of a floating point, an acceptable value can be in the form of
+  a cons cell like =(height . FLOAT)= or =(height FLOAT)=, where =FLOAT=
+  is the given number.
+
+Combinations of any of those properties are expressed as a list, like in
+these examples:
+
+#+begin_src emacs-lisp
+(semibold)
+(variable-pitch semibold)
+(variable-pitch semibold 1.3)
+(variable-pitch semibold (height 1.3))   ; same as above
+(variable-pitch semibold (height . 1.3)) ; same as above
+#+end_src
+
+The order in which the properties are set is not significant.
+
+In user configuration files the form may look like this:
+
+#+begin_src emacs-lisp
+(setq ef-themes-headings
+      '((1 . (light variable-pitch 1.5))
+        (2 . (regular 1.3))
+        (3 . (1.1))
+        (t . (variable-pitch))))
+#+end_src
+
+When defining the styles per heading level, it is possible to
+pass a non-nil value (t) instead of a list of properties.  This
+will retain the original aesthetic for that level.  For example:
+
+#+begin_src emacs-lisp
+(setq ef-themes-headings
+      '((1 . t)           ; keep the default style
+              (2 . (variable-pitch 1.2))
+              (t . (variable-pitch)))) ; style for all other headings
+
+(setq ef-themes-headings
+      '((1 . (variable-pitch 1.6))
+              (2 . (1.3))
+              (t . t))) ; default style for all other levels
+#+end_src
+
 * Principles
 :PROPERTIES:
 :CUSTOM_ID: h:a6dd030c-6b6c-4992-83e8-3438b4607b51
diff --git a/ef-themes.el b/ef-themes.el
index e5caa7b9c9..cc58c9d42b 100644
--- a/ef-themes.el
+++ b/ef-themes.el
@@ -54,6 +54,166 @@ This is used by the commands `ef-themes-select' and
 `ef-themes-load-random'."
   :type 'hook
   :group 'ef-themes)
+
+(defconst ef-themes-weights
+  '( thin ultralight extralight light semilight regular medium
+     semibold bold heavy extrabold ultrabold)
+  "List of font weights.")
+
+(defconst ef-themes--headings-choice
+  '(set :tag "Properties" :greedy t
+        (const :tag "Proportionately spaced font (variable-pitch)" 
variable-pitch)
+        (choice :tag "Font weight (must be supported by the typeface)"
+                (const :tag "Bold (default)" nil)
+                (const :tag "Thin" thin)
+                (const :tag "Ultra-light" ultralight)
+                (const :tag "Extra-light" extralight)
+                (const :tag "Light" light)
+                (const :tag "Semi-light" semilight)
+                (const :tag "Regular" regular)
+                (const :tag "Medium" medium)
+                (const :tag "Semi-bold" semibold)
+                (const :tag "Extra-bold" extrabold)
+                (const :tag "Ultra-bold" ultrabold))
+        (radio :tag "Height"
+               (float :tag "Floating point to adjust height by")
+               (cons :tag "Cons cell of `(height . FLOAT)'"
+                     (const :tag "The `height' key (constant)" height)
+                     (float :tag "Floating point"))))
+  "Refer to the doc string of `ef-themes-headings'.
+This is a helper variable intended for internal use.")
+
+(defcustom ef-themes-headings nil
+  "Heading styles with optional list of values for levels 0-8.
+
+This is an alist that accepts a (key . list-of-values)
+combination.  The key is either a number, representing the
+heading's level (0-8) or t, which pertains to the fallback style.
+
+Level 0 is a special heading: it is used for what counts as a
+document title or equivalent, such as the #+title construct we
+find in Org files.  Levels 1-8 are regular headings.
+
+The list of values covers symbols that refer to properties, as
+described below.  Here is a complete sample, followed by a
+presentation of all available properties:
+
+    (setq ef-themes-headings
+          (quote ((1 . (light variable-pitch 1.5))
+                  (2 . (regular 1.3))
+                  (3 . (1.1))
+                  (t . (variable-pitch)))))
+
+By default (a nil value for this variable), all headings have a
+bold typographic weight, a font family that is the same as the
+`default' face (typically monospaced), and a height that is equal
+to the `default' face's height.
+
+- A `variable-pitch' property changes the font family of the
+  heading to that of the `variable-pitch' face (normally a
+  proportionately spaced typeface).  Also check the `fontaine'
+  package (by Protesilaos) for tweaking fonts via faces.
+
+- The symbol of a weight attribute adjusts the font of the
+  heading accordingly, such as `light', `semibold', etc.  Valid
+  symbols are defined in the variable `ef-themes-weights'.  The
+  absence of a weight means that bold will be used by virtue of
+  inheriting the `bold' face.
+
+- A number, expressed as a floating point (e.g. 1.5), adjusts the
+  height of the heading to that many times the base font size.
+  The default height is the same as 1.0, though it need not be
+  explicitly stated.  Instead of a floating point, an acceptable
+  value can be in the form of a cons cell like (height . FLOAT)
+  or (height FLOAT), where FLOAT is the given number.
+
+Combinations of any of those properties are expressed as a list,
+like in these examples:
+
+    (semibold)
+    (variable-pitch semibold)
+    (variable-pitch semibold 1.3)
+    (variable-pitch semibold (height 1.3))   ; same as above
+    (variable-pitch semibold (height . 1.3)) ; same as above
+
+The order in which the properties are set is not significant.
+
+In user configuration files the form may look like this:
+
+    (setq ef-themes-headings
+          (quote ((1 . (light variable-pitch 1.5))
+                  (2 . (regular 1.3))
+                  (3 . (1.1))
+                  (t . (variable-pitch)))))
+
+When defining the styles per heading level, it is possible to
+pass a non-nil value (t) instead of a list of properties.  This
+will retain the original aesthetic for that level.  For example:
+
+    (setq ef-themes-headings
+          (quote ((1 . t)           ; keep the default style
+                  (2 . (variable-pitch 1.2))
+                  (t . (variable-pitch))))) ; style for all other headings
+
+    (setq ef-themes-headings
+          (quote ((1 . (variable-pitch 1.6))
+                  (2 . (1.3))
+                  (t . t)))) ; default style for all other levels"
+  :group 'ef-themes
+  :package-version '(ef-themes . "0.3.0")
+  :version "29.1"
+  :type `(alist
+          :options ,(mapcar (lambda (el)
+                              (list el ef-themes--headings-choice))
+                            '(0 1 2 3 4 5 6 7 8 t))
+          :key-type symbol
+          :value-type ,ef-themes--headings-choice)
+  :link '(info-link "(ef-themes) Heading styles"))
+
+;;; Helpers for user options
+
+(defun ef-themes--key-cdr (key alist)
+  "Get cdr of KEY in ALIST."
+  (cdr (assoc key alist)))
+
+(defun ef-themes--alist-or-seq (properties alist-key seq-pred seq-default)
+  "Return value from alist or sequence.
+Check PROPERTIES for an alist value that corresponds to
+ALIST-KEY.  If no alist is present, search the PROPERTIES
+sequence given SEQ-PRED, using SEQ-DEFAULT as a fallback."
+  (if-let* ((val (or (alist-get alist-key properties)
+                     (seq-find seq-pred properties seq-default)))
+            ((listp val)))
+      (car val)
+    val))
+
+(defun ef-themes--weight (list)
+  "Search for `ef-themes--heading' weight in LIST."
+  (catch 'found
+    (dolist (elt list)
+      (when (memq elt ef-themes-weights)
+        (throw 'found elt)))))
+
+(defun ef-themes--heading (level)
+  "Conditional styles for `ef-themes-headings' per LEVEL heading."
+  (let* ((key (ef-themes--key-cdr level ef-themes-headings))
+         (style (or key (ef-themes--key-cdr t ef-themes-headings)))
+         (style-listp (listp style))
+         (properties style)
+         (var (when (memq 'variable-pitch properties) 'variable-pitch))
+         (varbold (if var
+                      (append (list 'bold) (list var))
+                    'bold))
+         (weight (when style-listp (ef-themes--weight style))))
+    (list :inherit
+          (cond
+           (weight var)
+           (varbold))
+          :height
+          (ef-themes--alist-or-seq properties 'height #'floatp 'unspecified)
+          :weight
+          (or weight 'unspecified))))
+
 ;;; Commands and their helper functions
 
 (defconst ef-themes-light-themes '( ef-day ef-light ef-spring ef-summer
@@ -225,12 +385,19 @@ Helper function for `ef-themes-preview-colors'."
 
 ;;; Faces and variables
 
+(defgroup ef-themes-faces ()
+  "Faces defined by the Ef themes."
+  :group 'ef-themes
+  :link '(info-link "(ef-themes) Top")
+  :prefix "ef-themes-"
+  :tag "Ef Themes Faces")
+
 ;; This produces `ef-themes-height-0' and the like.
 (defmacro ef-themes--height (n)
-  "Write `defvar' for height level N."
-  `(defcustom ,(intern (format "ef-themes-height-%s" n)) ,(- 1.8 (* n 0.1))
-     ,(format "Height as floating point for %i level heading." n)
-     :type 'float))
+  "Write `defface' for height level N."
+  `(defface ,(intern (format "ef-themes-heading-%s" n)) nil
+     ,(format "Used for level %s heading." n)
+     :group 'ef-themes-faces))
 
 ;; FIXME 2022-08-18: Why won't `dotimes' work with the macro?  (dotimes
 ;; (n 8) ...) does not interpret the n as a number.
@@ -246,6 +413,16 @@ Helper function for `ef-themes-preview-colors'."
 
 (defconst ef-themes-faces
   '(
+;;;; internal faces for headings
+    `(ef-themes-heading-0 ((,c ,@(ef-themes--heading 0) :foreground 
,rainbow-0)))
+    `(ef-themes-heading-1 ((,c ,@(ef-themes--heading 1) :foreground 
,rainbow-1)))
+    `(ef-themes-heading-2 ((,c ,@(ef-themes--heading 2) :foreground 
,rainbow-2)))
+    `(ef-themes-heading-3 ((,c ,@(ef-themes--heading 3) :foreground 
,rainbow-3)))
+    `(ef-themes-heading-4 ((,c ,@(ef-themes--heading 4) :foreground 
,rainbow-4)))
+    `(ef-themes-heading-5 ((,c ,@(ef-themes--heading 5) :foreground 
,rainbow-5)))
+    `(ef-themes-heading-6 ((,c ,@(ef-themes--heading 6) :foreground 
,rainbow-6)))
+    `(ef-themes-heading-7 ((,c ,@(ef-themes--heading 7) :foreground 
,rainbow-7)))
+    `(ef-themes-heading-8 ((,c ,@(ef-themes--heading 8) :foreground 
,rainbow-8)))
 ;;;; all basic faces
     `(default ((,c :background ,bg-main :foreground ,fg-main)))
     `(cursor ((,c :background ,cursor)))
@@ -587,10 +764,10 @@ Helper function for `ef-themes-preview-colors'."
     `(info-menu-header ((,c :inherit bold)))
     `(info-menu-star ((,c :foreground ,red)))
     `(info-node ((,c :inherit bold)))
-    `(info-title-1 ((,c :inherit bold :foreground ,rainbow-1 :height 
,ef-themes-height-1)))
-    `(info-title-2 ((,c :inherit bold :foreground ,rainbow-2 :height 
,ef-themes-height-2)))
-    `(info-title-3 ((,c :inherit bold :foreground ,rainbow-3 :height 
,ef-themes-height-3)))
-    `(info-title-4 ((,c :inherit bold :foreground ,rainbow-4 :height 
,ef-themes-height-4)))
+    `(info-title-1 ((,c :inherit ef-themes-heading-1)))
+    `(info-title-2 ((,c :inherit ef-themes-heading-2)))
+    `(info-title-3 ((,c :inherit ef-themes-heading-3)))
+    `(info-title-4 ((,c :inherit ef-themes-heading-4)))
 ;;;; isearch, occur, and the like
     `(isearch ((,c :background ,bg-yellow :foreground ,fg-intense)))
     `(isearch-fail ((,c :background ,bg-red :foreground ,fg-intense)))
@@ -733,12 +910,12 @@ Helper function for `ef-themes-preview-colors'."
     `(markdown-code-face ((,c :background ,bg-inactive :extend t)))
     `(markdown-gfm-checkbox-face ((,c :foreground ,warning)))
     `(markdown-header-face (( )))
-    `(markdown-header-face-1 ((,c :inherit bold :foreground ,rainbow-0 :height 
,ef-themes-height-1)))
-    `(markdown-header-face-2 ((,c :inherit bold :foreground ,rainbow-1 :height 
,ef-themes-height-2)))
-    `(markdown-header-face-3 ((,c :inherit bold :foreground ,rainbow-2 :height 
,ef-themes-height-3)))
-    `(markdown-header-face-4 ((,c :inherit bold :foreground ,rainbow-3 :height 
,ef-themes-height-4)))
-    `(markdown-header-face-5 ((,c :inherit bold :foreground ,rainbow-4 :height 
,ef-themes-height-5)))
-    `(markdown-header-face-6 ((,c :inherit bold :foreground ,rainbow-5 :height 
,ef-themes-height-6)))
+    `(markdown-header-face-1 ((,c :inherit ef-themes-heading-1)))
+    `(markdown-header-face-2 ((,c :inherit ef-themes-heading-2)))
+    `(markdown-header-face-3 ((,c :inherit ef-themes-heading-3)))
+    `(markdown-header-face-4 ((,c :inherit ef-themes-heading-4)))
+    `(markdown-header-face-5 ((,c :inherit ef-themes-heading-5)))
+    `(markdown-header-face-6 ((,c :inherit ef-themes-heading-6)))
     `(markdown-highlighting-face ((,c :background ,bg-info :foreground ,info)))
     `(markdown-inline-code-face ((,c :foreground ,accent-1))) ; same as 
`org-code'
     `(markdown-italic-face ((,c :inherit italic)))
@@ -852,7 +1029,7 @@ Helper function for `ef-themes-preview-colors'."
     `(org-agenda-clocking ((,c :background ,bg-alt :foreground ,red-warmer)))
     `(org-agenda-column-dateline ((,c :background ,bg-alt)))
     `(org-agenda-current-time ((,c :foreground ,variable)))
-    `(org-agenda-date ((,c :foreground ,date :height ,ef-themes-height-3)))
+    `(org-agenda-date ((,c :inherit ef-themes-heading-3)))
     `(org-agenda-date-today ((,c :inherit org-agenda-date :underline t)))
     `(org-agenda-date-weekend ((,c :inherit org-agenda-date)))
     `(org-agenda-date-weekend-today ((,c :inherit org-agenda-date-today)))
@@ -864,7 +1041,7 @@ Helper function for `ef-themes-preview-colors'."
     `(org-agenda-filter-regexp ((,c :inherit success)))
     `(org-agenda-filter-tags ((,c :inherit success)))
     `(org-agenda-restriction-lock ((,c :background ,bg-dim :foreground 
,fg-dim)))
-    `(org-agenda-structure ((,c :height ,ef-themes-height-0)))
+    `(org-agenda-structure ((,c :inherit ef-themes-heading-0)))
     `(org-agenda-structure-filter ((,c :inherit (warning 
org-agenda-structure))))
     `(org-agenda-structure-secondary ((,c :foreground ,rainbow-1)))
     `(org-archived ((,c :background ,bg-alt :foreground ,fg-alt)))
@@ -883,7 +1060,7 @@ Helper function for `ef-themes-preview-colors'."
     `(org-dispatcher-highlight ((,c :inherit (bold secondary-selection))))
     `(org-document-info ((,c :foreground ,rainbow-1)))
     `(org-document-info-keyword ((,c :inherit shadow)))
-    `(org-document-title ((,c :foreground ,rainbow-0 :height 
,ef-themes-height-0)))
+    `(org-document-title ((,c :inherit ef-themes-heading-0)))
     `(org-done ((,c :foreground ,info)))
     `(org-drawer ((,c :inherit shadow)))
     `(org-ellipsis (( ))) ; inherits from the heading's color
@@ -895,14 +1072,14 @@ Helper function for `ef-themes-preview-colors'."
     `(org-indent ((,c :inherit org-hide)))
     `(org-imminent-deadline ((,c :inherit bold :foreground ,err)))
     `(org-latex-and-related ((,c :foreground ,type)))
-    `(org-level-1 ((,c :inherit bold :foreground ,rainbow-1 :height 
,ef-themes-height-1)))
-    `(org-level-2 ((,c :inherit bold :foreground ,rainbow-2 :height 
,ef-themes-height-2)))
-    `(org-level-3 ((,c :inherit bold :foreground ,rainbow-3 :height 
,ef-themes-height-3)))
-    `(org-level-4 ((,c :inherit bold :foreground ,rainbow-4 :height 
,ef-themes-height-4)))
-    `(org-level-5 ((,c :inherit bold :foreground ,rainbow-5 :height 
,ef-themes-height-5)))
-    `(org-level-6 ((,c :inherit bold :foreground ,rainbow-6 :height 
,ef-themes-height-6)))
-    `(org-level-7 ((,c :inherit bold :foreground ,rainbow-7 :height 
,ef-themes-height-7)))
-    `(org-level-8 ((,c :inherit bold :foreground ,rainbow-8 :height 
,ef-themes-height-8)))
+    `(org-level-1 ((,c :inherit ef-themes-heading-1)))
+    `(org-level-2 ((,c :inherit ef-themes-heading-2)))
+    `(org-level-3 ((,c :inherit ef-themes-heading-3)))
+    `(org-level-4 ((,c :inherit ef-themes-heading-4)))
+    `(org-level-5 ((,c :inherit ef-themes-heading-5)))
+    `(org-level-6 ((,c :inherit ef-themes-heading-6)))
+    `(org-level-7 ((,c :inherit ef-themes-heading-7)))
+    `(org-level-8 ((,c :inherit ef-themes-heading-8)))
     `(org-link ((,c :inherit link)))
     `(org-list-dt ((,c :inherit bold)))
     `(org-macro ((,c :foreground ,accent-2)))
@@ -941,14 +1118,14 @@ Helper function for `ef-themes-preview-colors'."
     `(org-modern-time-inactive ((,c :inherit org-modern-date-inactive)))
     `(org-modern-todo ((,c :background ,bg-err :foreground ,err)))
 ;;;; outline-mode
-    `(outline-1 ((,c :inherit bold :foreground ,rainbow-1 :height 
,ef-themes-height-1)))
-    `(outline-2 ((,c :inherit bold :foreground ,rainbow-2 :height 
,ef-themes-height-2)))
-    `(outline-3 ((,c :inherit bold :foreground ,rainbow-3 :height 
,ef-themes-height-3)))
-    `(outline-4 ((,c :inherit bold :foreground ,rainbow-4 :height 
,ef-themes-height-4)))
-    `(outline-5 ((,c :inherit bold :foreground ,rainbow-5 :height 
,ef-themes-height-5)))
-    `(outline-6 ((,c :inherit bold :foreground ,rainbow-6 :height 
,ef-themes-height-6)))
-    `(outline-7 ((,c :inherit bold :foreground ,rainbow-7 :height 
,ef-themes-height-7)))
-    `(outline-8 ((,c :inherit bold :foreground ,rainbow-8 :height 
,ef-themes-height-8)))
+    `(outline-1 ((,c :inherit ef-themes-heading-1)))
+    `(outline-2 ((,c :inherit ef-themes-heading-2)))
+    `(outline-3 ((,c :inherit ef-themes-heading-3)))
+    `(outline-4 ((,c :inherit ef-themes-heading-4)))
+    `(outline-5 ((,c :inherit ef-themes-heading-5)))
+    `(outline-6 ((,c :inherit ef-themes-heading-6)))
+    `(outline-7 ((,c :inherit ef-themes-heading-7)))
+    `(outline-8 ((,c :inherit ef-themes-heading-8)))
 ;;;; outline-minor-faces
     `(outline-minor-0 (( )))
 ;;;; package (M-x list-packages)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]