changeset 1875:ec2d1e636272

[xemacs-hg @ 2004-01-23 10:00:20 by stephent] specifier docs <87u12nugu7.fsf@tleepslib.sk.tsukuba.ac.jp>
author stephent
date Fri, 23 Jan 2004 10:00:34 +0000
parents 31c960994dba
children 6f2d5c78ac34
files lisp/ChangeLog lisp/specifier.el man/ChangeLog man/lispref/specifiers.texi src/ChangeLog src/specifier.c
diffstat 6 files changed, 237 insertions(+), 110 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/ChangeLog	Thu Jan 22 22:51:03 2004 +0000
+++ b/lisp/ChangeLog	Fri Jan 23 10:00:34 2004 +0000
@@ -1,3 +1,12 @@
+2004-01-22  Stephen J. Turnbull  <stephen@xemacs.org>
+
+	* specifier.el (canonicalize-spec): Fix typo in docstring.
+	(make-specifier-and-init):
+	(map-specifier):
+	(canonicalize-spec-list):
+	(set-specifier):
+	Improve docstring.
+	
 2004-01-21  Jerry James  <james@xemacs.org>
 
 	* wid-edit.el: Remove duplicate sexp widget definitions.
--- a/lisp/specifier.el	Thu Jan 22 22:51:03 2004 +0000
+++ b/lisp/specifier.el	Fri Jan 23 10:00:34 2004 +0000
@@ -32,16 +32,15 @@
 ;;; Code:
 
 (defun make-specifier-and-init (type spec-list &optional dont-canonicalize)
-  "Create and initialize a new specifier.
+  "Create and initialize a specifier of type TYPE with spec(s) SPEC-LIST.
 
-This is a front-end onto `make-specifier' that allows you to create a
-specifier and add specs to it at the same time.  TYPE specifies the
-specifier type.  SPEC-LIST supplies the specification(s) to be added
-to the specifier. Normally, almost any reasonable abbreviation of the
-full spec-list form is accepted, and is converted to the full form;
-however, if optional argument DONT-CANONICALIZE is non-nil, this
-conversion is not performed, and the SPEC-LIST must already be in full
-form.  See `canonicalize-spec-list'."
+A convenience API combining `make-specifier' and `set-specifier', allowing you
+to create a specifier and add specs to it at the same time.
+TYPE specifies the specifier type.  See `make-specifier' for known types.
+SPEC-LIST supplies the specification(s) to be added to the specifier, in any
+  form acceptable to `canonicalize-spec-list'.
+Optional DONT-CANONICALIZE, if non-nil, inhibits the conversion, and the
+  SPEC-LIST must already be in full form."
   (let ((sp (make-specifier type)))
     (if (not dont-canonicalize)
 	(setq spec-list (canonicalize-spec-list spec-list type)))
@@ -54,12 +53,13 @@
 		      ms-tag-set ms-exact-p)
   "Apply MS-FUNC to the specification(s) for MS-LOCALE in MS-SPECIFIER.
 
-If MS-LOCALE is a locale, MS-FUNC will be called for that locale.
-If MS-LOCALE is a locale type, MS-FUNC will be mapped over all locales
-of that type.  If MS-LOCALE is 'all or nil, MS-FUNC will be mapped
-over all locales in MS-SPECIFIER.
+If optional MS-LOCALE is a locale, MS-FUNC will be called for that locale.
+If MS-LOCALE is a locale type, MS-FUNC will be mapped over all locales of that
+type.  If MS-LOCALE is 'all or nil, MS-FUNC will be mapped over all locales in
+MS-SPECIFIER.
 
-MS-TAG-SET and MS-EXACT-P are as in `specifier-spec-list'.
+Optional MS-TAG-SET and MS-EXACT-P are as in `specifier-spec-list'.
+Optional MS-MAPARG will be passed to MS-FUNC.
 
 MS-FUNC is called with four arguments: the MS-SPECIFIER, the locale
 being mapped over, the inst-list for that locale, and the
@@ -173,8 +173,7 @@
 (defun canonicalize-spec (spec specifier-type &optional noerror)
   "Canonicalize the given SPEC (a specification).
 
-SPECIFIER-TYPE specifies the type of specifier that this SPEC-LIST
-will be used for.
+SPECIFIER-TYPE is the type of specifier that this SPEC will be used for.
 
 Canonicalizing means converting to the full form for a spec, i.e.
 `(LOCALE (TAG-SET . INSTANTIATOR) ...)'.  This function accepts a
@@ -226,9 +225,42 @@
 accepted by `set-specifier' and such into a form suitable for
 `add-spec-list-to-specifier'.
 
-This function tries extremely hard to resolve any ambiguities,
-and the built-in specifier types (font, image, toolbar, etc.) are
-designed so that there won't be any ambiguities.
+The canonicalization algorithm is as follows:
+
+1. Attempt to parse SPEC-LIST as a single, possibly abbreviated, specification.
+2. If (1) fails, attempt to parse SPEC-LIST as a list of (abbreviated)
+   specifications.
+3. If (2) fails, SPEC-LIST is invalid.
+
+A possibly abbreviated specification SPEC is parsed by
+
+1. Attempt to parse SPEC as a possibly abbreviated inst-list.
+2. If (1) fails, attempt to parse SPEC as a cons of a locale and an
+   (abbreviated) inst-list.
+3. If (2) fails, SPEC is invalid.
+
+A possibly abbreviated inst-list INST-LIST is parsed by
+
+1. Attempt to parse INST-LIST as a possibly abbreviated inst-pair.
+2. If (1) fails, attempt to parse INST-LIST as a list of (abbreviated)
+   inst-pairs.
+3. If (2) fails, INST-LIST is invalid.
+
+A possibly abbreviated inst-pair INST-PAIR is parsed by
+
+1. Check if INST-PAIR is `valid-instantiator-p'.
+2. If not, check if INST-PAIR is a cons of something that is a tag, ie,
+   `valid-specifier-tag-p', and something that is `valid-instantiator-p'.
+3. If not, check if INST-PAIR is a cons of a list of tags and something that
+   is `valid-instantiator-p'.
+
+In summary, this function generally prefers more abbreviated forms.
+
+This function tries extremely hard to resolve any ambiguities, and the
+built-in specifier types (font, image, toolbar, etc.) are designed so that
+there won't be any ambiguities.  (#### Unfortunately there are bugs in the
+treatment of toolbar spec-lists and generic spec-lists; avoid depending on
+canonicalization for these types.)
 
 If NOERROR is nil, signal an error if the spec-list is invalid;
 otherwise return t."
@@ -269,52 +301,47 @@
 	    (nreverse result)))))))
 
 (defun set-specifier (specifier value &optional locale tag-set how-to-add)
-  "Add a specification or specifications to SPECIFIER.
+  "Add the specification(s) given by VALUE to SPECIFIER in LOCALE.
+
+VALUE may be any of the values accepted by `canonicalize-spec-list', including
+
+-- an instantiator (either a Lisp object which will be returned when the
+   specifier is instanced, or a Lisp object that can be instantiated to
+   produce an opaque value: eg, a font name (string) can be used for a font
+   specifier, but an instance will be a font object)
+-- a list of instantiators
+-- a cons of a locale and an instantiator, or of a locale and a list of
+   instantiators
+-- a cons of a tag or tag-set and an instantiator (or list of instantiators)
+-- a cons of a locale and the previous type of item
+-- a list of one or more of any of the previous types of items
+-- a canonical spec-list.
 
-This function adds a specification of VALUE in locale LOCALE.
+See `canonicalize-spec-list' for details.  If you need to know the details,
+though, strongly consider using the unambiguous APIs `add-spec-to-specifier'
+and `add-spec-list-to-specifier' instead.
+
+Finally, VALUE can itself be a specifier (of the same type as
+SPECIFIER), if you want to copy specifications from one specifier
+to another; this is equivalent to calling `copy-specifier', and
+LOCALE, TAG-SET, and HOW-TO-ADD have the same semantics as with
+that function.
+
+Note that a VALUE of `nil' is either illegal or will be treated as a value of
+`nil'; it does not remove existing specifications.  Use `remove-specifier' for
+that.  N.B. `remove-specifier' defaults to removing all specifications, not
+just the 'global one!
+
+Warning: this function is inherently heuristic, and should not be relied on to
+properly resolve ambiguities, when specifier instantiators can be lists
+\(currently, for toolbar specifiers and generic specifiers).  In those cases
+use either `add-spec-to-specifier' or `add-spec-list-to-specifier'.
+
 LOCALE indicates where this specification is active, and should be
 a buffer, a window, a frame, a device, or the symbol `global' to
-indicate that it applies everywhere.  LOCALE usually defaults to
-`global' if omitted.
-
-VALUE is usually what is called an \"instantiator\" (which, roughly
-speaking, corresponds to the \"value\" of the property governed by
-SPECIFIER).  The valid instantiators for SPECIFIER depend on the type
-of SPECIFIER (which you can determine using `specifier-type').  The
-specifier `scrollbar-width', for example, is of type `integer',
-meaning its valid instantiators are integers.  The specifier governing
-the background color of the `default' face (you can retrieve this
-specifier using `(face-background 'default)') is of type `color',
-meaning its valid instantiators are strings naming colors and
-color-instance objects.  For some types of specifiers, such as `image'
-and `toolbar', the instantiators can be very complex.  Generally this
-is documented in the appropriate creation function --
-e.g. `make-color-specifier', `make-font-specifier',
-`make-image-specifier' -- or in the global variable holding the most
-common specifier for that type (`default-toolbar', `default-gutter',
-`current-display-table').
-
-NOTE: It does *not* work to give a VALUE of nil as a way of removing the
-specifications for a locale -- for many specifier types, such as `boolean',
-nil is a perfectly legitimate value to set.  Use `remove-specifier'
-instead. (And keep in mind that, if you omit the LOCALE argument to
-`remove-specifier', it removes *all* specifications!  If you want to remove
-just the `global' specification, make sure to specify a LOCALE of
-`global'.)
-
-VALUE can also be a list of instantiators.  This means basically,
-\"try each one in turn until you get one that works\".  This allows
-you to give funky instantiators that may only work in some cases,
-and provide more normal backups for the other cases. (For example,
-you might like the color \"darkseagreen2\", but some X servers
-don't recognize this color, so you could provide a backup
-\"forest green\".  Color TTY devices probably won't recognize this
-either, so you could provide a second backup \"green\".  You'd
-do this by specifying this list of instantiators:
-
-'(\"darkseagreen2\" \"forest green\" \"green\")
-
-VALUE can also be various more complicated forms; see below.
+indicate that it applies everywhere.  LOCALE defaults to
+`global' if omitted, and is overridden by locales provided by VALUE (in the
+cases where value is a full specification or a spec-list).
 
 Optional argument TAG-SET is a tag or a list of tags, to be associated
 with the VALUE.  Tags are symbols (usually naming device types, such
@@ -334,26 +361,6 @@
 See `copy-specifier' and `add-spec-to-specifier' for a full
 description of what each of these means.
 
-\[VALUE can actually be anything acceptable to `canonicalize-spec-list';
-this includes, among other things:
-
--- a cons of a locale and an instantiator (or list of instantiators)
--- a cons of a tag or tag-set and an instantiator (or list of
-   instantiators)
--- a cons of a locale and the previous type of item
--- a list of one or more of any of the previous types of items
-
-However, this usage is deprecated.  Either iterate and call `set-specifier'
-multiple times, or use the lower-level `add-spec-list-to-specifier'.  Also,
-in these cases, you cannot give a LOCALE or TAG-SET, because they do not
-make sense. (You will probably get an error if you try this.)]
-
-Finally, VALUE can itself be a specifier (of the same type as
-SPECIFIER), if you want to copy specifications from one specifier
-to another; this is equivalent to calling `copy-specifier', and
-LOCALE, TAG-SET, and HOW-TO-ADD have the same semantics as with
-that function.
-
 Note that `set-specifier' is exactly complementary to `specifier-specs'
 except in the case where SPECIFIER has no specs at all in it but nil
 is a valid instantiator (in that case, `specifier-specs' will return
@@ -361,14 +368,7 @@
 as meaning \"I'm adding a global instantiator and its value is `nil'\"),
 or in strange cases where there is an ambiguity between a spec-list
 and an inst-list, etc. (The built-in specifier types are designed
-in such a way as to avoid any such ambiguities.)
-
-NOTE: If you want to work with spec-lists, you should probably not
-use either `set-specifier' or `specifier-specs', but should use the
-lower-level functions `add-spec-list-to-specifier' and `specifier-spec-list'.
-These functions always work with fully-qualified spec-lists; thus, there
-is no possibility for ambiguity and no need to go through the function
-`canonicalize-spec-list', which is potentially time-consuming."
+in such a way as to avoid any such ambiguities.)"
 
   ;; backward compatibility: the old function had HOW-TO-ADD as the
   ;; third argument and no arguments after that.
--- a/man/ChangeLog	Thu Jan 22 22:51:03 2004 +0000
+++ b/man/ChangeLog	Fri Jan 23 10:00:34 2004 +0000
@@ -1,3 +1,14 @@
+2004-01-23  Stephen J. Turnbull  <stephen@xemacs.org>
+
+	* lispref/specifiers.texi (Specifier Instancing Functions): Add
+	documentation of `specifier-matching-instance'.
+	(Introduction to Specifiers): Fix typos.
+	(Simple Specifier Usage): Cross-reference Toolbar Intro.
+	(Creating Specifiers):
+	(Specifier Instancing Functions):
+	(Adding Specifications):
+	Various improvements.  Deprecate set-specifier a bit more.
+
 2004-01-20  Stephen J. Turnbull  <stephen@xemacs.org>
 
 	* lispref/specifiers.texi (Specifier Examples): Add new example,
--- a/man/lispref/specifiers.texi	Thu Jan 22 22:51:03 2004 +0000
+++ b/man/lispref/specifiers.texi	Fri Jan 23 10:00:34 2004 +0000
@@ -78,7 +78,7 @@
 keywords in a buffer will be the same no matter which window the
 buffer is displayed in, but windows on TTY devices will simply not be
 capable of the flexibility that windows on modern GUI devices are.
-Specifiers provide a way for the programmer to @emph{declare} that a
+Specifiers provide a way for the programmer to @emph{declare} that an
 emphasized text should be italic on GUI devices and inverse video on
 TTYs.  They also provide a way for the programmer to declare
 fallbacks, so that a color specified as ``chartreuse'' where possible
@@ -99,13 +99,13 @@
 different devices.  Since the specification is abstract (a Lisp form),
 you can state it without reference to a device.  On the other hand, when
 you instantiate a specification, you must know the type of the device.
-It is useless to specify that ``blue mean italic'' on a monochrome
+It is useless to specify that ``blue means emphasis'' on a monochrome
 device.  Thus instantiation requires specification of the device on
 which it will be rendered.
 
 Thus a @dfn{specifier} allows a great deal of flexibility in
 controlling exactly what value a property has in which circumstances.
-It is most commonly used for display properties, such as an image or
+Specifiers are most commonly used for display properties, such as an image or
 the foreground color of a face.  As a simple example, you can specify
 that the foreground of the default face be
 
@@ -141,7 +141,8 @@
 A useful specifier application is adding a button to a toolbar.  XEmacs
 provides several toolbars, one along each edge of the frame.  Normally
 only one is used at a time, the default.  The default toolbar is
-actually a specifier object which is the value of @code{default-toolbar}.
+actually a specifier object which is the value of
+@code{default-toolbar}.  @xref{Toolbar Intro}.
 
 The specification of a toolbar is simple:  it is a list of buttons.
 Each button is a vector with four elements:  an icon, a command, the
@@ -682,8 +683,13 @@
 the existing ones, and has the same semantics as for
 @code{add-spec-to-specifier}.
 
-In many circumstances, the higher-level function @code{set-specifier} is
-more convenient and should be used instead.
+The higher-level function @code{set-specifier} is often
+more convenient because it allows abbreviations of spec-lists to be used
+instead of the heavily nested canonical syntax.  However, one should
+take great care in using them with specifiers types which can have lists
+as instantiators, such as toolbar specifiers and generic specifiers.  In
+those cases it's probably best to use @code{add-spec-to-specifier} or
+@code{add-spec-list-to-specifier}.
 @end defun
 
 @defspec let-specifier specifier-list &rest body
@@ -733,7 +739,7 @@
 a global specification), a cons of a locale and instantiator or locale
 and instantiator list, a list of such conses, or nearly any other
 reasonable form.  More specifically, @var{value} can be anything
-accepted by @code{canonicalize-spec-list}.
+accepted by @code{canonicalize-spec-list} (described below).
 
 @var{locale}, @var{tag-set}, and @var{how-to-add} are the same as in
 @code{add-spec-to-specifier}.
@@ -746,7 +752,10 @@
 adding a global instantiator and its value is @code{nil}''), or in
 strange cases where there is an ambiguity between a spec-list and an
 inst-list, etc. (The built-in specifier types are designed in such a way
-as to avoid any such ambiguities.)
+as to avoid any such ambiguities.)  For robust code,
+@code{set-specifier} should probably be avoided for specifier types
+which accept lists as instantiators (currently toolbar specifiers and
+generic specifiers).
 
 If you want to work with spec-lists, you should probably not use these
 functions, but should use the lower-level functions
@@ -809,6 +818,10 @@
 @var{specifier-type} specifies the type of specifier that this
 @var{spec-list} will be used for.
 
+If @var{noerror} is @code{nil}, signal an error if the spec-list is
+invalid; otherwise return @code{t} for an invalid spec-list.  (Note that
+this cannot be confused with a canonical spec-list.)
+
 Canonicalizing means converting to the full form for a spec-list, i.e.
 @code{((@var{locale} (@var{tag-set} . @var{instantiator}) ...) ...)}.
 This function accepts a possibly abbreviated specification or a list of
@@ -820,8 +833,59 @@
 and the built-in specifier types (font, image, toolbar, etc.) are
 designed so that there won't be any ambiguities.
 
-If @var{noerror} is @code{nil}, signal an error if the spec-list is
-invalid; otherwise return @code{t}.
+The canonicalization algorithm is as follows:
+
+@enumerate
+@item
+Attempt to parse @var{spec-list} as a single, possibly abbreviated,
+specification.
+@item
+If that fails, attempt to parse @var{spec-list} as a list of (abbreviated)
+specifications.
+@item
+If that fails, @var{spec-list} is invalid.
+@end enumerate
+
+A possibly abbreviated specification @var{spec} is parsed by
+
+@enumerate
+@item
+Attempt to parse @var{spec} as a possibly abbreviated inst-list.
+@item
+If that fails, attempt to parse @var{spec} as a cons of a locale and an
+(abbreviated) inst-list.
+@item
+If that fails, @var{spec} is invalid.
+@end enumerate
+
+A possibly abbreviated inst-list @var{inst-list} is parsed by
+
+@enumerate
+@item
+Attempt to parse @var{inst-list} as a possibly abbreviated inst-pair.
+@item
+If that fails, attempt to parse @var{inst-list} as a list of (abbreviated)
+inst-pairs.
+@item
+If that fails, @var{inst-list} is invalid.
+@end enumerate
+
+A possibly abbreviated inst-pair @var{inst-pair} is parsed by
+
+@enumerate
+@item
+Check if @var{inst-pair} is @code{valid-instantiator-p}.
+@item
+If not, check if @var{inst-pair} is a cons of something that is a tag, ie,
+@code{valid-specifier-tag-p}, and something that is @code{valid-instantiator-p}.
+@item
+If not, check if @var{inst-pair} is a cons of a list of tags and something that
+is @code{valid-instantiator-p}.
+@item
+Otherwise, @var{inst-pair} is invalid.
+@end enumerate
+
+In summary, this function generally prefers more abbreviated forms.
 @end defun
 
 @node Retrieving Specifications
@@ -1037,6 +1101,36 @@
 value will be a string, pixmap, or subwindow.
 @end defun
 
+@defun specifier-matching-instance specifier matchspec &optional domain default no-fallback
+This function return an instance for @var{specifier} in @var{domain}
+that matches @var{matchspec}.  If no instance can be generated for
+@var{domain}, return @var{default}.
+
+This function is identical to @code{specifier-instance} except that a
+specification will only be considered if it matches @var{matchspec}.
+The definition of ``match,'' and allowed values for @var{matchspec}, are
+dependent on the particular type of specifier.  Here are some examples:
+
+@itemize
+@item
+For chartable (e.g. display table) specifiers, @var{matchspec} should be a
+character, and the specification (a chartable) must give a value for
+that character in order to be considered.  This allows you to specify,
+@emphe.g.}, a buffer-local display table that only gives values for particular
+characters.  All other characters are handled as if the buffer-local
+display table is not there. (Chartable specifiers are not yet
+implemented.)
+
+For font specifiers, @var{matchspec} should be a list (@var{charset}
+. @var{second-stage-p}), and the specification (a font string) must have
+a registry that matches the charset's registry.  (This only makes sense
+with Mule support.)  This makes it easy to choose a font that can
+display a particular character.  (This is what redisplay does, in fact.)
+@var{second-stage-p} means to ignore the font's registry and instead
+look at the characters in the font to see if the font can support the
+charset.  This currently only makes sense under MS Windows.
+@end defun
+
 @defun specifier-instance-from-inst-list specifier domain inst-list &optional default
 This function attempts to convert a particular inst-list into an
 instance.  This attempts to instantiate @var{inst-list} in the given
