aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJuri Linkov2010-06-14 19:03:04 +0300
committerJuri Linkov2010-06-14 19:03:04 +0300
commitf0bf7c8e5525fb4f964530c17399c3c987a79927 (patch)
tree2f55e221c7ddd0268d6541b5b4ee318c8a372b51
parentc42fe9a55d2356f509ea38e6de6fcec95fd6ac63 (diff)
downloademacs-f0bf7c8e5525fb4f964530c17399c3c987a79927.tar.gz
emacs-f0bf7c8e5525fb4f964530c17399c3c987a79927.zip
Add sort option `list-colors-sort'. (Bug#6332)
* lisp/facemenu.el (color-rgb-to-hsv): New function. (list-colors-sort): New defcustom. (list-colors-sort-key): New function. (list-colors-display): Doc fix. Sort list according to the option `list-colors-sort'. (list-colors-print): Add HSV values to `help-echo' property of RGB strings.
-rw-r--r--etc/NEWS3
-rw-r--r--lisp/ChangeLog11
-rw-r--r--lisp/facemenu.el110
3 files changed, 120 insertions, 4 deletions
diff --git a/etc/NEWS b/etc/NEWS
index e9d29c9ea87..60de0a286f3 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -125,6 +125,9 @@ trashing. This avoids inadvertently trashing temporary files.
125*** Calling `delete-file' or `delete-directory' with a prefix argument 125*** Calling `delete-file' or `delete-directory' with a prefix argument
126now forces true deletion, regardless of `delete-by-moving-to-trash'. 126now forces true deletion, regardless of `delete-by-moving-to-trash'.
127 127
128** New option `list-colors-sort' defines the color sort order
129for `list-colors-display'.
130
128 131
129* Editing Changes in Emacs 24.1 132* Editing Changes in Emacs 24.1
130 133
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 1afc00e9214..e7303f63f00 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,5 +1,16 @@
12010-06-14 Juri Linkov <juri@jurta.org> 12010-06-14 Juri Linkov <juri@jurta.org>
2 2
3 Add sort option `list-colors-sort'. (Bug#6332)
4 * facemenu.el (color-rgb-to-hsv): New function.
5 (list-colors-sort): New defcustom.
6 (list-colors-sort-key): New function.
7 (list-colors-display): Doc fix. Sort list according to the option
8 `list-colors-sort'.
9 (list-colors-print): Add HSV values to `help-echo' property of
10 RGB strings.
11
122010-06-14 Juri Linkov <juri@jurta.org>
13
3 * compare-w.el: Move to the "vc" subdirectory. 14 * compare-w.el: Move to the "vc" subdirectory.
4 15
52010-06-14 Stefan Monnier <monnier@iro.umontreal.ca> 162010-06-14 Stefan Monnier <monnier@iro.umontreal.ca>
diff --git a/lisp/facemenu.el b/lisp/facemenu.el
index 187383d44e2..9e8299720a6 100644
--- a/lisp/facemenu.el
+++ b/lisp/facemenu.el
@@ -479,6 +479,73 @@ These special properties include `invisible', `intangible' and `read-only'."
479 nil 479 nil
480 col))) 480 col)))
481 481
482(defun color-rgb-to-hsv (r g b)
483 "For R, G, B color components return a list of hue, saturation, value.
484R, G, B input values should be in [0..65535] range.
485Output values for hue are integers in [0..360] range.
486Output values for saturation and value are integers in [0..100] range."
487 (let* ((r (/ r 65535.0))
488 (g (/ g 65535.0))
489 (b (/ b 65535.0))
490 (max (max r g b))
491 (min (min r g b))
492 (h (cond ((= max min) 0)
493 ((= max r) (mod (+ (* 60 (/ (- g b) (- max min))) 360) 360))
494 ((= max g) (+ (* 60 (/ (- b r) (- max min))) 120))
495 ((= max b) (+ (* 60 (/ (- r g) (- max min))) 240))))
496 (s (cond ((= max 0) 0)
497 (t (- 1 (/ min max)))))
498 (v max))
499 (list (round h) (round s 0.01) (round v 0.01))))
500
501(defcustom list-colors-sort nil
502 "Color sort order for `list-colors-display'.
503`nil' means default implementation-dependent order (defined in `x-colors').
504`name' sorts by color name.
505`rgb' sorts by red, green, blue components.
506`rgb-dist' sorts by the RGB distance to the specified color.
507`hsv' sorts by hue, saturation, value.
508`hsv-dist' sorts by the HVS distance to the specified color
509and excludes grayscale colors."
510 :type '(choice (const :tag "Unsorted" nil)
511 (const :tag "Color Name" name)
512 (const :tag "Red-Green-Blue" rgb)
513 (cons :tag "Distance on RGB cube"
514 (const :tag "Distance from Color" rgb-dist)
515 (color :tag "Source Color Name"))
516 (const :tag "Hue-Saturation-Value" hsv)
517 (cons :tag "Distance on HSV cylinder"
518 (const :tag "Distance from Color" hsv-dist)
519 (color :tag "Source Color Name")))
520 :group 'facemenu
521 :version "24.1")
522
523(defun list-colors-sort-key (color)
524 "Return a list of keys for sorting colors depending on `list-colors-sort'.
525COLOR is the name of the color. When return value is nil,
526filter out the color from the output."
527 (cond
528 ((null list-colors-sort) color)
529 ((eq list-colors-sort 'name)
530 (downcase color))
531 ((eq list-colors-sort 'rgb)
532 (color-values color))
533 ((eq (car-safe list-colors-sort) 'rgb-dist)
534 (color-distance color (cdr list-colors-sort)))
535 ((eq list-colors-sort 'hsv)
536 (apply 'color-rgb-to-hsv (color-values color)))
537 ((eq (car-safe list-colors-sort) 'hsv-dist)
538 (let* ((c-rgb (color-values color))
539 (c-hsv (apply 'color-rgb-to-hsv c-rgb))
540 (o-hsv (apply 'color-rgb-to-hsv
541 (color-values (cdr list-colors-sort)))))
542 (unless (and (eq (nth 0 c-rgb) (nth 1 c-rgb)) ; exclude grayscale
543 (eq (nth 1 c-rgb) (nth 2 c-rgb)))
544 ;; 3D Euclidean distance (sqrt is not needed for sorting)
545 (+ (expt (- 180 (abs (- 180 (abs (- (nth 0 c-hsv) ; wrap hue
546 (nth 0 o-hsv)))))) 2)
547 (expt (- (nth 1 c-hsv) (nth 1 o-hsv)) 2)
548 (expt (- (nth 2 c-hsv) (nth 2 o-hsv)) 2)))))))
482 549
483(defun list-colors-display (&optional list buffer-name callback) 550(defun list-colors-display (&optional list buffer-name callback)
484 "Display names of defined colors, and show what they look like. 551 "Display names of defined colors, and show what they look like.
@@ -492,10 +559,38 @@ If the optional argument BUFFER-NAME is nil, it defaults to
492If the optional argument CALLBACK is non-nil, it should be a 559If the optional argument CALLBACK is non-nil, it should be a
493function to call each time the user types RET or clicks on a 560function to call each time the user types RET or clicks on a
494color. The function should accept a single argument, the color 561color. The function should accept a single argument, the color
495name." 562name.
563
564You can change the color sort order by customizing `list-colors-sort'."
496 (interactive) 565 (interactive)
497 (when (and (null list) (> (display-color-cells) 0)) 566 (when (and (null list) (> (display-color-cells) 0))
498 (setq list (list-colors-duplicates (defined-colors))) 567 (setq list (list-colors-duplicates (defined-colors)))
568 (when list-colors-sort
569 ;; Schwartzian transform with `(color key1 key2 key3 ...)'.
570 (setq list (mapcar
571 'car
572 (sort (delq nil (mapcar
573 (lambda (c)
574 (let ((key (list-colors-sort-key
575 (car c))))
576 (when key
577 (cons c (if (consp key) key
578 (list key))))))
579 list))
580 (lambda (a b)
581 (let* ((a-keys (cdr a))
582 (b-keys (cdr b))
583 (a-key (car a-keys))
584 (b-key (car b-keys)))
585 ;; Skip common keys at the beginning of key lists.
586 (while (and a-key b-key (equal a-key b-key))
587 (setq a-keys (cdr a-keys) a-key (car a-keys)
588 b-keys (cdr b-keys) b-key (car b-keys)))
589 (cond
590 ((and (numberp a-key) (numberp b-key))
591 (< a-key b-key))
592 ((and (stringp a-key) (stringp b-key))
593 (string< a-key b-key)))))))))
499 (when (memq (display-visual-class) '(gray-scale pseudo-color direct-color)) 594 (when (memq (display-visual-class) '(gray-scale pseudo-color direct-color))
500 ;; Don't show more than what the display can handle. 595 ;; Don't show more than what the display can handle.
501 (let ((lc (nthcdr (1- (display-color-cells)) list))) 596 (let ((lc (nthcdr (1- (display-color-cells)) list)))
@@ -550,9 +645,16 @@ name."
550 (point) 645 (point)
551 'face (list :foreground (car color))) 646 'face (list :foreground (car color)))
552 (indent-to (max (- (window-width) 8) 44)) 647 (indent-to (max (- (window-width) 8) 44))
553 (insert (apply 'format "#%02x%02x%02x" 648 (insert (propertize
554 (mapcar (lambda (c) (lsh c -8)) 649 (apply 'format "#%02x%02x%02x"
555 color-values))) 650 (mapcar (lambda (c) (lsh c -8))
651 color-values))
652 'mouse-face 'highlight
653 'help-echo
654 (let ((hsv (apply 'color-rgb-to-hsv
655 (color-values (car color)))))
656 (format "H:%d S:%d V:%d"
657 (nth 0 hsv) (nth 1 hsv) (nth 2 hsv)))))
556 (when callback 658 (when callback
557 (make-text-button 659 (make-text-button
558 opoint (point) 660 opoint (point)