comparison man/lispref/specifiers.texi @ 1135:9eddcb9548e2

[xemacs-hg @ 2002-12-02 17:56:58 by stephent] texinfo improvements <87d6okxq4i.fsf@tleepslib.sk.tsukuba.ac.jp>
author stephent
date Mon, 02 Dec 2002 17:57:09 +0000
parents 576fb035e263
children 05ed51332340
comparison
equal deleted inserted replaced
1134:dd61dd14b2a4 1135:9eddcb9548e2
1 @c -*-texinfo-*- 1 @c -*-texinfo-*-
2 @c This is part of the XEmacs Lisp Reference Manual. 2 @c This is part of the XEmacs Lisp Reference Manual.
3 @c Copyright (C) 1995, 1996 Ben Wing. 3 @c Copyright (C) 1995, 1996 Ben Wing.
4 @c Copyright (C) 2002 Free Software Foundation, Inc.
4 @c See the file lispref.texi for copying conditions. 5 @c See the file lispref.texi for copying conditions.
5 @setfilename ../../info/specifiers.info 6 @setfilename ../../info/specifiers.info
6 @node Specifiers, Faces and Window-System Objects, Extents, top 7 @node Specifiers, Faces and Window-System Objects, Extents, top
7 @chapter Specifiers 8 @chapter Specifiers
8 @cindex specifier 9 @cindex specifier
9 10
10 A specifier is an object used to keep track of a property whose value 11 A specifier is an object used to keep track of a property whose value
11 may vary depending on the particular situation (e.g. particular buffer 12 should vary according to @emph{display context}, a window, a frame, or
12 displayed in a particular window) that it is used in. The value of many 13 device. The value of many built-in properties, such as the font,
13 built-in properties, such as the font, foreground, background, and such 14 foreground, background, and such properties of a face and variables
14 properties of a face and variables such as 15 such as @code{modeline-shadow-thickness} and
15 @code{modeline-shadow-thickness} and @code{top-toolbar-height}, is 16 @code{top-toolbar-height}, is actually a specifier object. The
16 actually a specifier object. The specifier object, in turn, is 17 specifier object, in turn, is ``instanced'' in a particular situation
17 ``instanced'' in a particular situation to yield the real value 18 to yield the real value of the property in the current context.
18 of the property in that situation.
19 19
20 @defun specifierp object 20 @defun specifierp object
21 This function returns non-@code{nil} if @var{object} is a specifier. 21 This function returns non-@code{nil} if @var{object} is a specifier.
22 @end defun 22 @end defun
23 23
24 @menu 24 @menu
25 * Introduction to Specifiers:: Specifiers provide a clean way for 25 * Introduction to Specifiers:: Specifiers provide a clean way for
26 display and other properties to vary 26 display and other properties to vary
27 (under user control) in a wide variety 27 (under user control) in a wide variety
28 of contexts. 28 of contexts.
29 * Simple Specifier Usage:: Getting started with specifiers.
29 * Specifiers In-Depth:: Gory details about specifier innards. 30 * Specifiers In-Depth:: Gory details about specifier innards.
30 * Specifier Instancing:: Instancing means obtaining the ``value'' of 31 * Specifier Instancing:: Instancing means obtaining the ``value'' of
31 a specifier in a particular context. 32 a specifier in a particular context.
32 * Specifier Types:: Specifiers come in different flavors. 33 * Specifier Types:: Specifiers come in different flavors.
33 * Adding Specifications:: Specifications control a specifier's ``value'' 34 * Adding Specifications:: Specifications control a specifier's ``value''
46 @end menu 47 @end menu
47 48
48 @node Introduction to Specifiers 49 @node Introduction to Specifiers
49 @section Introduction to Specifiers 50 @section Introduction to Specifiers
50 51
51 Sometimes you may want the value of a property to vary depending on 52 Perhaps the most useful way to explain specifiers is via an analogy.
52 the context the property is used in. A simple example of this in XEmacs 53 Emacs Lisp programmers are used to @emph{buffer-local variables}
53 is buffer-local variables. For example, the variable 54 @ref{buffer-local variables}. For example, the variable
54 @code{modeline-format}, which controls the format of the modeline, can 55 @code{modeline-format}, which controls the format of the modeline, can
55 have different values depending on the particular buffer being edited. 56 have different values depending on the particular buffer being edited.
56 The variable has a default value which most modes will use, but a 57 The variable has a default value which most modes will use, but a
57 specialized package such as Calendar might change the variable so 58 specialized package such as Calendar might change the variable so as
58 as to tailor the modeline to its own purposes. 59 to tailor the modeline to its own purposes. Other variables are
60 perhaps best thought of as ``mode local,'' such as font-lock keywords,
61 but they are implemented as buffer locals.
59 62
60 Other properties (such as those that can be changed by the 63 Other properties (such as those that can be changed by the
61 @code{modify-frame-parameters} function, for example the color of the 64 @code{modify-frame-parameters} function, for example the color of the
62 text cursor) can have frame-local values, although it might also make 65 text cursor) can have frame-local values, although it might also make
63 sense for them to have buffer-local values. In other cases, you might 66 sense for them to have buffer-local values. In other cases, you might
68 value in a specified buffer, another value in all other buffers 71 value in a specified buffer, another value in all other buffers
69 displayed on a particular frame, another value in all other buffers 72 displayed on a particular frame, another value in all other buffers
70 displayed in all other frames on any mono (two-color, e.g. black and 73 displayed in all other frames on any mono (two-color, e.g. black and
71 white only) displays, and a default value in all other circumstances. 74 white only) displays, and a default value in all other circumstances.
72 75
73 A @dfn{specifier} is a generalization of this, allowing a great deal 76 Specifiers generalize both buffer- and frame-local properties.
74 of flexibility in controlling exactly what value a property has in which 77 Specifiers vary according to the @emph{display} context. Font-lock
75 circumstances. It is most commonly used for display properties, such as 78 keywords in a buffer will be the same no matter which window the
76 an image or the foreground color of a face. As a simple example, you can 79 buffer is displayed in, but windows on TTY devices will simply not be
77 specify that the foreground of the default face be 80 capable of the flexibility that windows on modern GUI devices are.
81 Specifiers provide a way for the programmer to @emph{declare} that a
82 emphasized text should be italic on GUI devices and inverse video on
83 TTYs. They also provide a way for the programmer to declare
84 fallbacks, so that a color specified as ``chartreuse'' where possible
85 can fall back to ``yellow'' on devices where only ANSI (4-bit) color
86 is available. The complex calculations and device querying are
87 transparent to both user and programmer. You ask for what you want;
88 it's up to XEmacs to provide it, or a reasonable approximation.
89
90 We call such a declaration a @dfn{specification}. A @dfn{specification}
91 applies in a particular @dfn{locale}, which is a window, buffer, frame,
92 device, or the global locale. The value part of the specification is
93 called an @dfn{instantiator}. The process of determining the value in a
94 particular context, or @dfn{domain}, is called @dfn{instantiation} or
95 @dfn{instancing}. A domain is a window, frame, or device.
96
97 The difference between @dfn{locale} and @dfn{domain} is somewhat subtle.
98 You may think of a locale as a class of domains, which may span
99 different devices. Since the specification is abstract (a Lisp form),
100 you can state it without reference to a device. On the other hand, when
101 you instantiate a specification, you must know the type of the device.
102 It is useless to specify that ``blue mean italic'' on a monochrome
103 device. Thus instantiation requires specification of the device on
104 which it will be rendered.
105
106 Thus a @dfn{specifier} allows a great deal of flexibility in
107 controlling exactly what value a property has in which circumstances.
108 It is most commonly used for display properties, such as an image or
109 the foreground color of a face. As a simple example, you can specify
110 that the foreground of the default face be
78 111
79 @itemize @bullet 112 @itemize @bullet
80 @item 113 @item
81 blue for a particular buffer 114 blue for a particular buffer
82 @item 115 @item
95 @item 128 @item
96 red for all other buffers displayed on a color device 129 red for all other buffers displayed on a color device
97 @item 130 @item
98 white for all other buffers 131 white for all other buffers
99 @end itemize 132 @end itemize
133
134 @node Simple Specifier Usage
135 @section Simple Specifier Usage
136 @cindex specifier examples
137 @cindex examples, specifier
138 @cindex adding a button to a toolbar
139 @cindex toolbar button, adding
140
141 A useful specifier application is adding a button to a toolbar. XEmacs
142 provides several toolbars, one along each edge of the frame. Normally
143 only one is used at a time, the default. The default toolbar is
144 actually a specifier object which is the value of @code{default-toolbar}.
145
146 The specification of a toolbar is simple: it is a list of buttons.
147 Each button is a vector with four elements: an icon, a command, the
148 enabled flag, and a help string. Let's retrieve the instance of the
149 toolbar you see in the selected frame.
150
151 @example
152 (specifier-instance default-toolbar)
153 @end example
154
155 The value returned is, as promised, a list of vectors. Now let's build
156 up a button, and add it to the toolbar. Our button will invoke the last
157 defined keyboard macro. This is an alternative to
158 @code{name-last-kbd-macro} for creating a persistent macro, rather than
159 an alias for @kbd{C-x e}.
160
161 A toolbar button icon can be quite sophisticated, with different images
162 for button up, button down, and disabled states, and a similar set with
163 captions. We'll use a very simple icon, but we have to jump through a
164 few non-obvious hoops designed to support the sophisticated applications.
165 The rest of the button descriptor is straightforward.
166
167 @example
168 (setq toolbar-my-kbd-macro-button
169 `[ (list (make-glyph "MyKbdMac"))
170 (lambda () (interactive) (execute-kbd-macro ,last-kbd-macro))
171 t
172 "Execute a previously defined keyboard macro." ])
173
174 (set-specifier default-toolbar
175 (cons toolbar-my-kbd-macro-button
176 (specifier-specs default-toolbar 'global))
177 'global)
178 @end example
179
180 To remove the button, just substitute the function @code{delete} for the
181 @code{cons} above.
182
183 What is the difference between @code{specifier-instance}, which we used
184 in the example of retrieving the toolbar descriptor, and
185 @code{specifier-specs}, which was used in the toolbar manipulating code?
186 @code{specifier-specs} retrieves a copy of the instantiator, which is
187 abstract and does not depend on context. @code{specifier-instance}, on
188 the other hand, actually instantiates the specification, and returns the
189 result for the given context. Another way to express this is:
190 @code{specifier-specs} takes a @emph{locale} as an argument, while
191 @code{specifier-instance} takes a @emph{domain}. The reason for
192 providing @code{specifier-instance} is that sometimes you wish to see
193 the object that XEmacs will actually use. @code{specifier-specs}, on
194 the other hand, shows you what the programmer (or user) requested. When
195 a program manipulates specifications, clearly it's the latter that is
196 desirable.
197
198 In the case of the toolbar descriptor, it turns out that these are the
199 same: the instancing process is trivial. However, many specifications
200 have non-trivial instancing. Compare the results of the following forms
201 on my system. (The @samp{(cdr (first ...))} form is due to my use of
202 Mule. On non-Mule XEmacsen, just use @code{specifier-specs}.)
203
204 @example
205 (cdr (first (specifier-specs (face-font 'default) 'global)))
206 => "-*--14-*jisx0208*-0"
207
208 (specifier-instance (face-font 'default))
209 #<font-instance "-*--14-*jisx0208*-0" on #<x-device on ":0.0" 0x970> 0xe0028b 0x176b>
210 @end example
211
212 In this case, @code{specifier-instance} returns an opaque object;
213 programs can't work on it, they can only pass it around. Worse, in some
214 environments the instantiation will fail, resulting in a different value
215 (when another instantiation succeeds), or worse yet, an error, if all
216 attempts to instance the specifier fail. @code{specifier-instance} is
217 context-dependent, even for the exact same specification.
218 @code{specifier-specs} is deterministic, and only depends on the
219 specifications.
220
221 Note that in the toolbar-changing code we operate in the global locale.
222 This means that narrower locales, if they have specifications, will
223 shadow our changes. (Specifier instancing does not merge
224 specifications. It selects the "highest-priority successful
225 specification" and instances that.)
226
227 In fact, in our example, it seems pretty likely that different buffers
228 @emph{should} have different buttons. (The icon can be the same, but
229 the keyboard macro you create in a Dired buffer is highly unlikely to be
230 useful in a LaTeX buffer!) Here's one way to implement this:
231
232 @example
233 (setq toolbar-my-kbd-macro-button
234 `[ (list (make-glyph "MyKbdMac"))
235 (lambda () (interactive) (execute-kbd-macro ,last-kbd-macro))
236 t
237 "Execute a previously defined keyboard macro." ])
238
239 (set-specifier default-toolbar
240 (cons toolbar-my-kbd-macro-button
241 (cond ((specifier-specs default-toolbar
242 (current-buffer)))
243 ((specifier-specs default-toolbar
244 'global)))
245 (current-buffer))
246 @end example
247
248 Finally, a cautionary note: the use of @code{specifier-specs} in the
249 code above is for expository purposes. Don't use it in production code.
250 In fact, the @code{set-specifier} form above is likely to fail
251 occasionally, because you can add many specifications for the same
252 locale.
253
254 In these cases, @code{specifier-specs} will return a list. A further
255 refinement is that a specification may be associated with a set of
256 @dfn{specifier tags}. If the list of specifier tags is non-nil, then
257 @code{specifier-specs} will return a cons of the tag set and the
258 instantiator. Evidently @code{specifier-specs} is a bit unreliable.
259 (For toolbars, the code above should work 99% of the time, because
260 toolbars are rarely changed. Since instantiation is trivial, multiple
261 specs are not useful---the first one always succeeds.)
262
263 In fact, @code{specifier-specs} is intended to be used to display specs
264 to humans with a minimum of clutter. The robust way to access
265 specifications is via @code{specifier-spec-list}. @xref{Adding
266 Specifications}, for the definition of @dfn{spec-list}.
267 @xref{Retrieving Specifications} for documentation of
268 @code{specifier-specs} and @code{specifier-spec-list}. To get the
269 desired effect, replace the form @code{(specifier-spec default-toolbar
270 'global)} with
271
272 @example
273 (cdr (second (first (specifier-spec-list default-toolbar 'global))))
274 @end example
275
276 (It should be obvious why the example uses the lazy unreliable method!)
100 277
101 @node Specifiers In-Depth 278 @node Specifiers In-Depth
102 @section In-Depth Overview of a Specifier 279 @section In-Depth Overview of a Specifier
103 @cindex specification (in a specifier) 280 @cindex specification (in a specifier)
104 @cindex domain (in a specifier) 281 @cindex domain (in a specifier)
119 @cindex specifier, inst-list 296 @cindex specifier, inst-list
120 @cindex specifier, inst-pair 297 @cindex specifier, inst-pair
121 @cindex specifier, tag 298 @cindex specifier, tag
122 @cindex specifier, tag set 299 @cindex specifier, tag set
123 300
124 A specifier object encapsulates a set of @dfn{specifications}, each of 301 Having variables vary according the editing context is very useful, and
125 which says what its value should be if a particular condition applies. 302 the buffer is the natural ``atomic'' unit of editing context. In a GUI
303 environment, it can be similarly useful to have variables whose values
304 vary according to display context. The atomic unit of display context
305 is the Emacs window. Buffers are cleanly grouped by modes, but windows
306 are not so easily pigeonholed. On the one hand, a window displays a
307 buffer, and thus one possible hierarchy is window, buffer, mode. On the
308 other, a window is a component of a frame. This generates the window,
309 frame, device hierarchy. Finally, there are objects such as toolbars
310 whose properties are described by specifiers. These do not fit
311 naturally into either hierarchy. This problem is as yet not cleanly
312 solved.
313
314 Another potential source of conceptual confusion is the instantiation
315 process. Instantiating a buffer-local variable is simple: at any given
316 point in time there is a current buffer, and its local values are used
317 and set whenever the variable is accessed, unless the programmer goes to
318 some special effort (uses @code{default-value} and @code{set-default}.
319 However, a specifier object encapsulates a set of @dfn{specifications},
320 each of which says what its value should be if a particular condition
321 applies. Several such conditions might apply simultaneously in a given
322 window.
323
126 For example, one specification might be ``The value should be 324 For example, one specification might be ``The value should be
127 darkseagreen2 on X devices'' another might be ``The value should be blue 325 darkseagreen2 on X devices'' another might be ``The value should be blue
128 in the *Help* buffer''. In specifier terminology, these conditions are 326 in the *Help* buffer''. So what do we do for "the *Help* buffer on an X
129 called @dfn{locales} and the values are called @dfn{instantiators}. 327 device"? The answer is simple: give each type of locale a priority and
328 check them in priority order, returning the first instantiator that
329 successfully instantiates a value.
330
130 Given a specifier, a logical question is ``What is its value in a 331 Given a specifier, a logical question is ``What is its value in a
131 particular situation?'' This involves looking through the specifications 332 particular situation?'' This involves looking through the specifications
132 to see which ones apply to this particular situation, and perhaps 333 to see which ones apply to this particular situation, and perhaps
133 preferring one over another if more than one applies. In specifier 334 preferring one over another if more than one applies. In specifier
134 terminology, a ``particular situation'' is called a @dfn{domain}, and 335 terminology, a ``particular situation'' is called a @dfn{domain}, and
138 a particular window, it retrieves the specifier for the foreground color 339 a particular window, it retrieves the specifier for the foreground color
139 of the default face and @dfn{instances} it in the domain given by that 340 of the default face and @dfn{instances} it in the domain given by that
140 window; in other words, it asks the specifier, ``What is your value in 341 window; in other words, it asks the specifier, ``What is your value in
141 this window?''. 342 this window?''.
142 343
344 Note that the redisplay example is in a sense canonical. That is,
345 specifiers are designed to present a uniform and @emph{efficient} API
346 to redisplay. It is the efficiency constraint that motivates the
347 introduction of specifier tags, and many restrictions on access (for
348 example, a buffer is not a domain, and you cannot instantiate a
349 specifier over a buffer).
350
143 More specifically, a specifier contains a set of @dfn{specifications}, 351 More specifically, a specifier contains a set of @dfn{specifications},
144 each of which associates a @dfn{locale} (a window object, a buffer 352 each of which associates a @dfn{locale} (a window object, a buffer
145 object, a frame object, a device object, or the symbol @code{global}) 353 object, a frame object, a device object, or the symbol @code{global})
146 with an @dfn{inst-list}, which is a list of one or more 354 with an @dfn{inst-list}, which is a list of one or more
147 @dfn{inst-pairs}. (For each possible locale, there can be at most one 355 @dfn{inst-pairs}. (For each possible locale, there can be at most one
158 @dfn{predicate} associated with it, which is a function of one argument 366 @dfn{predicate} associated with it, which is a function of one argument
159 (a device) that specifies whether the tag matches that particular 367 (a device) that specifies whether the tag matches that particular
160 device. (If a tag does not have a predicate, it matches all devices.) 368 device. (If a tag does not have a predicate, it matches all devices.)
161 All tags in a tag set must match a device for the associated inst-pair 369 All tags in a tag set must match a device for the associated inst-pair
162 to be instantiable over that device. (A null tag set is perfectly 370 to be instantiable over that device. (A null tag set is perfectly
163 valid.) 371 valid, and trivially matches all devices.)
164 372
373 @c #### don't we have more device types now, gtk, ms-windows, mac-carbon?
165 The valid device types (normally @code{x}, @code{tty}, and 374 The valid device types (normally @code{x}, @code{tty}, and
166 @code{stream}) and device classes (normally @code{color}, 375 @code{stream}) and device classes (normally @code{color},
167 @code{grayscale}, and @code{mono}) can always be used as tags, and match 376 @code{grayscale}, and @code{mono}) can always be used as tags, and match
168 devices of the associated type or class (@pxref{Consoles and Devices}). 377 devices of the associated type or class (@pxref{Consoles and Devices}).
169 User-defined tags may be defined, with an optional predicate specified. 378 User-defined tags may be defined, with an optional predicate specified.