2008-06-03 11:05:52 +00:00
|
|
|
|
;;; face-remap.el --- Functions for managing `face-remapping-alist'
|
|
|
|
|
;;
|
|
|
|
|
;; Copyright (C) 2008 Free Software Foundation, Inc.
|
|
|
|
|
;;
|
|
|
|
|
;; Author: Miles Bader <miles@gnu.org>
|
|
|
|
|
;; Keywords: faces face display user commands
|
|
|
|
|
;;
|
|
|
|
|
;; This file is part of GNU Emacs.
|
|
|
|
|
;;
|
|
|
|
|
;; GNU Emacs is free software: you can redistribute it and/or modify
|
|
|
|
|
;; it under the terms of the GNU General Public License as published by
|
|
|
|
|
;; the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
;; (at your option) any later version.
|
|
|
|
|
;;
|
|
|
|
|
;; GNU Emacs is distributed in the hope that it will be useful,
|
|
|
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
;; GNU General Public License for more details.
|
|
|
|
|
;;
|
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
|
|
|
|
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
;;
|
|
|
|
|
|
|
|
|
|
;;; Commentary:
|
|
|
|
|
|
|
|
|
|
;;
|
|
|
|
|
;; This file defines some simple operations that can be used for
|
|
|
|
|
;; maintaining the `face-remapping-alist' in a cooperative way. This is
|
|
|
|
|
;; especially important for the `default' face.
|
|
|
|
|
;;
|
|
|
|
|
;; Each face-remapping definition in `face-remapping-alist' added by
|
|
|
|
|
;; this code uses the form:
|
|
|
|
|
;;
|
|
|
|
|
;; (face RELATIVE_SPECS_1 RELATIVE_SPECS_2 ... BASE_SPECS)
|
|
|
|
|
;;
|
|
|
|
|
;; The "specs" values are a lists of face names or face attribute-value
|
|
|
|
|
;; pairs, and are merged together, with earlier values taking precedence.
|
|
|
|
|
;;
|
2008-06-05 02:42:55 +00:00
|
|
|
|
;; The RELATIVE_SPECS_* values are added by `face-remap-add-relative'
|
|
|
|
|
;; (and removed by `face-remap-remove-relative', and are intended for
|
2008-06-03 11:05:52 +00:00
|
|
|
|
;; face "modifications" (such as increasing the size). Typical users of
|
|
|
|
|
;; relative specs would be minor modes.
|
|
|
|
|
;;
|
|
|
|
|
;; BASE_SPECS is the lowest-priority value, and by default is just the
|
|
|
|
|
;; face name, which causes the global definition of that face to be used.
|
|
|
|
|
;;
|
|
|
|
|
;; A non-default value of BASE_SPECS may also be set using
|
2008-06-05 02:42:55 +00:00
|
|
|
|
;; `face-remap-set-base'. Because this _overwrites_ the default
|
2008-06-03 11:05:52 +00:00
|
|
|
|
;; value inheriting from the global face definition, it is up to the
|
2008-06-05 02:42:55 +00:00
|
|
|
|
;; caller of face-remap-set-base to add such inheritance if it is
|
|
|
|
|
;; desired. A typical use of face-remap-set-base would be a major
|
2008-06-03 11:05:52 +00:00
|
|
|
|
;; mode setting face remappings, e.g., of the default face.
|
|
|
|
|
;;
|
|
|
|
|
;; All modifications cause face-remapping-alist to be made buffer-local.
|
|
|
|
|
;;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;; Code:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;; ----------------------------------------------------------------
|
|
|
|
|
;; Utility functions
|
|
|
|
|
|
2008-06-17 11:27:36 +00:00
|
|
|
|
;; Names of face attributes corresponding to lisp face-vector positions.
|
|
|
|
|
;; This variable should probably be defined in C code where the actual
|
|
|
|
|
;; definitions are available.
|
|
|
|
|
;;
|
|
|
|
|
(defvar internal-lisp-face-attributes
|
|
|
|
|
[nil
|
|
|
|
|
:family :foundry :swidth :height :weight :slant :underline :inverse
|
|
|
|
|
:foreground :background :stipple :overline :strike :box
|
|
|
|
|
:font :inherit :fontset :vector])
|
|
|
|
|
|
|
|
|
|
(defun face-attrs-more-relative-p (attrs1 attrs2)
|
|
|
|
|
"Return true if ATTRS1 contains a greater number of relative
|
|
|
|
|
face-attributes than ATTRS2. A face attribute is considered
|
|
|
|
|
relative if `face-attribute-relative-p' returns non-nil.
|
|
|
|
|
|
|
|
|
|
ATTRS1 and ATTRS2 may be any value suitable for a `face' text
|
|
|
|
|
property, including face names, lists of face names,
|
|
|
|
|
face-attribute plists, etc.
|
|
|
|
|
|
|
|
|
|
This function can be used as a predicate with `sort', to sort
|
|
|
|
|
face lists so that more specific faces are located near the end."
|
|
|
|
|
(unless (vectorp attrs1)
|
|
|
|
|
(setq attrs1 (face-attributes-as-vector attrs1)))
|
|
|
|
|
(unless (vectorp attrs2)
|
|
|
|
|
(setq attrs2 (face-attributes-as-vector attrs2)))
|
|
|
|
|
(let ((rel1-count 0) (rel2-count 0))
|
|
|
|
|
(dotimes (i (length attrs1))
|
|
|
|
|
(let ((attr (aref internal-lisp-face-attributes i)))
|
|
|
|
|
(when attr
|
|
|
|
|
(when (face-attribute-relative-p attr (aref attrs1 i))
|
|
|
|
|
(setq rel1-count (+ rel1-count 1)))
|
|
|
|
|
(when (face-attribute-relative-p attr (aref attrs2 i))
|
|
|
|
|
(setq rel2-count (+ rel2-count 1))))))
|
|
|
|
|
(< rel1-count rel2-count)))
|
|
|
|
|
|
|
|
|
|
(defun face-remap-order (entry)
|
|
|
|
|
"Order ENTRY so that more relative face specs are near the beginning.
|
|
|
|
|
The list structure of ENTRY may be destructively modified."
|
|
|
|
|
(setq entry (nreverse entry))
|
|
|
|
|
(setcdr entry (sort (cdr entry) 'face-attrs-more-relative-p))
|
|
|
|
|
(nreverse entry))
|
|
|
|
|
|
2008-06-03 11:05:52 +00:00
|
|
|
|
;;;### autoload
|
2008-06-05 02:42:55 +00:00
|
|
|
|
(defun face-remap-add-relative (face &rest specs)
|
2008-06-03 11:05:52 +00:00
|
|
|
|
"Add a face remapping entry of FACE to SPECS in the current buffer.
|
|
|
|
|
|
|
|
|
|
Return a cookie which can be used to delete the remapping with
|
2008-06-05 02:42:55 +00:00
|
|
|
|
`face-remap-remove-relative'.
|
2008-06-03 11:05:52 +00:00
|
|
|
|
|
|
|
|
|
SPECS can be any value suitable for the `face' text property,
|
|
|
|
|
including a face name, a list of face names, or a face-attribute
|
|
|
|
|
property list. The attributes given by SPECS will be merged with
|
|
|
|
|
any other currently active face remappings of FACE, and with the
|
2008-06-17 11:27:36 +00:00
|
|
|
|
global definition of FACE. An attempt is made to sort multiple
|
|
|
|
|
entries so that entries with relative face-attributes are applied
|
|
|
|
|
after entries with absolute face-attributes.
|
2008-06-03 11:05:52 +00:00
|
|
|
|
|
|
|
|
|
The base (lowest priority) remapping may be set to a specific
|
|
|
|
|
value, instead of the default of the global face definition,
|
2008-06-05 02:42:55 +00:00
|
|
|
|
using `face-remap-set-base'."
|
2008-06-03 11:05:52 +00:00
|
|
|
|
(make-local-variable 'face-remapping-alist)
|
|
|
|
|
(let ((entry (assq face face-remapping-alist)))
|
|
|
|
|
(when (null entry)
|
|
|
|
|
(setq entry (list face face)) ; explicitly merge with global def
|
|
|
|
|
(push entry face-remapping-alist))
|
2008-06-17 11:27:36 +00:00
|
|
|
|
(setcdr entry (face-remap-order (cons specs (cdr entry))))
|
2008-06-03 11:05:52 +00:00
|
|
|
|
(cons face specs)))
|
|
|
|
|
|
2008-06-05 02:42:55 +00:00
|
|
|
|
(defun face-remap-remove-relative (cookie)
|
|
|
|
|
"Remove a face remapping previously added by `face-remap-add-relative'.
|
2008-06-03 11:05:52 +00:00
|
|
|
|
COOKIE should be the return value from that function."
|
|
|
|
|
(let ((remapping (assq (car cookie) face-remapping-alist)))
|
|
|
|
|
(when remapping
|
|
|
|
|
(let ((updated-entries (remq (cdr cookie) (cdr remapping))))
|
|
|
|
|
(unless (eq updated-entries (cdr remapping))
|
|
|
|
|
(setcdr remapping updated-entries)
|
|
|
|
|
(when (or (null updated-entries)
|
|
|
|
|
(and (eq (car-safe updated-entries) (car cookie))
|
|
|
|
|
(null (cdr updated-entries))))
|
|
|
|
|
(setq face-remapping-alist
|
|
|
|
|
(remq remapping face-remapping-alist)))
|
|
|
|
|
(cdr cookie))))))
|
|
|
|
|
|
|
|
|
|
;;;### autoload
|
2008-06-05 02:42:55 +00:00
|
|
|
|
(defun face-remap-reset-base (face)
|
2008-06-03 11:05:52 +00:00
|
|
|
|
"Set the base remapping of FACE to inherit from FACE's global definition."
|
|
|
|
|
(let ((entry (assq face face-remapping-alist)))
|
|
|
|
|
(when entry
|
|
|
|
|
;; If there's nothing except a base remapping, we simply remove
|
|
|
|
|
;; the entire remapping entry, as setting the base to the default
|
|
|
|
|
;; would be the same as the global definition. Otherwise, we
|
|
|
|
|
;; modify the base remapping.
|
|
|
|
|
(if (null (cddr entry)) ; nothing except base remapping
|
|
|
|
|
(setq face-remapping-alist ; so remove entire entry
|
|
|
|
|
(remq entry face-remapping-alist))
|
|
|
|
|
(setcar (last entry) face))))) ; otherwise, just inherit global def
|
|
|
|
|
|
|
|
|
|
;;;### autoload
|
2008-06-05 02:42:55 +00:00
|
|
|
|
(defun face-remap-set-base (face &rest specs)
|
2008-06-03 11:05:52 +00:00
|
|
|
|
"Set the base remapping of FACE in the current buffer to SPECS.
|
|
|
|
|
If SPECS is empty, the default base remapping is restored, which
|
|
|
|
|
inherits from the global definition of FACE; note that this is
|
|
|
|
|
different from SPECS containing a single value `nil', which does
|
|
|
|
|
not inherit from the global definition of FACE."
|
|
|
|
|
(if (or (null specs)
|
|
|
|
|
(and (eq (car specs) face) (null (cdr specs)))) ; default
|
|
|
|
|
;; Set entry back to default
|
2008-06-05 02:42:55 +00:00
|
|
|
|
(face-remap-reset-base face)
|
2008-06-03 11:05:52 +00:00
|
|
|
|
;; Set the base remapping
|
|
|
|
|
(make-local-variable 'face-remapping-alist)
|
|
|
|
|
(let ((entry (assq face face-remapping-alist)))
|
|
|
|
|
(if entry
|
|
|
|
|
(setcar (last entry) specs) ; overwrite existing base entry
|
|
|
|
|
(push (list face specs) face-remapping-alist)))))
|
2008-06-04 11:14:07 +00:00
|
|
|
|
|
2008-06-03 11:05:52 +00:00
|
|
|
|
|
|
|
|
|
;; ----------------------------------------------------------------
|
|
|
|
|
;; text-scale-mode
|
|
|
|
|
|
|
|
|
|
(defcustom text-scale-mode-step 1.2
|
|
|
|
|
"Scale factor used by `text-scale-mode'.
|
|
|
|
|
Each positive or negative step scales the default face height by this amount."
|
|
|
|
|
:group 'display
|
|
|
|
|
:type 'number)
|
|
|
|
|
|
|
|
|
|
;; current remapping cookie for text-scale-mode
|
|
|
|
|
(defvar text-scale-mode-remapping nil)
|
|
|
|
|
(make-variable-buffer-local 'text-scale-mode-remapping)
|
|
|
|
|
|
|
|
|
|
;; Lighter displayed for text-scale-mode in mode-line minor-mode list
|
|
|
|
|
(defvar text-scale-mode-lighter "+0")
|
|
|
|
|
(make-variable-buffer-local 'text-scale-mode-lighter)
|
|
|
|
|
|
|
|
|
|
;; Number of steps that text-scale-mode will increase/decrease text height
|
|
|
|
|
(defvar text-scale-mode-amount 0)
|
|
|
|
|
(make-variable-buffer-local 'text-scale-mode-amount)
|
|
|
|
|
|
|
|
|
|
(define-minor-mode text-scale-mode
|
|
|
|
|
"Minor mode for displaying buffer text in a larger/smaller font than usual.
|
|
|
|
|
|
|
|
|
|
The amount of scaling is determined by the variable
|
2008-06-04 11:14:07 +00:00
|
|
|
|
`text-scale-mode-amount': one step scales the global default
|
|
|
|
|
face size by the value of the variable `text-scale-mode-step'
|
|
|
|
|
\(a negative amount shrinks the text).
|
|
|
|
|
|
2008-06-05 02:42:55 +00:00
|
|
|
|
The `text-scale-increase' and `text-scale-decrease' functions may
|
|
|
|
|
be used to interactively modify the variable
|
|
|
|
|
`text-scale-mode-amount' (they also enable or disable
|
|
|
|
|
`text-scale-mode' as necessary)."
|
2008-06-03 11:05:52 +00:00
|
|
|
|
:lighter (" " text-scale-mode-lighter)
|
|
|
|
|
(when text-scale-mode-remapping
|
2008-06-05 02:42:55 +00:00
|
|
|
|
(face-remap-remove-relative text-scale-mode-remapping))
|
2008-06-03 11:05:52 +00:00
|
|
|
|
(setq text-scale-mode-lighter
|
|
|
|
|
(format (if (>= text-scale-mode-amount 0) "+%d" "%d")
|
|
|
|
|
text-scale-mode-amount))
|
|
|
|
|
(setq text-scale-mode-remapping
|
|
|
|
|
(and text-scale-mode
|
2008-06-05 02:42:55 +00:00
|
|
|
|
(face-remap-add-relative 'default
|
2008-06-03 11:05:52 +00:00
|
|
|
|
:height
|
|
|
|
|
(expt text-scale-mode-step
|
|
|
|
|
text-scale-mode-amount))))
|
|
|
|
|
(force-window-update (current-buffer)))
|
|
|
|
|
|
|
|
|
|
;;;###autoload
|
2008-06-05 02:42:55 +00:00
|
|
|
|
(defun text-scale-increase (&optional inc)
|
2008-06-03 11:05:52 +00:00
|
|
|
|
"Increase the height of the default face in the current buffer by INC steps.
|
|
|
|
|
If the new height is other than the default, `text-scale-mode' is enabled.
|
|
|
|
|
|
|
|
|
|
Each step scales the height of the default face by the variable
|
|
|
|
|
`text-scale-mode-step' (a negative number of steps decreases the
|
|
|
|
|
height by the same amount). As a special case, an argument of 0
|
|
|
|
|
will remove any scaling currently active."
|
2008-06-04 05:38:04 +00:00
|
|
|
|
(interactive "p")
|
2008-06-03 11:05:52 +00:00
|
|
|
|
(setq text-scale-mode-amount (if (= inc 0) 0 (+ text-scale-mode-amount inc)))
|
|
|
|
|
(text-scale-mode (if (zerop text-scale-mode-amount) -1 1)))
|
|
|
|
|
|
|
|
|
|
;;;###autoload
|
2008-06-05 02:42:55 +00:00
|
|
|
|
(defun text-scale-decrease (&optional dec)
|
2008-06-03 11:05:52 +00:00
|
|
|
|
"Decrease the height of the default face in the current buffer by DEC steps.
|
2008-06-05 02:42:55 +00:00
|
|
|
|
See `text-scale-increase' for more details."
|
2008-06-04 05:38:04 +00:00
|
|
|
|
(interactive "p")
|
2008-06-05 02:42:55 +00:00
|
|
|
|
(text-scale-increase (- dec)))
|
2008-06-03 11:05:52 +00:00
|
|
|
|
|
2008-06-05 02:42:55 +00:00
|
|
|
|
;;;###autoload (define-key ctl-x-map [(control ?+)] 'text-scale-adjust)
|
|
|
|
|
;;;###autoload (define-key ctl-x-map [(control ?-)] 'text-scale-adjust)
|
|
|
|
|
;;;###autoload (define-key ctl-x-map [(control ?=)] 'text-scale-adjust)
|
|
|
|
|
;;;###autoload (define-key ctl-x-map [(control ?0)] 'text-scale-adjust)
|
2008-06-04 05:38:04 +00:00
|
|
|
|
;;;###autoload
|
2008-06-05 02:42:55 +00:00
|
|
|
|
(defun text-scale-adjust (&optional inc)
|
2008-06-04 05:38:04 +00:00
|
|
|
|
"Increase or decrease the height of the default face in the current buffer.
|
|
|
|
|
|
|
|
|
|
The actual adjustment made depends on the final component of the
|
2008-06-04 11:14:07 +00:00
|
|
|
|
key-binding used to invoke the command, with all modifiers removed:
|
2008-06-04 05:38:04 +00:00
|
|
|
|
|
|
|
|
|
+, = Increase the default face height by one step
|
|
|
|
|
- Decrease the default face height by one step
|
|
|
|
|
0 Reset the default face height to the global default
|
|
|
|
|
|
|
|
|
|
Then, continue to read input events and further adjust the face
|
2008-06-04 11:14:07 +00:00
|
|
|
|
height as long as the input event read (with all modifiers removed)
|
|
|
|
|
is one of the above.
|
2008-06-04 05:38:04 +00:00
|
|
|
|
|
|
|
|
|
Each step scales the height of the default face by the variable
|
|
|
|
|
`text-scale-mode-step' (a negative number of steps decreases the
|
|
|
|
|
height by the same amount). As a special case, an argument of 0
|
|
|
|
|
will remove any scaling currently active.
|
|
|
|
|
|
|
|
|
|
This command is a special-purpose wrapper around the
|
2008-06-05 02:42:55 +00:00
|
|
|
|
`text-scale-increase' command which makes repetition convenient
|
|
|
|
|
even when it is bound in a non-top-level keymap. For binding in
|
|
|
|
|
a top-level keymap, `text-scale-increase' or
|
|
|
|
|
`text-scale-decrease' may be more appropriate."
|
2008-06-04 05:38:04 +00:00
|
|
|
|
(interactive "p")
|
2008-06-04 11:14:07 +00:00
|
|
|
|
(let ((first t)
|
2008-06-04 05:38:04 +00:00
|
|
|
|
(step t)
|
|
|
|
|
(ev last-command-event))
|
|
|
|
|
(while step
|
|
|
|
|
(let ((base (event-basic-type ev)))
|
|
|
|
|
(cond ((or (eq base ?+) (eq base ?=))
|
|
|
|
|
(setq step inc))
|
|
|
|
|
((eq base ?-)
|
|
|
|
|
(setq step (- inc)))
|
|
|
|
|
((eq base ?0)
|
|
|
|
|
(setq step 0))
|
2008-06-04 11:14:07 +00:00
|
|
|
|
(first
|
2008-06-04 05:38:04 +00:00
|
|
|
|
(setq step inc))
|
|
|
|
|
(t
|
|
|
|
|
(setq step nil))))
|
|
|
|
|
(when step
|
2008-06-05 02:42:55 +00:00
|
|
|
|
(text-scale-increase step)
|
2008-06-04 05:38:04 +00:00
|
|
|
|
(setq inc 1 first nil)
|
|
|
|
|
(setq ev (read-event))))
|
|
|
|
|
(push ev unread-command-events)))
|
|
|
|
|
|
2008-06-03 11:05:52 +00:00
|
|
|
|
|
|
|
|
|
;; ----------------------------------------------------------------
|
|
|
|
|
;; variable-pitch-mode
|
|
|
|
|
|
|
|
|
|
;; suggested key binding: (global-set-key "\C-cv" 'variable-pitch-mode)
|
|
|
|
|
|
|
|
|
|
;; current remapping cookie for variable-pitch-mode
|
|
|
|
|
(defvar variable-pitch-mode-remapping nil)
|
|
|
|
|
(make-variable-buffer-local 'variable-pitch-mode-remapping)
|
|
|
|
|
|
2008-06-05 00:11:16 +00:00
|
|
|
|
;;;###autoload
|
2008-06-03 11:05:52 +00:00
|
|
|
|
(define-minor-mode variable-pitch-mode
|
2008-06-04 11:14:07 +00:00
|
|
|
|
"Variable-pitch default-face mode.
|
|
|
|
|
When active, causes the buffer text to be displayed using
|
|
|
|
|
the `variable-pitch' face."
|
2008-06-03 11:05:52 +00:00
|
|
|
|
:lighter " VarPitch"
|
|
|
|
|
(when variable-pitch-mode-remapping
|
2008-06-05 02:42:55 +00:00
|
|
|
|
(face-remap-remove-relative variable-pitch-mode-remapping))
|
2008-06-03 11:05:52 +00:00
|
|
|
|
(setq variable-pitch-mode-remapping
|
|
|
|
|
(and variable-pitch-mode
|
2008-06-05 02:42:55 +00:00
|
|
|
|
(face-remap-add-relative 'default 'variable-pitch)))
|
2008-06-03 11:05:52 +00:00
|
|
|
|
(force-window-update (current-buffer)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(provide 'face-remap)
|
|
|
|
|
|
|
|
|
|
;; arch-tag: 5c5f034b-8d58-4967-82bd-d61fd364e686
|
|
|
|
|
;;; face-remap.el ends here
|