emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: custom type `color' is not enforced


From: Drew Adams
Subject: RE: custom type `color' is not enforced
Date: Thu, 20 Dec 2007 11:11:09 -0800

>     The `color' type, in particular, should be easy to test
>     (either the string is in the list of color names or it
>     satisfies `#' followed by three groups of hex digits).
>
>     Type `regexp' might be more difficult to test, but that too should be
>     possible, since we issue invalid-regexp errors for strings
>     that aren't valid regexps.
>
> I agree that these changes would be improvements.  However, I don't
> think we have any way to test the validity of a regexp without
> matching it, and matching it (even against a null string) could
> cause an infinite loop.

That could be, but `color' should be doable, at least. There might also be
other such type checks that could be done but are not.

>     I have, for instance, a command `describe-option-of-type'
>     (which I bind to `C-h M-o'). It is similar to `describe-variable',
>     but it lets you use defcustom types to narrow the set of
>     completion candidates.
>
> I have to say it doesn't sound tremendously useful.

I have to say "lack of imagination". ;-)

Don't assume that the user knows just which option s?he wants to describe.
`describe-variable' gives you only one way, by option name, to define a set
of candidate options, in order to pick one to describe. You can type a
prefix and hit TAB to see what the matching options are, but when there are
many with the same prefix that doesn't help much. You need to scan the list
looking for what might be the appropriate option, and some of the names in
the list might not be very suggestive. That can mean a lot of parsing and
thinking energy.

Obviously, with substring (not just prefix) matching, finding the right
option to describe is easier - you can match, say, `width' anywhere in the
option name, not just as a prefix. And if you can also match multiple
substrings, without regard to order, so much the better.

But you are still relying on only the option name, which (1) is not
necessarily efficient (there can still be many such matches) and (2) might
not work at all: you might not be thinking in terms of the same words that
are used in the option name.

Adding the ability to specify the option type increases your matching power
and thus your expressiveness and efficiency as a user.

For example, you might know that you want to examine or modify some
integer-valued option that controls how many chars are used for something.
You can try strings such as `char', `min', and `width' in the option name,
and you can also make it match the prefix `icicle-' to limit the search to
options in one package, but you will still be fishing in the dark to some
extent. Being able to also say that you know that the option is an integer
can narrow things down considerably.

Or suppose the option you are after is `Info-prefer-subnodes', and you can't
remember the name. You might be thinking in terms of `space', `menu',
`submenu', `depth-first', `navigate', and `traversal', but not in terms of
`subnode'. Matching against the `Info-' options gives you twice as many
candidates as matching against the `Info-' options that are boolean.

Same thing for other options where there are many with the same prefix and
the option name might not use terms you are thinking of - boolean options
`imenu-eager-completion-buffer' and `inverse-video', for example.

Similarly, if you want to customize an option, you can use
`customize-apropos-options', but you can often narrow things down better if
you use `customize-apropos-options-of-type' (another command I can offer).

>     `C-h M-o color RET TAB' correctly gives all options defined with :type
>     `color' (rigid equality test). However, since Emacs currently does not
>     distinguish type `color' from type `string' (= this bug),
>
> That statement surprises me.  The two types have different names, and
> don't behave the same, so in what sense does Emacs not distinguish
> them?

Please reread what I said: it _correctly_ gives all options defined with
`color', using a rigid equality test for the type. Where it breaks down is
"this bug": the fact that any string as the option value satisfies type
`color'.

The part you didn't quote explains this: Using `C-u' with `C-h M-o' tests
whether the current value of an option satisfies (is compatible with) type
`color' (in this case). And any string at all is deemed by Emacs to be of
type `color'. That's the missing feature or bug. If you don't use `C-u',
then you get a rigid equality test for the type, and that works OK, as far
as it goes.

`help-var-is-of-type-p' is the part of the code that `C-u' uses to test
whether the value is of the right type:

 (widget-apply (widget-convert type):match value)

And any string VALUE at all satisfies this test when TYPE is `color',
`string', or `regexp'.

The ability to look for options whose value is of the right type (i.e., via
`C-u' here) is all the more important in that there is not yet any treatment
of type comparison (beyond a rigid :type comparison with `equal') or of
subtyping (a `regexp' is a `string'; an `integer' is a `number').

With substring matching and using `C-u' with `C-h M-o', I can see candidate
options whose current value satisfies a `type' definition that includes
"string" - that means type definitions such as these:

(choice (string :tag "Show candidate plus a WYSIWYG swatch with text..."
                :value "MMMM")
        (const :tag "Show candidate itself using WYSIWYG" t)
        (const :tag "Show candidate as is, with no text properties" nil))

(repeat (list string (choice (const :tag "None" nil) (string :tag "Match
regexp")) (choice (const :tag "None" nil) (string :tag "No-match regexp"))
(choice (const :tag "None" nil) (function :tag "Predicate")) (choice (const
:tag "None" nil) (repeat (string :tag "Extra buffer"))) (choice (const :tag
"None" nil) (function :tag "Sort function"))))






reply via email to

[Prev in Thread] Current Thread [Next in Thread]