diff options
| author | Richard M. Stallman | 2007-10-29 13:54:00 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 2007-10-29 13:54:00 +0000 |
| commit | 26c07a69b954b4616d09b03424a0c3dcb4902c6f (patch) | |
| tree | 34005967f97f995f24e34176af2735a13c4cc929 | |
| parent | f10bbb7315f5203b17e378022ce5edf1e06dd73e (diff) | |
| download | emacs-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.el | 140 |
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. | ||
| 1609 | Completion is available for color names, but not for RGB hex strings. | ||
| 1610 | If the user inputs an RGB hex string, it must have the form | ||
| 1611 | #XXXXXXXXXXXX or XXXXXXXXXXXX, where each X is a hex digit. The | ||
| 1612 | number of Xs must be a multiple of 3, with the same number of Xs for | ||
| 1613 | each of red, green, and blue. The order is red, green, blue. | ||
| 1614 | |||
| 1615 | In addition to standard color names and RGB hex values, the following | ||
| 1616 | are available as color candidates. In each case, the corresponding | ||
| 1617 | color is used. | ||
| 1618 | |||
| 1619 | * `foreground at point' - foreground under the cursor | ||
| 1620 | * `background at point' - background under the cursor | ||
| 1621 | |||
| 1622 | Checks input to be sure it represents a valid color. If not, raises | ||
| 1623 | an error (but see exception for empty input with non-nil | ||
| 1624 | ALLOW-EMPTY-NAME-P). | ||
| 1625 | |||
| 1626 | Optional arg PROMPT is the prompt; if nil, uses a default prompt. | ||
| 1627 | |||
| 1628 | Interactively, or with optional arg CONVERT-TO-RGB-P non-nil, converts | ||
| 1629 | an input color name to an RGB hex string. Returns the RGB hex string. | ||
| 1630 | |||
| 1631 | Optional arg ALLOW-EMPTY-NAME-P controls what happens if the user | ||
| 1632 | enters an empty color name (that is, just hits `RET'). If non-nil, | ||
| 1633 | then returns an empty color name, \"\". If nil, then raises an error. | ||
| 1634 | Programs must test for \"\" if ALLOW-EMPTY-NAME-P is non-nil. They | ||
| 1635 | can then perform an appropriate action in case of empty input. | ||
| 1636 | |||
| 1637 | Interactively, or with optional arg MSG-P non-nil, echoes the color in | ||
| 1638 | a 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. | ||
| 1693 | If it has more than one face, return the first one. | ||
| 1694 | Return 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. |