branch: externals/face-shift
commit 0a420101316136e1ab71edfccec32d65250b832c
Author: Philip K <[email protected]>
Commit: Philip K <[email protected]>

    initial export
---
 face-shift.el | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 106 insertions(+)

diff --git a/face-shift.el b/face-shift.el
new file mode 100644
index 0000000000..816eb466ec
--- /dev/null
+++ b/face-shift.el
@@ -0,0 +1,106 @@
+;;; -*- lexical-binding: t -*-
+;;; published under CC0 into the public domain
+;;; author: philip k. [https://zge.us.to], 2019
+
+(require 'color)
+(eval-when-compile (require 'cl-lib))
+
+(defgroup face-shift nil
+  "Distort colours of certain faces"
+  :group 'faces
+  :prefix "face-shift-")
+
+(defcustom face-shift-force-fit nil
+  "Make sure that all transformations stay in the RGB-unit-space,
+by wrapping values over 1 to 1."
+  :type 'boolean
+  :group 'face-shift)
+
+(defcustom face-shift-intensity 0.9
+  "Value to replace a `int' symbol with in `face-shift-colors'."
+  :type 'float
+  :group 'face-shift)
+
+(defcustom face-shift-minimum 0.0
+  "Value to replace a `min' symbol with in `face-shift-colors'."
+  :type 'float
+  :group 'face-shift)
+
+(defcustom face-shift-maximum 1.0
+  "Value to replace a `max' symbol with in `face-shift-colors'."
+  :type 'float
+  :group 'face-shift)
+
+(defcustom face-shift-colors
+  '((blue .   ((int min min) (min max min) (min min max)))
+       (pink .   ((max min min) (min int min) (min min max)))
+       (yellow . ((max min min) (min max min) (min min int)))
+       (peach .  ((max min min) (min int min) (min min int)))
+       (green .  ((int min min) (min max min) (min min int)))
+       (purple . ((int min min) (min int min) (min min max))))
+  "Alist of matrices representing RGB transformations towards a
+  certain hue. Symbols `int', `max' and `min' are substituted
+  with `face-shift-intensity', `face-shift-maximum' and
+  `face-shift-minimum' respectively."
+  :type '(list (list symbol))
+  :group 'face-shift)
+
+(defcustom face-shift-faces
+  (append '(default cursor region isearch)
+                 (cl-remove-if-not
+                  (lambda (sym)
+                        (string-match-p (rx bos "font-lock-")
+                                                        (symbol-name sym)))
+                  (face-list)))
+  "Faces that `face-shift' should distort."
+  :type '(list face)
+  :group 'face-shift)
+
+(defun face-shift-by (face prop mat)
+  "Call `face-remap-add-relative' on FACE by distorting the
+colour behind PROP by MAT in an RGB colour space."
+  (let* ((mvp (lambda (vec)
+                               (mapcar (lambda (row)
+                                                 (apply #'+ (cl-mapcar #'* row 
vec)))
+                                               mat)))
+                (bg (face-attribute face prop))
+                (colors (color-name-to-rgb bg))
+                (trans (funcall mvp colors))
+                (ncolor
+                 (apply
+                  #'color-rgb-to-hex
+                  (append
+                       (if face-shift-force-fit
+                               (mapcar (lambda (x) (if (< x 1) 1 x))
+                                               trans)
+                         trans)
+                       '(2)))))
+       (unless (eq bg 'unspecified)
+         (face-remap-add-relative face `(,prop ,ncolor)))
+       ncolor))
+
+(defun face-shift (color &optional ignore)
+  "Produce a function that will shift all background and
+foreground colours behind the faces listed in `face-shift-faces',
+that can then be added to a hook. COLOR should index a
+transformation from the `face-shift-colors' alist.
+
+If IGNORE is non-nil, it has to be a list of modes that should be
+ignored by this hook. For example
+
+   (face-shift 'green '(mail-mode))
+
+will apply the green shift, unless the mode of the hook it was
+added to is mail-mode or a derivative."
+  (let ((mat (cl-sublis
+                         `((int . ,face-shift-intensity)
+                               (max . ,face-shift-maximum)
+                               (min . ,face-shift-minimum))
+                         (cdr (assq color face-shift-colors)))))
+       (lambda ()
+         (unless (cl-some #'derived-mode-p ignore)
+               (dolist (face face-shift-faces)
+                 (face-shift-by face :foreground mat)
+                 (face-shift-by face :background mat))))))
+
+(provide 'face-shift)

Reply via email to