@@ -1288,16 +1382,20 @@
 @end defun
 
 @defun make-specifier-and-init type spec-list &optional dont-canonicalize
-This function creates and initialize a new specifier.
+This function creates and initializes a new specifier.
 
-This is a front-end onto @code{make-specifier} that allows you to create
+This is a convenience API combining @code{make-specifier} and
+@code{set-specifier} that allows you to create
 a specifier and add specs to it at the same time.  @var{type} specifies
-the specifier type.  @var{spec-list} supplies the specification(s) to be
-added to the specifier. Normally, almost any reasonable abbreviation of
-the full spec-list form is accepted, and is converted to the full form;
-however, if optional argument @var{dont-canonicalize} is non-@code{nil},
-this conversion is not performed, and the @var{spec-list} must already
-be in full form.  See @code{canonicalize-spec-list}.
+the specifier type.  Allowed types are as for @code{make-specifier}.
+
+@var{spec-list} supplies the specification(s) to be
+added to the specifier.  Any abbreviation of
+the full spec-list form accepted by @code{canonicalize-spec-list} may
+be used.
+However, if the optional argument @var{dont-canonicalize} is non-@code{nil},
+canonicalization is not performed, and the @var{spec-list} must already
+be in full form.
 @end defun
 
 @defun make-integer-specifier spec-list
