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

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

[elpa] externals/cursory 88820a72b7 2/4: Make presets optionally inherit


From: ELPA Syncer
Subject: [elpa] externals/cursory 88820a72b7 2/4: Make presets optionally inherit from another; refactor code
Date: Fri, 9 Jun 2023 03:57:47 -0400 (EDT)

branch: externals/cursory
commit 88820a72b78863bec28d07a3f9e4a71f55de33cb
Author: Protesilaos Stavrou <info@protesilaos.com>
Commit: Protesilaos Stavrou <info@protesilaos.com>

    Make presets optionally inherit from another; refactor code
---
 README.org |  76 +++++++++++++++++-----
 cursory.el | 209 +++++++++++++++++++++++++++++++++++++++++++------------------
 2 files changed, 208 insertions(+), 77 deletions(-)

diff --git a/README.org b/README.org
index 00956c86f7..b88ad868bb 100644
--- a/README.org
+++ b/README.org
@@ -41,6 +41,7 @@ Current development target is {{{development-version}}}.
     + GitHub: <https://github.com/protesilaos/cursory>
     + GitLab: <https://gitlab.com/protesilaos/cursory>
 + Mailing list: <https://lists.sr.ht/~protesilaos/cursory>
++ Backronym: Cursor Usability Requires Styles Objectively Rated Yearlong
 
 #+toc: headlines 8 insert TOC here, with eight headline levels
 
@@ -69,25 +70,30 @@ modify this GNU manual.”
 :END:
 
 Cursory provides a thin wrapper around built-in variables that affect
-the style of the Emacs cursor on graphical terminals.  The intent is to
-allow the user to define preset configurations such as "block with slow
-blinking" or "bar with fast blinking" and set them on demand.
+the style of the Emacs cursor on graphical terminals.  The intent is
+to allow the user to define preset configurations such as "block with
+slow blinking" or "bar with fast blinking" and set them on demand.
+The use-case for such presets is to adapt to evolving interface
+requirements and concomitant levels of expected comfort, such as in
+the difference between writing and reading.
 
 #+vindex: cursory-presets
 #+findex: cursory-set-preset
 The user option ~cursory-presets~ holds the presets.  The command
-~cursory-set-preset~ is used to select one among them.  Selection
-supports minibuffer completion when there are multiple presets, else
-sets the single preset outright.
+~cursory-set-preset~ is applies one among them.  The command supports
+minibuffer completion when there are multiple presets, else sets the
+single preset outright.
 
-Presets consist of a list of properties that govern the cursor type in
-the active and inactive windows, as well as cursor blinking variables.
+Presets consist of an arbitrary symbol broadly described the style set
+followed by a list of properties that govern the cursor type in the
+active and inactive windows, as well as cursor blinking variables.
 They look like this:
 
 #+begin_src emacs-lisp
 (bar
  :cursor-type (bar . 2)
  :cursor-in-non-selected-windows hollow
+ :blink-cursor-mode 1
  :blink-cursor-blinks 10
  :blink-cursor-interval 0.5
  :blink-cursor-delay 0.2)
@@ -102,14 +108,40 @@ references.
 
 A property of =:blink-cursor-mode= is also available.  It is a numeric
 value of either =1= or =-1= and is given to the function
-~blink-cursor-mode~ (=1= is to enable, =-1= is to disable the mode).
+~blink-cursor-mode~: =1= is to enable, =-1= is to disable the mode.
 
