branch: externals/cursory commit 7322b3b1e4477fc1dbfa5b5351c49457c4bd6d09 Author: Protesilaos Stavrou <i...@protesilaos.com> Commit: Protesilaos Stavrou <i...@protesilaos.com>
Make it possible to define a :cursor-color to modify the cursor face --- README.org | 10 +++++++ cursory.el | 90 ++++++++++++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 80 insertions(+), 20 deletions(-) diff --git a/README.org b/README.org index 3b00db3ecc..b2991c8e52 100644 --- a/README.org +++ b/README.org @@ -97,6 +97,7 @@ They look like this: #+begin_src emacs-lisp (bar + :cursor-color unspecified :cursor-type (bar . 2) :cursor-in-non-selected-windows hollow :blink-cursor-mode 1 @@ -112,6 +113,15 @@ built-in variables: ~cursor-type~, ~cursor-in-non-selected-windows~, The value each property accepts is the same as the variable it references. +The ~:cursor-color~ specifies the color value applied to the ~cursor~ +face. When the value is nil or ~unspecified~, no changes to the +~cursor~ face are made. When the value is a hexadecimal RGB color +value, like =#123456= it is used as-is. Same if it is a named color +among those produced by the command ~list-colors-display~. When the +value is the symbol of a face (unquoted), then the foreground of that +face is used for the ~cursor~ face, falling back to ~default~. [ The +=:cursor-color= is part of {{{development-version}}}. ] + 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. diff --git a/cursory.el b/cursory.el index 2ba0263e7c..98f5b82821 100644 --- a/cursory.el +++ b/cursory.el @@ -148,6 +148,18 @@ :group 'cursor :link '(info-link "(cursory) Top")) +;; NOTE 2025-07-20: This is what `use-package' does with its own +;; theme, so it is probably the right approach for us too. +(eval-and-compile + ;; Declare a synthetic theme for :custom variables. + ;; Necessary in order to avoid having those variables saved by custom.el. + (deftheme cursory "Special theme for Cursory modifications.")) + +(enable-theme 'cursory) +;; Remove the synthetic cursory theme from the enabled themes, so +;; iterating over them to "disable all themes" won't disable it. +(setq custom-enabled-themes (remq 'cursory custom-enabled-themes)) + (defcustom cursory-presets '((box :blink-cursor-interval 0.8) @@ -166,6 +178,7 @@ :inherit underscore :cursor-in-non-selected-windows (hbar . 1)) (t ; the default values + :cursor-color unspecified :cursor-type box :cursor-in-non-selected-windows hollow :blink-cursor-mode 1 @@ -188,6 +201,7 @@ variable for how that is done. The `cdr' is a plist which specifies the cursor type and blink properties. In particular, it accepts the following properties: + :cursor-color :cursor-type :cursor-in-non-selected-windows :blink-cursor-blinks @@ -196,32 +210,43 @@ properties. In particular, it accepts the following properties: They correspond to built-in variables: `cursor-type', `cursor-in-non-selected-windows', `blink-cursor-blinks', -`blink-cursor-interval', `blink-cursor-delay'. The value each of -them accepts is the same as the variable it references. +`blink-cursor-interval', `blink-cursor-delay'. The value each of 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 +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). -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." +The `:cursor-color' specifies the color value applied to the `cursor' +face. When the value is nil or `unspecified', no changes to the +`cursor' face are made. When the value is a hexadecimal RGB color +value, like #123456 it is used as-is. Same if it is a named color among +those produced by the command `list-colors-display'. When the value is +the symbol of a face (unquoted), then the foreground of that face is +used for the `cursor' face, falling back to `default'. + +The plist optionally takes the special `:inherit' property. Its value +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 . "1.0.0") + :package-version '(cursory . "1.2.0") :type `(alist :value-type (plist :options - (((const :tag "Cursor type" + (((const :tag "Cursor color" :cursor-color) + (choice (const :tag "Do not modify the `cursor' face" unspecified) + (string :tag "Hexademical RGB color value (e.g. #123456) or named color (e.g. red)") + (face :tag "A face whose foreground is used (falling back to `default'"))) + ((const :tag "Cursor type" :cursor-type) ,(get 'cursor-type 'custom-type)) ((const :tag "Cursor in non-selected windows" @@ -319,6 +344,29 @@ Saving is done by the `cursory-store-latest-preset' function." (defvar cursory-last-selected-preset nil "The last value of `cursory-set-preset'.") +(defun cursory--get-cursor-color (color-value) + "Return the color of the `cursor' face based on VALUE. +COLOR-VALUE can be a string, representing a color by name or hexadecimal +RGB, a symbol of a face, the symbol `unspecified' or nil." + (cond + ((stringp color-value) color-value) + ((facep color-value) (face-foreground color-value nil 'default)) + (t nil))) + +(defun cursory--set-cursor (color-value frame) + "Set the cursor style given COLOR-VALUE. +When FRAME is a frame object, only do it for it. Otherwise, apply the +effect to all frames." + (let ((color (cursory--get-cursor-color color-value))) + (if frame + (if color + (set-face-attribute 'cursor frame :background color) + (set-face-attribute 'cursor frame :background 'unspecified)) + (let ((custom--inhibit-theme-enable nil)) + (if color + (custom-theme-set-faces 'cursory `(cursor ((t :background ,color)))) + (custom-theme-set-faces 'cursory '(cursor (( ))))))))) + (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 @@ -326,12 +374,14 @@ 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)) + (let ((color-value (plist-get styles :cursor-color)) + (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))) (setq cursory-last-selected-preset preset) + (cursory--set-cursor color-value (when local (selected-frame))) (if local (setq-local cursor-type type cursor-in-non-selected-windows type-no-select