@@ -1482,12 +1580,17 @@
 This function applies @var{func} to the specification(s) for
 @var{locale} in @var{specifier}.
 
-If @var{locale} is a locale, @var{func} will be called for that locale.
+If optional @var{locale} is a locale, @var{func} will be called for that
+locale.
 If @var{locale} is a locale type, @var{func} will be mapped over all
 locales of that type.  If @var{locale} is @code{nil} or the symbol
 @code{all}, @var{func} will be mapped over all locales in
 @var{specifier}.
 
+Optional @var{ms-tag-set} and @var{ms-exact-p} are as in
+@code{specifier-spec-list'}.
+Optional @var{ms-maparg} will be passed to @var{ms-func}.
+
 @var{func} is called with four arguments: the @var{specifier}, the
 locale being mapped over, the inst-list for that locale, and the
 optional @var{maparg}.  If any invocation of @var{func} returns
--- a/src/ChangeLog	Thu Jan 22 22:51:03 2004 +0000
+++ b/src/ChangeLog	Fri Jan 23 10:00:34 2004 +0000
@@ -1,3 +1,7 @@
+2004-01-23  Stephen J. Turnbull  <stephen@xemacs.org>
+
+	* specifier.c (Fvalid_specifier_type_p): Fix docstring typo.
+
 2003-12-29  Malcolm Purvis  <malcolmpurvis@optushome.com.au>
 
 	* sysdll.c (dll_function): Added support for finding symbols in
--- a/src/specifier.c	Thu Jan 22 22:51:03 2004 +0000
+++ b/src/specifier.c	Fri Jan 23 10:00:34 2004 +0000
@@ -459,7 +459,7 @@
 
 DEFUN ("valid-specifier-type-p", Fvalid_specifier_type_p, 1, 1, 0, /*
 Given a SPECIFIER-TYPE, return non-nil if it is valid.
-Valid types are 'generic, 'integer, boolean, 'color, 'font, 'image,
+Valid types are 'generic, 'integer, 'boolean, 'color, 'font, 'image,
 'face-boolean, and 'toolbar.
 */
        (specifier_type))