-A preset whose car is =t= is treated as the default option.  This makes
-it possible to specify multiple presets without duplicating their
-properties.  The other presets beside =t= act as overrides of the
-defaults and, as such, need only consist of the properties that change
-from the default.  See the original value of this variable for how that
-is done:
+Presets can inherit from each other.  Using the special =:inherit=
+property, like this:
+
+#+begin_src emacs-lisp
+(bar
+ :cursor-type (bar . 2)
+ :cursor-in-non-selected-windows hollow
+ :blink-cursor-mode 1
+ :blink-cursor-blinks 10
+ :blink-cursor-interval 0.5
+ :blink-cursor-delay 0.2)
+(bar-no-other-window
+ :inherit bar
+ :cursor-in-non-selected-windows nil)
+#+end_src
+
+In the above example, the =bar-no-other-window= is the same as =bar=
+except for the value of =:cursor-in-non-selected-windows=.
+
+The value given to the =:inherit= property corresponds to the name of
+another named preset (unquoted).  This tells the relevant Cursory
+functions to get the properties of that given preset and blend them
+with those of the current one.  The properties of the current preset
+take precedence over those of the inherited one, thus overriding them.
+
+A preset whose car is =t= is treated as the default option.  This
+makes it possible to specify multiple presets without duplicating
+their properties.  The other presets beside =t= act as overrides of
+the defaults and, as such, need only consist of the properties that
+change from the default.  In the case of an =:inherit=, properties are
+first taken from the inherited preset and then the default one.  See
+the original value of this variable for how that is done:
 
 #+begin_src emacs-lisp
 (defcustom cursory-presets
@@ -120,9 +152,15 @@ is done:
     (bar
      :cursor-type (bar . 2)
      :blink-cursor-interval 0.5)
+    (bar-no-other-window
+     :inherit bar
+     :cursor-in-non-selected-windows nil)
     (underscore
      :cursor-type (hbar . 3)
      :blink-cursor-blinks 50)
+    (underscore-thin-other-window
+     :inherit underscore
+     :cursor-in-non-selected-windows (hbar . 1))
     (t ; the default values
      :cursor-type box
      :cursor-in-non-selected-windows hollow
@@ -145,7 +183,11 @@ The default behaviour of ~cursory-set-preset~ is to change 
cursors
 globally.  The user can, however, limit the effect to the current
 buffer.  With interactive use, this is done by invoking the command with
 a universal prefix argument (=C-u= by default).  When called from Lisp,
-the LOCAL argument must be non-nil.
+the LOCAL argument must be non-nil, thus:
+
+#+begin_src emacs-lisp
+(cursory-set-preset 'bar :local)
+#+end_src
 
 #+findex: cursory-store-latest-preset
 #+vindex: cursory-latest-state-file
@@ -154,6 +196,8 @@ The function ~cursory-store-latest-preset~ is used to save 
the last
 selected style in the ~cursory-latest-state-file~.  The value can then
 be restored with the ~cursory-restore-latest-preset~ function.
 
+[[#h:b3c38cda-48d3-4715-9c46-6b9844a6da86][Sample configuration]].
+
 * Installation
 :PROPERTIES:
 :CUSTOM_ID: h:6dd596f2-d98b-4275-b25e-495e2a0616bf
diff --git a/cursory.el b/cursory.el
index d0c041f7d4..5e250e812d 100644
--- a/cursory.el
+++ b/cursory.el
@@ -28,22 +28,27 @@
 ;;; Commentary:
 ;;
 ;; Cursory provides a thin wrapper around built-in variables that affect
-;; the style of the Emacs cursor on graphical terminals.  The intent is to
-;; allow the user to define preset configurations such as "block with slow
-;; blinking" or "bar with fast blinking" and set them on demand.
+;; the style of the Emacs cursor on graphical terminals.  The intent is
+;; to allow the user to define preset configurations such as "block with
+;; slow blinking" or "bar with fast blinking" and set them on demand.
+;; The use-case for such presets is to adapt to evolving interface
+;; requirements and concomitant levels of expected comfort, such as in
+;; the difference between writing and reading.
 ;;
 ;; The user option `cursory-presets' holds the presets.  The command
-;; `cursory-set-preset' is used to select one among them.  Selection
-;; supports minibuffer completion when there are multiple presets, else
-;; sets the single preset outright.
+;; `cursory-set-preset' is applies one among them.  The command supports
+;; minibuffer completion when there are multiple presets, else sets the
+;; single preset outright.
 ;;
-;; Presets consist of a list of properties that govern the cursor type in
-;; the active and inactive windows, as well as cursor blinking variables.
+;; Presets consist of an arbitrary symbol broadly described the style set
+;; followed by a list of properties that govern the cursor type in the
+;; active and inactive windows, as well as cursor blinking variables.
 ;; They look like this:
 ;;
 ;;     (bar
 ;;      :cursor-type (bar . 2)
 ;;      :cursor-in-non-selected-windows hollow
+;;      :blink-cursor-mode 1
 ;;      :blink-cursor-blinks 10
 ;;      :blink-cursor-interval 0.5
 ;;      :blink-cursor-delay 0.2)
@@ -57,14 +62,39 @@
 ;;
 ;; A property of `:blink-cursor-mode' is also available.  It is a numeric
 ;; value of either `1' or `-1' and is given to the function
-;; `blink-cursor-mode' (`1' is to enable, `-1' is to disable the mode).
+;; `blink-cursor-mode': `1' is to enable, `-1' is to disable the mode.
 ;;
-;; A preset whose car is `t' is treated as the default option.  This makes
-;; it possible to specify multiple presets without duplicating their
-;; properties.  The other presets beside `t' act as overrides of the
-;; defaults and, as such, need only consist of the properties that change
-;; from the default.  See the original value of this variable for how that
-;; is done:
+;; Presets can inherit from each other.  Using the special `:inherit'
+;; property, like this:
+;;
+;;     (bar
+;;      :cursor-type (bar . 2)
+;;      :cursor-in-non-selected-windows hollow
+;;      :blink-cursor-mode 1
+;;      :blink-cursor-blinks 10
+;;      :blink-cursor-interval 0.5
+;;      :blink-cursor-delay 0.2)
+;;
+;;     (bar-no-other-window
+;;      :inherit bar
+;;      :cursor-in-non-selected-windows nil)
+;;
+;; In the above example, the `bar-no-other-window' is the same as `bar'
+;; except for the value of `:cursor-in-non-selected-windows'.
+;;
+;; The value given to the `:inherit' property corresponds to the name of
+;; another named preset (unquoted).  This tells the relevant Cursory
+;; functions to get the properties of that given preset and blend them
+;; with those of the current one.  The properties of the current preset
+;; take precedence over those of the inherited one, thus overriding them.
+;;
+;; A preset whose car is `t' is treated as the default option.  This
+;; makes it possible to specify multiple presets without duplicating
+;; their properties.  The other presets beside `t' act as overrides of
+;; the defaults and, as such, need only consist of the properties that
+;; change from the default.  In the case of an `:inherit', properties are
+;; first taken from the inherited preset and then the default one.  See
+;; the original value of this variable for how that is done:
 ;;
 ;;     (defcustom cursory-presets
 ;;       '((box
@@ -74,9 +104,15 @@
 ;;         (bar
 ;;          :cursor-type (bar . 2)
 ;;          :blink-cursor-interval 0.5)
+;;         (bar-no-other-window
+;;          :inherit bar
+;;          :cursor-in-non-selected-windows nil)
 ;;         (underscore
 ;;          :cursor-type (hbar . 3)
 ;;          :blink-cursor-blinks 50)
+;;         (underscore-thin-other-window
+;;          :inherit underscore
+;;          :cursor-in-non-selected-windows (hbar . 1))
 ;;         (t ; the default values
 ;;          :cursor-type box
 ;;          :cursor-in-non-selected-windows hollow
@@ -96,7 +132,9 @@
 ;; globally.  The user can, however, limit the effect to the current
 ;; buffer.  With interactive use, this is done by invoking the command with
 ;; a universal prefix argument (`C-u' by default).  When called from Lisp,
-;; the LOCAL argument must be non-nil.
+;; the LOCAL argument must be non-nil, thus:
+;;
+;;     (cursory-set-preset 'bar :local)
 ;;
 ;; The function `cursory-store-latest-preset' is used to save the last
 ;; selected style in the `cursory-latest-state-file'.  The value can then
@@ -117,9 +155,15 @@
     (bar
      :cursor-type (bar . 2)
      :blink-cursor-interval 0.5)
+    (bar-no-other-window
+     :inherit bar
+     :cursor-in-non-selected-windows nil)
     (underscore
      :cursor-type (hbar . 3)
      :blink-cursor-blinks 50)
+    (underscore-thin-other-window
+     :inherit underscore
+     :cursor-in-non-selected-windows (hbar . 1))
     (t ; the default values
      :cursor-type box
      :cursor-in-non-selected-windows hollow
@@ -140,7 +184,7 @@ the defaults and, as such, need only consist of the 
properties
 that change from the default.  See the original value of this
 variable for how that is done.
 
-The cdr is a plist which specifies the cursor type and blink
+The `cdr' is a plist which specifies the cursor type and blink
 properties.  In particular, it accepts the following properties:
 
     :cursor-type
@@ -156,9 +200,23 @@ them accepts is the same as the variable it references.
 
 A property of `:blink-cursor-mode' is also available.  It is a
 numeric value of either 1 or -1 and is given to the function
-`blink-cursor-mode' (1 is to enable, -1 is to disable the mode)."
+`blink-cursor-mode' (1 is to enable, -1 is to disable the mode).
+
+Finally, the plist takes the special `:inherit' property.  Its
+value is contains the name of another named preset (unquoted).
+This tells the relevant Cursory functions to get the properties
+of that given preset and blend them with those of the current
+one.  The properties of the current preset take precedence over
+those of the inherited one, thus overriding them.  In practice,
+this is a way to have something like an underscore style with a
+hallow cursor for the other window and the same with a thin
+underscore for the other window (see the default value of this
+user option for concrete examples).  Remember that all named
+presets fall back to the preset whose name is t.  The `:inherit'
+is not a substitute for that generic fallback but rather an extra
+method of specifying font configuration presets."
   :group 'cursory
-  :package-version '(cursory . "0.3.0")
+  :package-version '(cursory . "1.0.0")
   :type `(alist
           :value-type
           (plist :options
@@ -181,7 +239,8 @@ numeric value of either 1 or -1 and is given to the function
                           :blink-cursor-mode)
                    (choice :value 1
                            (const :tag "Enable" 1)
-                           (const :tag "Disable" -1)))))
+                           (const :tag "Disable" -1)))
+                  ((const :tag "Inherit another preset" :inherit) symbol)))
           :key-type symbol))
 
 (defcustom cursory-latest-state-file
@@ -195,19 +254,31 @@ Saving is done by the `cursory-store-latest-preset' 
function."
 (defvar cursory--style-hist '()
   "Minibuffer history of `cursory--set-cursor-prompt'.")
 
-(defun cursory--preset-values (preset)
-  "Get properties of PRESET with relevant fallbacks."
-  (append (alist-get preset cursory-presets)
-          (alist-get t cursory-presets)))
+(defun cursory--preset-p (preset)
+  "Return non-nil if PRESET is one of the named `cursory-presets'."
+  (let ((presets (delq t (mapcar #'car cursory-presets))))
+    (memq preset presets)))
+
+(defun cursory--get-inherit-name (preset)
+  "Get the `:inherit' value of PRESET."
+  (when-let* ((inherit (plist-get (alist-get preset cursory-presets) :inherit))
+              (cursory--preset-p inherit))
+    inherit))
+
+(defun cursory--get-preset-properties (preset)
+  "Return list of properties for PRESET in `cursory-presets'."
+  (let ((presets cursory-presets))
+    (append (alist-get preset presets)
+            (when-let ((inherit (cursory--get-inherit-name preset)))
+              (alist-get inherit presets))
+            (alist-get t presets))))
 
 (defun cursory--presets-no-fallback ()
   "Return list of `cursory-presets', minus the fallback value."
-  (delete
-   nil
-   (mapcar (lambda (symbol)
-             (unless (eq (car symbol) t)
-               symbol))
-           cursory-presets)))
+  (seq-remove
+   (lambda (symbol)
+     (eq (car symbol) t))
+   cursory-presets))
 
 (defun cursory--set-cursor-prompt ()
   "Promp for `cursory-presets' (used by `cursory-set-preset')."
@@ -220,6 +291,48 @@ Saving is done by the `cursory-store-latest-preset' 
function."
      (cursory--presets-no-fallback)
      nil t nil 'cursory--style-hist def)))
 
+(defun cursory--get-preset-as-symbol (preset)
+  "Return PRESET as a symbol."
+  (if (stringp preset)
+      (intern preset)
+    preset))
+
+(defun cursory--delete-local-variables ()
+  "Delete all cursor-related local variables."
+  (dolist (var '( cursor-type cursor-in-non-selected-windows
+                  blink-cursor-blinks blink-cursor-interval
+                  blink-cursor-delay))
+    (kill-local-variable var)))
+
+(defun cursory--set-preset-with-scope (preset &optional local)
+  "Set PRESET of `cursory-presets' to the global scope.
+With optional non-nil LOCAL, set STYLES scoped locally to the
+current buffer."
+  (if-let ((styles (cursory--get-preset-properties preset)))
+      ;; We do not include this in the `if-let' because we also accept
+      ;; nil values for :cursor-type, :cursor-in-non-selected-windows.
+      (let ((type (plist-get styles :cursor-type))
+            (type-no-select (plist-get styles :cursor-in-non-selected-windows))
+            (blinks (plist-get styles :blink-cursor-blinks))
+            (interval (plist-get styles :blink-cursor-interval))
+            (delay (plist-get styles :blink-cursor-delay)))
+        (if local
+            (setq-local cursor-type type
+                        cursor-in-non-selected-windows type-no-select
+                        blink-cursor-blinks blinks
+                        blink-cursor-interval interval
+                        blink-cursor-delay delay)
+          (cursory--delete-local-variables)
+          (setq-default cursor-type type
+                        cursor-in-non-selected-windows type-no-select
+                        blink-cursor-blinks blinks
+                        blink-cursor-interval interval
+                        blink-cursor-delay delay)
+          ;; We only want to save global values in 
`cursory-store-latest-preset'.
+          (add-to-history 'cursory--style-hist (format "%s" preset)))
+        (blink-cursor-mode (plist-get styles :blink-cursor-mode)))
+    (user-error "Cannot determine styles of preset `%s'" preset)))
+
 ;;;###autoload
 (defun cursory-set-preset (style &optional local)
   "Set cursor preset associated with STYLE.
@@ -229,40 +342,14 @@ STYLE is a symbol that represents the car of a list in
 
 With optional LOCAL as a prefix argument, set the
 `cursory-presets' only for the current buffer.  This does not
-cover the function `blink-cursor-mode', which is always global."
+cover the `blink-cursor-mode', which is always global."
   (interactive
    (list
-    (if (= (length cursory-presets) 1)
-        (caar cursory-presets)
-      (cursory--set-cursor-prompt))
+    (cursory--set-cursor-prompt)
     current-prefix-arg))
-  (when-let* ((styles (if (stringp style) (intern style) style))
-              (properties (cursory--preset-values styles))
-              (type (plist-get properties :cursor-type))
-              (type-no-select (plist-get properties 
:cursor-in-non-selected-windows))
-              (blinks (plist-get properties :blink-cursor-blinks))
-              (interval (plist-get properties :blink-cursor-interval))
-              (delay (plist-get properties :blink-cursor-delay)))
-    (if local
-        (setq-local cursor-type type
-                    cursor-in-non-selected-windows type-no-select
-                    blink-cursor-blinks blinks
-                    blink-cursor-interval interval
-                    blink-cursor-delay delay)
-      (dolist (var '( cursor-type cursor-in-non-selected-windows
-                      blink-cursor-blinks blink-cursor-interval
-                      blink-cursor-delay))
-        (kill-local-variable var))
-      (setq-default cursor-type type
-                    cursor-in-non-selected-windows type-no-select
-                    blink-cursor-blinks blinks
-                    blink-cursor-interval interval
-                    blink-cursor-delay delay))
-    (blink-cursor-mode (plist-get properties :blink-cursor-mode))
-    ;; We only want to save global values in
-    ;; `cursory-store-latest-preset'.
-    (unless local
-      (add-to-history 'cursory--style-hist (format "%s" style)))))
+  (if-let ((preset (cursory--get-preset-as-symbol style)))
+      (cursory--set-preset-with-scope preset local)
+    (user-error "Cannot determine preset `%s'" preset)))
 
 ;;;###autoload
 (defun cursory-store-latest-preset ()



reply via email to

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