aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard M. Stallman2007-10-29 13:54:00 +0000
committerRichard M. Stallman2007-10-29 13:54:00 +0000
commit26c07a69b954b4616d09b03424a0c3dcb4902c6f (patch)
tree34005967f97f995f24e34176af2735a13c4cc929
parentf10bbb7315f5203b17e378022ce5edf1e06dd73e (diff)
downloademacs-26c07a69b954b4616d09b03424a0c3dcb4902c6f.tar.gz
emacs-26c07a69b954b4616d09b03424a0c3dcb4902c6f.zip
(read-color): New function.
(face-at-point, foreground-color-at-point) (background-color-at-point): New functions.
-rw-r--r--lisp/faces.el140
1 files changed, 140 insertions, 0 deletions
diff --git a/lisp/faces.el b/lisp/faces.el
index ab299160b6d..83b69ca630f 100644
--- a/lisp/faces.el
+++ b/lisp/faces.el
@@ -1472,6 +1472,12 @@ See `defface' for information about SPEC. If SPEC is nil, do nothing."
1472 ;; When we reset the face based on its spec, then it is unmodified 1472 ;; When we reset the face based on its spec, then it is unmodified
1473 ;; as far as Custom is concerned. 1473 ;; as far as Custom is concerned.
1474 (put (or (get face 'face-alias) face) 'face-modified nil) 1474 (put (or (get face 'face-alias) face) 'face-modified nil)
1475;;; ;; Clear all the new-frame defaults for this face.
1476;;; ;; face-spec-reset-face won't do it right.
1477;;; (let ((facevec (cdr (assq face face-new-frame-defaults))))
1478;;; (dotimes (i (length facevec))
1479;;; (unless (= i 0)
1480;;; (aset facevec i 'unspecified))))
1475 ;; Set each frame according to the rules implied by SPEC. 1481 ;; Set each frame according to the rules implied by SPEC.
1476 (dolist (frame (frame-list)) 1482 (dolist (frame (frame-list))
1477 (face-spec-set face spec frame)))) 1483 (face-spec-set face spec frame))))
@@ -1598,6 +1604,140 @@ If omitted or nil, that stands for the selected frame's display."
1598 (t 1604 (t
1599 (> (tty-color-gray-shades display) 2))))) 1605 (> (tty-color-gray-shades display) 2)))))
1600 1606
1607(defun read-color (&optional prompt convert-to-RGB-p allow-empty-name-p msg-p)
1608 "Read a color name or RGB hex value: #RRRRGGGGBBBB.
1609Completion is available for color names, but not for RGB hex strings.
1610If the user inputs an RGB hex string, it must have the form
1611#XXXXXXXXXXXX or XXXXXXXXXXXX, where each X is a hex digit. The
1612number of Xs must be a multiple of 3, with the same number of Xs for
1613each of red, green, and blue. The order is red, green, blue.
1614
1615In addition to standard color names and RGB hex values, the following
1616are available as color candidates. In each case, the corresponding
1617color is used.
1618
1619 * `foreground at point' - foreground under the cursor
1620 * `background at point' - background under the cursor
1621
1622Checks input to be sure it represents a valid color. If not, raises
1623an error (but see exception for empty input with non-nil
1624ALLOW-EMPTY-NAME-P).
1625
1626Optional arg PROMPT is the prompt; if nil, uses a default prompt.
1627
1628Interactively, or with optional arg CONVERT-TO-RGB-P non-nil, converts
1629an input color name to an RGB hex string. Returns the RGB hex string.
1630
1631Optional arg ALLOW-EMPTY-NAME-P controls what happens if the user
1632enters an empty color name (that is, just hits `RET'). If non-nil,
1633then returns an empty color name, \"\". If nil, then raises an error.
1634Programs must test for \"\" if ALLOW-EMPTY-NAME-P is non-nil. They
1635can then perform an appropriate action in case of empty input.
1636
1637Interactively, or with optional arg MSG-P non-nil, echoes the color in
1638a message."
1639 (interactive "i\np\ni\np") ; Always convert to RGB interactively.
1640 (let* ((completion-ignore-case t)
1641 (colors (append '("foreground at point" "background at point")
1642 (defined-colors)))
1643 (color (completing-read (or prompt "Color (name or #R+G+B+): ")
1644 colors))
1645 hex-string)
1646 (cond ((string= "foreground at point" color)
1647 (setq color (foreground-color-at-point)))
1648 ((string= "background at point" color)
1649 (setq color (background-color-at-point))))
1650 (unless color
1651 (setq color ""))
1652 (setq hex-string
1653 (string-match "^#?\\([a-fA-F0-9][a-fA-F0-9][a-fA-F0-9]\\)+$" color))
1654 (if (and allow-empty-name-p (string= "" color))
1655 ""
1656 (when (and hex-string (not (eq (aref color 0) ?#)))
1657 (setq color (concat "#" color))) ; No #; add it.
1658 (unless hex-string
1659 (when (or (string= "" color) (not (test-completion color colors)))
1660 (error "No such color: %S" color))
1661 (when convert-to-RGB-p
1662 (let ((components (x-color-values color)))
1663 (unless components (error "No such color: %S" color))
1664 (unless (string-match "^#\\([a-fA-F0-9][a-fA-F0-9][a-fA-F0-9]\\)+$" color)
1665 (setq color (format "#%04X%04X%04X"
1666 (logand 65535 (nth 0 components))
1667 (logand 65535 (nth 1 components))
1668 (logand 65535 (nth 2 components))))))))
1669 (when msg-p (message "Color: `%s'" color))
1670 color)))
1671
1672;; Commented out because I decided it is better to include the
1673;; duplicates in read-color's completion list.
1674
1675;; (defun defined-colors-without-duplicates ()
1676;; "Return the list of defined colors, without the no-space versions.
1677;; For each color name, we keep the variant that DOES have spaces."
1678;; (let ((result (copy-sequence (defined-colors)))
1679;; to-be-rejected)
1680;; (save-match-data
1681;; (dolist (this result)
1682;; (if (string-match " " this)
1683;; (push (replace-regexp-in-string " " ""
1684;; this)
1685;; to-be-rejected)))
1686;; (dolist (elt to-be-rejected)
1687;; (let ((as-found (car (member-ignore-case elt result))))
1688;; (setq result (delete as-found result)))))
1689;; result))
1690
1691(defun face-at-point ()
1692 "Return the face of the character after point.
1693If it has more than one face, return the first one.
1694Return nil if it has no specified face."
1695 (let* ((faceprop (or (get-char-property (point) 'read-face-name)
1696 (get-char-property (point) 'face)
1697 'default))
1698 (face (cond ((symbolp faceprop) faceprop)
1699 ;; List of faces (don't treat an attribute spec).
1700 ;; Just use the first face.
1701 ((and (consp faceprop) (not (keywordp (car faceprop)))
1702 (not (memq (car faceprop)
1703 '(foreground-color background-color))))
1704 (car faceprop))
1705 (t nil)))) ; Invalid face value.
1706 (if (facep face) face nil)))
1707
1708(defun foreground-color-at-point ()
1709 "Return the foreground color of the character after point."
1710 ;; `face-at-point' alone is not sufficient. It only gets named faces.
1711 ;; Need also pick up any face properties that are not associated with named faces.
1712 (let ((face (or (face-at-point)
1713 (get-char-property (point) 'read-face-name)
1714 (get-char-property (point) 'face))))
1715 (cond ((and face (symbolp face))
1716 (let ((value (face-foreground face nil 'default)))
1717 (if (member value '("unspecified-fg" "unspecified-bg"))
1718 nil
1719 value)))
1720 ((consp face)
1721 (cond ((memq 'foreground-color face) (cdr (memq 'foreground-color face)))
1722 ((memq ':foreground face) (cadr (memq ':foreground face)))))
1723 (t nil)))) ; Invalid face value.
1724
1725(defun background-color-at-point ()
1726 "Return the background color of the character after point."
1727 ;; `face-at-point' alone is not sufficient. It only gets named faces.
1728 ;; Need also pick up any face properties that are not associated with named faces.
1729 (let ((face (or (face-at-point)
1730 (get-char-property (point) 'read-face-name)
1731 (get-char-property (point) 'face))))
1732 (cond ((and face (symbolp face))
1733 (let ((value (face-background face nil 'default)))
1734 (if (member value '("unspecified-fg" "unspecified-bg"))
1735 nil
1736 value)))
1737 ((consp face)
1738 (cond ((memq 'background-color face) (cdr (memq 'background-color face)))
1739 ((memq ':background face) (cadr (memq ':background face)))))
1740 (t nil)))) ; Invalid face value.
1601 1741
1602;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1742;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1603;;; Background mode. 1743;;; Background mode.