-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
make modus-themes-list-colors sort by colour name #60
Comments
Hello @bestlem!
Note that several colours from the old version do not exist anymore. I removed all those that were introduced ad-hoc or, generally, were not used considerately.
The palette is organised in subsets. For example,
Those are the basic/common "base" colours. Then we have the common accent colours for regular text:
In the above, you will notice that the grouping is on a per-hue basis. Further down there are background values and purpose-specific groups like:
Sorting by hue will not always yield the desired results. For example, the "added" colours are easier to compare in their context with their "removed" counterparts than with the common green hues. Perhaps it is easier if I help you identify a colour from the old version or, at least, a proxy for it? |
It is not by hue I was after. More alphabetical so for example I can see all magenta-* together. The reason for this is you have changed the background colours in org-blocks soi that I find some text difficult to read due to low contrast and I wanted to see all magenta to choose what it should be. |
This fixes a mistake of mine where I amplified the background colouration of Org blocks. This concerns the case where the user option 'modus-themes-org-blocks' has a 'tinted-background' value. Thanks to Mark Bestley for informing me about this in issue 60 on the GitHub mirror: <#60 (comment)>.
I understand you are using |
Thanks that fixes my immediate issue. However I think that having list-colors be sortable perhaps by clicking on the column headers would be useful |
Yes, this would be useful. I believe we can do it with |
FWIW, I think the ability to sort the list would be nice, but I like the default order for the reason Prot has mentioned. |
@edgar-vincent I will need to experiment with the tabulated list to better understand what our options are. |
I have been experimenting with this. The (defun my-modus-themes--sorted-palette (theme &optional overrides)
(let ((bg (face-background 'default)))
(sort (seq-filter (lambda (entry)
(stringp (cadr entry)))
(append (symbol-value (modus-themes--palette-symbol theme :overrides))
modus-themes-common-palette-overrides
(symbol-value (modus-themes--palette-symbol theme))))
(lambda (x y) ; comment this lambda out and enable the one below
(string-lessp (car x) (car y)))
;; (lambda (x y)
;; (< (modus-themes-contrast bg (cadr x))
;; (modus-themes-contrast bg (cadr y))))
)))
(defun my-modus-themes-list-colors-current-sorted ()
(interactive)
(cl-letf (((symbol-function 'modus-themes--palette-value) #'my-modus-themes--sorted-palette))
(modus-themes-list-colors-current))) Do I think this is not good enough because it places unrelated colours next to each other, such as "border" close to "blue". The method that sorts by contrast is a bit better as it helps put all the backgrounds together, but it still groups them in awkward ways. There probably is a more sophisticated algorithm we can use, though it needs more thought. |
I'm working on a better sorting solution. I hope to be able to finish it today. |
This is my attempt at sorting the colours. I loosely followed the method described there: https://tomekdev.com/posts/sorting-colors-in-js What this does is that it clusters colours together around a series of main colours (red, orange, yellow, etc.), and then each cluster is sorted by luminosity (for colours which are close to black, white and grey) or saturation (all the others). The result is not perfect, but it is an improvement over the previous solutions, and it is reasonably fast, at least on my computer. It is a lot of code for a minor feature, though, so it might need to be simplified. (require 'color)
(defun my-modus-themes--hex-to-rgb (hex-color &optional range)
"Convert HEX-COLOR to a list of the form (RED GREEN BLUE).
HEX-COLOR must be a string of the form '#AABBCC'. Optional parameter RANGE
specifies the maximum value of RED, GREEN and BLUE (by default, 255)."
(let* ((hex (string-to-number (string-remove-prefix "#" hex-color) 16))
(rgb-raw (reverse (mapcar (lambda (d)
(% (/ hex (expt 16 (- d 1))) 16))
(number-sequence 1 6))))
(rgb)
(i 1))
(mapc (lambda (e)
(when (= 1 (% i 2))
(push (+ (* e 16) (nth i rgb-raw)) rgb))
(setq i (1+ i)))
rgb-raw)
(if range
(reverse (mapcar (lambda (d)
(/ (* d range) 255))
rgb))
(reverse rgb))))
(defun my-modus-themes--color-distance (color1 color2)
"Return the distance between COLOR1 and COLOR2.
Both arguments should be expressed in hexadecimal notation"
;; Euclidian distance.
(let ((rgb1 (my-modus-themes--hex-to-rgb color1))
(rgb2 (my-modus-themes--hex-to-rgb color2))
(result 0))
(dotimes (i 3)
(setq result (+ result
(expt (- (nth i rgb1)
(nth i rgb2)) 2))))
(sqrt result)))
;; From core Emacs' color.el. This doesn't give good results so far.
;; (color-distance (my-modus-themes--hex-to-rgb color1 65536) (my-modus-themes--hex-to-rgb color2 65536)))
;; From ct.el
;; (require 'ct)
;; (ct-distance color1 color2))
(defun my-modus-themes--sorted-palette (theme &optional overrides)
(apply #'append ;; Flatten the color list.
(mapcar (lambda (cluster) ;; Sort each cluster.
(let ((cluster-main (car cluster)) ;; We need to know the main color of each cluster
(cluster-stripped (cdr cluster))) ;; because black, white and grey are sorted by lightness
;; while the others are sorted by saturation.
(sort cluster-stripped ;; We want to sort the palette colors only, not the main clusters' color.
(lambda (x y)
(let* ((color1-rgb (my-modus-themes--hex-to-rgb (cadr x) 1.0))
(color2-rgb (my-modus-themes--hex-to-rgb (cadr y) 1.0))
(color1-hsl (apply #'color-rgb-to-hsl color1-rgb))
(color2-hsl (apply #'color-rgb-to-hsl color2-rgb)))
(if (member cluster-main '("black" "grey" "white"))
(< (nth 2 color1-hsl) (nth 2 color2-hsl))
(< (nth 1 color1-hsl) (nth 1 color2-hsl))))))))
;; Put each color of the palette into a cluster.
(let ((colors (seq-filter (lambda (entry) ;; List of Modus palette colors.
(stringp (cadr entry)))
(append (symbol-value (modus-themes--palette-symbol theme :overrides))
modus-themes-common-palette-overrides
(symbol-value (modus-themes--palette-symbol theme)))))
(clusters '(((red "#ff0000"))
((orange "#ff8000"))
((yellow "#ffff00"))
((chartreuse "#80ff00"))
((green "#00ff00"))
((spring-green "#00ff80"))
((cyan "#00ffff"))
((azure "#007fff"))
((blue "#0000ff"))
((violet "#7f00ff"))
((magenta "#ff00ff"))
((rose "#ff0080"))
((black "#000000"))
((grey "#ebebeb"))
((white "#ffffff")))))
(dolist (color colors)
(let* ((cluster-key
(let ((closest-distance)
(closest-cluster))
(dolist (cluster clusters closest-cluster)
(let* ((cur-cluster (car cluster))
(cur-distance (my-modus-themes--color-distance (cadr color) (cadr cur-cluster))))
(when (null closest-distance)
(setq closest-distance cur-distance
closest-cluster cur-cluster))
(when (< cur-distance closest-distance)
(setq closest-distance cur-distance
closest-cluster cur-cluster))))))
(cluster-entry (assoc cluster-key clusters)))
(setf (cdr cluster-entry) (push color (cdr cluster-entry)))))
clusters))))
(defun my-modus-themes-list-colors-current-sorted ()
(interactive)
(cl-letf (((symbol-function 'modus-themes--palette-value) #'my-modus-themes--sorted-palette))
(modus-themes-list-colors-current)))
|
Thank you @edgar-vincent! Sorting those is not easy and we see how the code has to expand considerably. Each method has its advantages, though we ultimately lose the original grouping of the palette. For example, with your approach I get this somewhere in the middle:
These values are close to each other based on the criteria you use, but they are unrelated in terms of how they are applied in the themes. The "added" colours go together with the "removed" and "changed" entries, as they all concern diffs. The Again, this is not to say that your approach is wrong: this is a matter of preference and I still find the default to be the best (or least bad) for the kind of semantics that are involved. |
I agree with you. I think the (default) semantic sorting method is the best. Anyway, my algorithm is there for those who want to use it. |
I know it has been a while, but I just pushed a change to make the preview commands use |
I was just comparing the colours in versions 3 and 4 and I found it difficult to find all shades of say magenta. This is because they are not in a common place in the output.
Could modus-themes-list-colors be sorted by colour name so that for example all magenta shades would be close together,
Is the current order significant in any way?
The text was updated successfully, but these errors were encountered: